]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiDocument.cpp
Embedding: add option \extra_embedded_files to buffer params. This increase
[lyx.git] / src / frontends / qt4 / GuiDocument.cpp
1 /**
2  * \file GuiDocument.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Edwin Leuven
7  * \author Richard Heck (modules)
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "GuiDocument.h"
15
16 #include "LayoutFile.h"
17 #include "BranchList.h"
18 #include "buffer_funcs.h"
19 #include "Buffer.h"
20 #include "BufferParams.h"
21 #include "BufferView.h"
22 #include "Color.h"
23 #include "Encoding.h"
24 #include "FloatPlacement.h"
25 #include "FuncRequest.h"
26 #include "support/gettext.h"
27 #include "GuiBranches.h"
28 #include "Language.h"
29 #include "LaTeXFeatures.h"
30 #include "LaTeXHighlighter.h"
31 #include "Layout.h"
32 #include "LengthCombo.h"
33 #include "LyXRC.h" // defaultUnit
34 #include "ModuleList.h"
35 #include "OutputParams.h"
36 #include "PanelStack.h"
37 #include "PDFOptions.h"
38 #include "qt_helpers.h"
39 #include "Spacing.h"
40 #include "Validator.h"
41
42 #include "insets/InsetListingsParams.h"
43
44 #include "support/debug.h"
45 #include "support/FileName.h"
46 #include "support/FileFilterList.h"
47 #include "support/filetools.h"
48 #include "support/lstrings.h"
49
50 #include "frontends/alert.h"
51
52 #include <QCloseEvent>
53 #include <QScrollBar>
54 #include <QTextCursor>
55
56 #include <sstream>
57
58 using namespace std;
59 using namespace lyx::support;
60
61
62 namespace {
63
64 char const * const tex_graphics[] =
65 {
66         "default", "dvips", "dvitops", "emtex",
67         "ln", "oztex", "textures", "none", ""
68 };
69
70
71 char const * const tex_graphics_gui[] =
72 {
73         N_("Default"), "Dvips", "DVItoPS", "EmTeX",
74         "LN", "OzTeX", "Textures", N_("None"), ""
75 };
76
77
78 char const * const tex_fonts_roman[] =
79 {
80         "default", "cmr", "lmodern", "ae", "times", "palatino",
81         "charter", "newcent", "bookman", "utopia", "beraserif",
82         "ccfonts", "chancery", ""
83 };
84
85
86 char const * tex_fonts_roman_gui[] =
87 {
88         N_("Default"), N_("Computer Modern Roman"), N_("Latin Modern Roman"),
89         N_("AE (Almost European)"), N_("Times Roman"), N_("Palatino"),
90         N_("Bitstream Charter"), N_("New Century Schoolbook"), N_("Bookman"),
91         N_("Utopia"),  N_("Bera Serif"), N_("Concrete Roman"), N_("Zapf Chancery"),
92         ""
93 };
94
95
96 char const * const tex_fonts_sans[] =
97 {
98         "default", "cmss", "lmss", "helvet", "avant", "berasans", "cmbr", ""
99 };
100
101
102 char const * tex_fonts_sans_gui[] =
103 {
104         N_("Default"), N_("Computer Modern Sans"), N_("Latin Modern Sans"),
105         N_("Helvetica"), N_("Avant Garde"), N_("Bera Sans"), N_("CM Bright"), ""
106 };
107
108
109 char const * const tex_fonts_monospaced[] =
110 {
111         "default", "cmtt", "lmtt", "courier", "beramono", "luximono", "cmtl", ""
112 };
113
114
115 char const * tex_fonts_monospaced_gui[] =
116 {
117         N_("Default"), N_("Computer Modern Typewriter"),
118         N_("Latin Modern Typewriter"), N_("Courier"), N_("Bera Mono"),
119         N_("LuxiMono"), N_("CM Typewriter Light"), ""
120 };
121
122
123 vector<pair<string, lyx::docstring> > pagestyles;
124
125
126 } // anonymous namespace
127
128 namespace lyx {
129
130 namespace {
131 // used when sorting the textclass list.
132 class less_textclass_avail_desc
133         : public binary_function<string, string, int>
134 {
135 public:
136         int operator()(string const & lhs, string const & rhs) const
137         {
138                 // Ordering criteria:
139                 //   1. Availability of text class
140                 //   2. Description (lexicographic)
141                 LayoutFile const & tc1 = LayoutFileList::get()[lhs];
142                 LayoutFile const & tc2 = LayoutFileList::get()[rhs];
143                 return (tc1.isTeXClassAvailable() && !tc2.isTeXClassAvailable()) ||
144                         (tc1.isTeXClassAvailable() == tc2.isTeXClassAvailable() &&
145                          _(tc1.description()) < _(tc2.description()));
146         }
147 };
148
149 }
150
151 namespace frontend {
152
153
154 /// 
155 QModelIndex getSelectedIndex(QListView * lv)
156 {
157         QModelIndex retval = QModelIndex();
158         QModelIndexList selIdx = 
159                         lv->selectionModel()->selectedIndexes();
160         if (!selIdx.empty())
161                 retval = selIdx.first();
162         return retval;
163 }
164
165
166 namespace {
167         vector<string> getRequiredList(string const & modName) 
168         {
169                 LyXModule const * const mod = moduleList[modName];
170                 if (!mod)
171                         return vector<string>(); //empty such thing
172                 return mod->getRequiredModules();
173         }
174
175
176         vector<string> getExcludedList(string const & modName)
177         {
178                 LyXModule const * const mod = moduleList[modName];
179                 if (!mod)
180                         return vector<string>(); //empty such thing
181                 return mod->getExcludedModules();
182         }
183
184
185         docstring getModuleDescription(string const & modName)
186         {
187                 LyXModule const * const mod = moduleList[modName];
188                 if (!mod)
189                         return _("Module not found!");
190                 return _(mod->getDescription());
191         }
192
193
194         vector<string> getPackageList(string const & modName)
195         {
196                 LyXModule const * const mod = moduleList[modName];
197                 if (!mod)
198                         return vector<string>(); //empty such thing
199                 return mod->getPackageList();
200         }
201
202
203         bool isModuleAvailable(string const & modName)
204         {
205                 LyXModule * mod = moduleList[modName];
206                 if (!mod)
207                         return false;
208                 return mod->isAvailable();
209         }
210 } //anonymous namespace
211
212
213 ModuleSelMan::ModuleSelMan(
214         QListView * availableLV, 
215         QListView * selectedLV,
216         QPushButton * addPB, 
217         QPushButton * delPB, 
218         QPushButton * upPB, 
219         QPushButton * downPB,
220         GuiIdListModel * availableModel,
221         GuiIdListModel * selectedModel) :
222 GuiSelectionManager(availableLV, selectedLV, addPB, delPB,
223                     upPB, downPB, availableModel, selectedModel) 
224 {}
225         
226
227 void ModuleSelMan::updateAddPB() 
228 {
229         int const arows = availableModel->rowCount();
230         QModelIndexList const availSels = 
231                         availableLV->selectionModel()->selectedIndexes();
232         if (arows == 0 || availSels.isEmpty()  || isSelected(availSels.first())) {
233                 addPB->setEnabled(false);
234                 return;
235         }
236         
237         QModelIndex const & idx = availableLV->selectionModel()->currentIndex();
238         string const modName = getAvailableModel()->getIDString(idx.row());
239         vector<string> reqs = getRequiredList(modName);
240         vector<string> excl = getExcludedList(modName);
241         
242         if (reqs.empty() && excl.empty()) {
243                 addPB->setEnabled(true);
244                 return;
245         }
246
247         int const srows = selectedModel->rowCount();
248         vector<string> selModList;
249         for (int i = 0; i < srows; ++i)
250                 selModList.push_back(getSelectedModel()->getIDString(i));
251
252         vector<string>::const_iterator selModStart = selModList.begin();
253         vector<string>::const_iterator selModEnd   = selModList.end();
254         
255         //Check whether some required module is available
256         if (!reqs.empty()) {
257                 bool foundOne = false;
258                 vector<string>::const_iterator it  = reqs.begin();
259                 vector<string>::const_iterator end = reqs.end();
260                 for (; it != end; ++it) {
261                         if (find(selModStart, selModEnd, *it) != selModEnd) {
262                                 foundOne = true;
263                                 break;
264                         }
265                 }
266                 if (!foundOne) {
267                         addPB->setEnabled(false);
268                         return;
269                 }
270         }
271         
272         //Check whether any excluded module is being used
273         if (!excl.empty()) {
274                 vector<string>::const_iterator it  = excl.begin();
275                 vector<string>::const_iterator end = excl.end();
276                 for (; it != end; ++it) {
277                         if (find(selModStart, selModEnd, *it) != selModEnd) {
278                                 addPB->setEnabled(false);
279                                 return;
280                         }
281                 }
282         }
283
284         addPB->setEnabled(true);
285 }
286
287
288 void ModuleSelMan::updateDownPB()
289 {
290         int const srows = selectedModel->rowCount();
291         if (srows == 0) {
292                 downPB->setEnabled(false);
293                 return;
294         }
295         QModelIndexList const selSels = 
296                         selectedLV->selectionModel()->selectedIndexes();
297         //disable if empty or last item is selected
298         if (selSels.empty() || selSels.first().row() == srows - 1) {
299                 downPB->setEnabled(false);
300                 return;
301         }
302         //determine whether immediately succeding element requires this one
303         QModelIndex const & curIdx = selectedLV->selectionModel()->currentIndex();
304         int curRow = curIdx.row();
305         if (curRow < 0 || curRow >= srows - 1) { //this shouldn't happen...
306                 downPB->setEnabled(false);
307                 return;
308         }
309         string const curModName = getSelectedModel()->getIDString(curRow);
310         string const nextModName = getSelectedModel()->getIDString(curRow + 1);
311
312         vector<string> reqs = getRequiredList(nextModName);
313
314         //if it doesn't require anything....
315         if (reqs.empty()) {
316                 downPB->setEnabled(true);
317                 return;
318         }
319
320         //FIXME This should perhaps be more flexible and check whether, even 
321         //if this one is required, there is also an earlier one that is required.
322         //enable it if this module isn't required
323         downPB->setEnabled(
324                         find(reqs.begin(), reqs.end(), curModName) == reqs.end());
325 }
326
327 void ModuleSelMan::updateUpPB() 
328 {
329         int const srows = selectedModel->rowCount();
330         if (srows == 0) {
331                 upPB->setEnabled(false);
332                 return;
333         }
334         QModelIndexList const selSels = 
335                         selectedLV->selectionModel()->selectedIndexes();
336         //disable if empty or first item is selected
337         if (selSels.empty() || selSels.first().row() == 0) {
338                 upPB->setEnabled(false);
339                 return;
340         }
341
342         //determine whether immediately preceding element is required by this one
343         QModelIndex const & curIdx = selectedLV->selectionModel()->currentIndex();
344         int curRow = curIdx.row();
345         if (curRow <= -1 || curRow > srows - 1) { //sanity check
346                 downPB->setEnabled(false);
347                 return;
348         }
349         string const curModName = getSelectedModel()->getIDString(curRow);
350         vector<string> reqs = getRequiredList(curModName);
351         
352         //if this one doesn't require anything....
353         if (reqs.empty()) {
354                 upPB->setEnabled(true);
355                 return;
356         }
357
358         string preModName = getSelectedModel()->getIDString(curRow - 1);
359
360         //NOTE This is less flexible than it might be. You could check whether, even 
361         //if this one is required, there is also an earlier one that is required.
362         //enable it if the preceding module isn't required
363         upPB->setEnabled(find(reqs.begin(), reqs.end(), preModName) == reqs.end());
364 }
365
366 void ModuleSelMan::updateDelPB() 
367 {
368         int const srows = selectedModel->rowCount();
369         if (srows == 0) {
370                 deletePB->setEnabled(false);
371                 return;
372         }
373         QModelIndexList const selSels = 
374                         selectedLV->selectionModel()->selectedIndexes();
375         if (selSels.empty() || selSels.first().row() < 0) {
376                 deletePB->setEnabled(false);
377                 return;
378         }
379         
380         //determine whether some LATER module requires this one
381         //NOTE Things are arranged so that this is the only way there
382         //can be a problem. At least, we hope so.
383         QModelIndex const & curIdx = 
384                 selectedLV->selectionModel()->currentIndex();
385         int const curRow = curIdx.row();
386         if (curRow < 0 || curRow >= srows) { //this shouldn't happen
387                 deletePB->setEnabled(false);
388                 return;
389         }
390                 
391         QString const curModName = curIdx.data().toString();
392         
393         //We're looking here for a reason NOT to enable the button. If we
394         //find one, we disable it and return. If we don't, we'll end up at
395         //the end of the function, and then we enable it.
396         for (int i = curRow + 1; i < srows; ++i) {
397                 string const thisMod = getSelectedModel()->getIDString(i);
398                 vector<string> reqs = getRequiredList(thisMod);
399                 //does this one require us?
400                 if (find(reqs.begin(), reqs.end(), fromqstr(curModName)) == reqs.end())
401                         //no...
402                         continue;
403
404                 //OK, so this module requires us
405                 //is there an EARLIER module that also satisfies the require?
406                 //NOTE We demand that it be earlier to keep the list of modules
407                 //consistent with the rule that a module must be proceeded by a
408                 //required module. There would be more flexible ways to proceed,
409                 //but that would be a lot more complicated, and the logic here is
410                 //already complicated. (That's why I've left the debugging code.)
411                 //lyxerr << "Testing " << thisMod << std::endl;
412                 bool foundOne = false;
413                 for (int j = 0; j < curRow; ++j) {
414                         string const mod = getSelectedModel()->getIDString(j);
415                         //lyxerr << "In loop: Testing " << mod << std::endl;
416                         //do we satisfy the require? 
417                         if (find(reqs.begin(), reqs.end(), mod) != reqs.end()) {
418                                 //lyxerr << mod << " does the trick." << std::endl;
419                                 foundOne = true;
420                                 break;
421                         }
422                 }
423                 //did we find a module to satisfy the require?
424                 if (!foundOne) {
425                         //lyxerr << "No matching module found." << std::endl;
426                         deletePB->setEnabled(false);
427                         return;
428                 }
429         }
430         //lyxerr << "All's well that ends well." << std::endl;  
431         deletePB->setEnabled(true);
432 }
433
434
435 /////////////////////////////////////////////////////////////////////
436 //
437 // PreambleModule
438 //
439 /////////////////////////////////////////////////////////////////////
440
441 PreambleModule::PreambleModule(): current_id_(0)
442 {
443         // This is not a memory leak. The object will be destroyed
444         // with this.
445         (void) new LaTeXHighlighter(preambleTE->document());
446         setFocusProxy(preambleTE);
447         connect(preambleTE, SIGNAL(textChanged()), this, SIGNAL(changed()));
448 }
449
450
451 void PreambleModule::update(BufferParams const & params, BufferId id)
452 {
453         QString preamble = toqstr(params.preamble);
454         // Nothing to do if the params and preamble are unchanged.
455         if (id == current_id_
456                 && preamble == preambleTE->document()->toPlainText())
457                 return;
458
459         QTextCursor cur = preambleTE->textCursor();
460         // Save the coords before switching to the new one.
461         preamble_coords_[current_id_] =
462                 make_pair(cur.position(), preambleTE->verticalScrollBar()->value());
463
464         // Save the params address for further use.
465         current_id_ = id;
466         preambleTE->document()->setPlainText(preamble);
467         Coords::const_iterator it = preamble_coords_.find(current_id_);
468         if (it == preamble_coords_.end())
469                 // First time we open this one.
470                 preamble_coords_[current_id_] = make_pair(0,0);
471         else {
472                 // Restore saved coords.
473                 QTextCursor cur = preambleTE->textCursor();
474                 cur.setPosition(it->second.first);
475                 preambleTE->setTextCursor(cur);
476                 preambleTE->verticalScrollBar()->setValue(it->second.second);
477         }
478 }
479
480
481 void PreambleModule::apply(BufferParams & params)
482 {
483         params.preamble = fromqstr(preambleTE->document()->toPlainText());
484 }
485
486
487 void PreambleModule::closeEvent(QCloseEvent * e)
488 {
489         // Save the coords before closing.
490         QTextCursor cur = preambleTE->textCursor();
491         preamble_coords_[current_id_] =
492                 make_pair(cur.position(), preambleTE->verticalScrollBar()->value());
493         e->accept();
494 }
495
496
497 /////////////////////////////////////////////////////////////////////
498 //
499 // DocumentDialog
500 //
501 /////////////////////////////////////////////////////////////////////
502
503
504 GuiDocument::GuiDocument(GuiView & lv)
505         : GuiDialog(lv, "document", qt_("Document Settings")), current_id_(0)
506 {
507         setupUi(this);
508
509         QList<LanguagePair> langs = languageData(false);        
510         for (int i = 0; i != langs.size(); ++i)
511                 lang_.append(langs[i].second);
512
513         connect(okPB, SIGNAL(clicked()), this, SLOT(slotOK()));
514         connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
515         connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
516         connect(restorePB, SIGNAL(clicked()), this, SLOT(slotRestore()));
517
518         connect(savePB, SIGNAL(clicked()), this, SLOT(saveDefaultClicked()));
519         connect(defaultPB, SIGNAL(clicked()), this, SLOT(useDefaultsClicked()));
520
521         // Manage the restore, ok, apply, restore and cancel/close buttons
522         bc().setPolicy(ButtonPolicy::NoRepeatedApplyReadOnlyPolicy);
523         bc().setOK(okPB);
524         bc().setApply(applyPB);
525         bc().setCancel(closePB);
526         bc().setRestore(restorePB);
527
528         textLayoutModule = new UiWidget<Ui::TextLayoutUi>;
529         // text layout
530         connect(textLayoutModule->lspacingCO, SIGNAL(activated(int)),
531                 this, SLOT(change_adaptor()));
532         connect(textLayoutModule->lspacingCO, SIGNAL(activated(int)),
533                 this, SLOT(setLSpacing(int)));
534         connect(textLayoutModule->lspacingLE, SIGNAL(textChanged(const QString &)),
535                 this, SLOT(change_adaptor()));
536         connect(textLayoutModule->skipRB, SIGNAL(clicked()),
537                 this, SLOT(change_adaptor()));
538         connect(textLayoutModule->indentRB, SIGNAL(clicked()),
539                 this, SLOT(change_adaptor()));
540         connect(textLayoutModule->skipCO, SIGNAL(activated(int)),
541                 this, SLOT(change_adaptor()));
542         connect(textLayoutModule->skipLE, SIGNAL(textChanged(const QString &)),
543                 this, SLOT(change_adaptor()));
544         connect(textLayoutModule->skipLengthCO, SIGNAL(activated(int)),
545                 this, SLOT(change_adaptor()));
546         connect(textLayoutModule->skipCO, SIGNAL(activated(int)),
547                 this, SLOT(setSkip(int)));
548         connect(textLayoutModule->skipRB, SIGNAL(toggled(bool)),
549                 this, SLOT(enableSkip(bool)));
550         connect(textLayoutModule->twoColumnCB, SIGNAL(clicked()),
551                 this, SLOT(change_adaptor()));
552         connect(textLayoutModule->twoColumnCB, SIGNAL(clicked()),
553                 this, SLOT(setColSep()));
554         connect(textLayoutModule->listingsED, SIGNAL(textChanged()),
555                 this, SLOT(change_adaptor()));
556         connect(textLayoutModule->bypassCB, SIGNAL(clicked()), 
557                 this, SLOT(change_adaptor()));
558         connect(textLayoutModule->bypassCB, SIGNAL(clicked()), 
559                 this, SLOT(set_listings_msg()));
560         connect(textLayoutModule->listingsED, SIGNAL(textChanged()),
561                 this, SLOT(set_listings_msg()));
562         textLayoutModule->listingsTB->setPlainText(
563                 qt_("Input listings parameters on the right. Enter ? for a list of parameters."));
564         textLayoutModule->lspacingLE->setValidator(new QDoubleValidator(
565                 textLayoutModule->lspacingLE));
566         textLayoutModule->skipLE->setValidator(unsignedLengthValidator(
567                 textLayoutModule->skipLE));
568
569         textLayoutModule->skipCO->addItem(qt_("SmallSkip"));
570         textLayoutModule->skipCO->addItem(qt_("MedSkip"));
571         textLayoutModule->skipCO->addItem(qt_("BigSkip"));
572         textLayoutModule->skipCO->addItem(qt_("Length"));
573         // remove the %-items from the unit choice
574         textLayoutModule->skipLengthCO->noPercents();
575         textLayoutModule->lspacingCO->insertItem(
576                 Spacing::Single, qt_("Single"));
577         textLayoutModule->lspacingCO->insertItem(
578                 Spacing::Onehalf, qt_("OneHalf"));
579         textLayoutModule->lspacingCO->insertItem(
580                 Spacing::Double, qt_("Double"));
581         textLayoutModule->lspacingCO->insertItem(
582                 Spacing::Other, qt_("Custom"));
583
584         // initialize the length validator
585         bc().addCheckedLineEdit(textLayoutModule->skipLE);
586
587         fontModule = new UiWidget<Ui::FontUi>;
588         // fonts
589         connect(fontModule->fontsRomanCO, SIGNAL(activated(int)),
590                 this, SLOT(change_adaptor()));
591         connect(fontModule->fontsRomanCO, SIGNAL(activated(int)),
592                 this, SLOT(romanChanged(int)));
593         connect(fontModule->fontsSansCO, SIGNAL(activated(int)),
594                 this, SLOT(change_adaptor()));
595         connect(fontModule->fontsSansCO, SIGNAL(activated(int)),
596                 this, SLOT(sansChanged(int)));
597         connect(fontModule->fontsTypewriterCO, SIGNAL(activated(int)),
598                 this, SLOT(change_adaptor()));
599         connect(fontModule->fontsTypewriterCO, SIGNAL(activated(int)),
600                 this, SLOT(ttChanged(int)));
601         connect(fontModule->fontsDefaultCO, SIGNAL(activated(int)),
602                 this, SLOT(change_adaptor()));
603         connect(fontModule->fontsizeCO, SIGNAL(activated(int)),
604                 this, SLOT(change_adaptor()));
605         connect(fontModule->scaleSansSB, SIGNAL(valueChanged(int)),
606                 this, SLOT(change_adaptor()));
607         connect(fontModule->scaleTypewriterSB, SIGNAL(valueChanged(int)),
608                 this, SLOT(change_adaptor()));
609         connect(fontModule->fontScCB, SIGNAL(clicked()),
610                 this, SLOT(change_adaptor()));
611         connect(fontModule->fontOsfCB, SIGNAL(clicked()),
612                 this, SLOT(change_adaptor()));
613
614         for (int n = 0; tex_fonts_roman[n][0]; ++n) {
615                 QString font = qt_(tex_fonts_roman_gui[n]);
616                 if (!isFontAvailable(tex_fonts_roman[n]))
617                         font += qt_(" (not installed)");
618                 fontModule->fontsRomanCO->addItem(font);
619         }
620         for (int n = 0; tex_fonts_sans[n][0]; ++n) {
621                 QString font = qt_(tex_fonts_sans_gui[n]);
622                 if (!isFontAvailable(tex_fonts_sans[n]))
623                         font += qt_(" (not installed)");
624                 fontModule->fontsSansCO->addItem(font);
625         }
626         for (int n = 0; tex_fonts_monospaced[n][0]; ++n) {
627                 QString font = qt_(tex_fonts_monospaced_gui[n]);
628                 if (!isFontAvailable(tex_fonts_monospaced[n]))
629                         font += qt_(" (not installed)");
630                 fontModule->fontsTypewriterCO->addItem(font);
631         }
632
633         fontModule->fontsizeCO->addItem(qt_("Default"));
634         fontModule->fontsizeCO->addItem(qt_("10"));
635         fontModule->fontsizeCO->addItem(qt_("11"));
636         fontModule->fontsizeCO->addItem(qt_("12"));
637
638         for (int n = 0; GuiDocument::fontfamilies_gui[n][0]; ++n)
639                 fontModule->fontsDefaultCO->addItem(
640                         qt_(GuiDocument::fontfamilies_gui[n]));
641
642
643         pageLayoutModule = new UiWidget<Ui::PageLayoutUi>;
644         // page layout
645         connect(pageLayoutModule->papersizeCO, SIGNAL(activated(int)),
646                 this, SLOT(setCustomPapersize(int)));
647         connect(pageLayoutModule->papersizeCO, SIGNAL(activated(int)),
648                 this, SLOT(setCustomPapersize(int)));
649         connect(pageLayoutModule->portraitRB, SIGNAL(clicked()),
650                 this, SLOT(portraitChanged()));
651         connect(pageLayoutModule->papersizeCO, SIGNAL(activated(int)),
652                 this, SLOT(change_adaptor()));
653         connect(pageLayoutModule->paperheightLE, SIGNAL(textChanged(const QString &)),
654                 this, SLOT(change_adaptor()));
655         connect(pageLayoutModule->paperwidthLE, SIGNAL(textChanged(const QString &)),
656                 this, SLOT(change_adaptor()));
657         connect(pageLayoutModule->paperwidthUnitCO, SIGNAL(activated(int)),
658                 this, SLOT(change_adaptor()));
659         connect(pageLayoutModule->paperheightUnitCO, SIGNAL(activated(int)),
660                 this, SLOT(change_adaptor()));
661         connect(pageLayoutModule->portraitRB, SIGNAL(clicked()),
662                 this, SLOT(change_adaptor()));
663         connect(pageLayoutModule->landscapeRB, SIGNAL(clicked()),
664                 this, SLOT(change_adaptor()));
665         connect(pageLayoutModule->facingPagesCB, SIGNAL(clicked()),
666                 this, SLOT(change_adaptor()));
667         connect(pageLayoutModule->pagestyleCO, SIGNAL(activated(int)),
668                 this, SLOT(change_adaptor()));
669
670         pageLayoutModule->pagestyleCO->addItem(qt_("Default"));
671         pageLayoutModule->pagestyleCO->addItem(qt_("empty"));
672         pageLayoutModule->pagestyleCO->addItem(qt_("plain"));
673         pageLayoutModule->pagestyleCO->addItem(qt_("headings"));
674         pageLayoutModule->pagestyleCO->addItem(qt_("fancy"));
675         bc().addCheckedLineEdit(pageLayoutModule->paperheightLE,
676                 pageLayoutModule->paperheightL);
677         bc().addCheckedLineEdit(pageLayoutModule->paperwidthLE,
678                 pageLayoutModule->paperwidthL);
679
680         // paper
681         QComboBox * cb = pageLayoutModule->papersizeCO;
682         cb->addItem(qt_("Default"));
683         cb->addItem(qt_("Custom"));
684         cb->addItem(qt_("US letter"));
685         cb->addItem(qt_("US legal"));
686         cb->addItem(qt_("US executive"));
687         cb->addItem(qt_("A3"));
688         cb->addItem(qt_("A4"));
689         cb->addItem(qt_("A5"));
690         cb->addItem(qt_("B3"));
691         cb->addItem(qt_("B4"));
692         cb->addItem(qt_("B5"));
693         // remove the %-items from the unit choice
694         pageLayoutModule->paperwidthUnitCO->noPercents();
695         pageLayoutModule->paperheightUnitCO->noPercents();
696         pageLayoutModule->paperheightLE->setValidator(unsignedLengthValidator(
697                 pageLayoutModule->paperheightLE));
698         pageLayoutModule->paperwidthLE->setValidator(unsignedLengthValidator(
699                 pageLayoutModule->paperwidthLE));
700
701
702         marginsModule = new UiWidget<Ui::MarginsUi>;
703         // margins
704         connect(marginsModule->marginCB, SIGNAL(toggled(bool)),
705                 this, SLOT(setCustomMargins(bool)));
706         connect(marginsModule->marginCB, SIGNAL(clicked()),
707                 this, SLOT(change_adaptor()));
708         connect(marginsModule->topLE, SIGNAL(textChanged(const QString &)),
709                 this, SLOT(change_adaptor()));
710         connect(marginsModule->topUnit, SIGNAL(activated(int)),
711                 this, SLOT(change_adaptor()));
712         connect(marginsModule->bottomLE, SIGNAL(textChanged(const QString &)),
713                 this, SLOT(change_adaptor()));
714         connect(marginsModule->bottomUnit, SIGNAL(activated(int)),
715                 this, SLOT(change_adaptor()));
716         connect(marginsModule->innerLE, SIGNAL(textChanged(const QString &)),
717                 this, SLOT(change_adaptor()));
718         connect(marginsModule->innerUnit, SIGNAL(activated(int)),
719                 this, SLOT(change_adaptor()));
720         connect(marginsModule->outerLE, SIGNAL(textChanged(const QString &)),
721                 this, SLOT(change_adaptor()));
722         connect(marginsModule->outerUnit, SIGNAL(activated(int)),
723                 this, SLOT(change_adaptor()));
724         connect(marginsModule->headheightLE, SIGNAL(textChanged(const QString &)),
725                 this, SLOT(change_adaptor()));
726         connect(marginsModule->headheightUnit, SIGNAL(activated(int)),
727                 this, SLOT(change_adaptor()));
728         connect(marginsModule->headsepLE, SIGNAL(textChanged(const QString &)),
729                 this, SLOT(change_adaptor()));
730         connect(marginsModule->headsepUnit, SIGNAL(activated(int)),
731                 this, SLOT(change_adaptor()));
732         connect(marginsModule->footskipLE, SIGNAL(textChanged(const QString&)),
733                 this, SLOT(change_adaptor()));
734         connect(marginsModule->footskipUnit, SIGNAL(activated(int)),
735                 this, SLOT(change_adaptor()));
736         connect(marginsModule->columnsepLE, SIGNAL(textChanged(const QString&)),
737                 this, SLOT(change_adaptor()));
738         connect(marginsModule->columnsepUnit, SIGNAL(activated(int)),
739                 this, SLOT(change_adaptor()));
740         marginsModule->topLE->setValidator(unsignedLengthValidator(
741                 marginsModule->topLE));
742         marginsModule->bottomLE->setValidator(unsignedLengthValidator(
743                 marginsModule->bottomLE));
744         marginsModule->innerLE->setValidator(unsignedLengthValidator(
745                 marginsModule->innerLE));
746         marginsModule->outerLE->setValidator(unsignedLengthValidator(
747                 marginsModule->outerLE));
748         marginsModule->headsepLE->setValidator(unsignedLengthValidator(
749                 marginsModule->headsepLE));
750         marginsModule->headheightLE->setValidator(unsignedLengthValidator(
751                 marginsModule->headheightLE));
752         marginsModule->footskipLE->setValidator(unsignedLengthValidator(
753                 marginsModule->footskipLE));
754         marginsModule->columnsepLE->setValidator(unsignedLengthValidator(
755                 marginsModule->columnsepLE));
756
757         bc().addCheckedLineEdit(marginsModule->topLE,
758                 marginsModule->topL);
759         bc().addCheckedLineEdit(marginsModule->bottomLE,
760                 marginsModule->bottomL);
761         bc().addCheckedLineEdit(marginsModule->innerLE,
762                 marginsModule->innerL);
763         bc().addCheckedLineEdit(marginsModule->outerLE,
764                 marginsModule->outerL);
765         bc().addCheckedLineEdit(marginsModule->headsepLE,
766                 marginsModule->headsepL);
767         bc().addCheckedLineEdit(marginsModule->headheightLE,
768                 marginsModule->headheightL);
769         bc().addCheckedLineEdit(marginsModule->footskipLE,
770                 marginsModule->footskipL);
771         bc().addCheckedLineEdit(marginsModule->columnsepLE,
772                 marginsModule->columnsepL);
773
774
775         langModule = new UiWidget<Ui::LanguageUi>;
776         // language & quote
777         connect(langModule->languageCO, SIGNAL(activated(int)),
778                 this, SLOT(change_adaptor()));
779         connect(langModule->defaultencodingRB, SIGNAL(clicked()),
780                 this, SLOT(change_adaptor()));
781         connect(langModule->otherencodingRB, SIGNAL(clicked()),
782                 this, SLOT(change_adaptor()));
783         connect(langModule->encodingCO, SIGNAL(activated(int)),
784                 this, SLOT(change_adaptor()));
785         connect(langModule->quoteStyleCO, SIGNAL(activated(int)),
786                 this, SLOT(change_adaptor()));
787         // language & quotes
788
789         QList<LanguagePair>::const_iterator lit  = langs.begin();
790         QList<LanguagePair>::const_iterator lend = langs.end();
791         for (; lit != lend; ++lit)
792                 langModule->languageCO->addItem(lit->first);
793
794         // Always put the default encoding in the first position.
795         // It is special because the displayed text is translated.
796         langModule->encodingCO->addItem(qt_("LaTeX default"));
797         Encodings::const_iterator it = encodings.begin();
798         Encodings::const_iterator const end = encodings.end();
799         for (; it != end; ++it)
800                 langModule->encodingCO->addItem(toqstr(it->latexName()));
801
802         langModule->quoteStyleCO->addItem(qt_("``text''"));
803         langModule->quoteStyleCO->addItem(qt_("''text''"));
804         langModule->quoteStyleCO->addItem(qt_(",,text``"));
805         langModule->quoteStyleCO->addItem(qt_(",,text''"));
806         langModule->quoteStyleCO->addItem(qt_("<<text>>"));
807         langModule->quoteStyleCO->addItem(qt_(">>text<<"));
808
809
810         numberingModule = new UiWidget<Ui::NumberingUi>;
811         // numbering
812         connect(numberingModule->depthSL, SIGNAL(valueChanged(int)),
813                 this, SLOT(change_adaptor()));
814         connect(numberingModule->tocSL, SIGNAL(valueChanged(int)),
815                 this, SLOT(change_adaptor()));
816         connect(numberingModule->depthSL, SIGNAL(valueChanged(int)),
817                 this, SLOT(updateNumbering()));
818         connect(numberingModule->tocSL, SIGNAL(valueChanged(int)),
819                 this, SLOT(updateNumbering()));
820         numberingModule->tocTW->setColumnCount(3);
821         numberingModule->tocTW->headerItem()->setText(0, qt_("Example"));
822         numberingModule->tocTW->headerItem()->setText(1, qt_("Numbered"));
823         numberingModule->tocTW->headerItem()->setText(2, qt_("Appears in TOC"));
824
825
826         biblioModule = new UiWidget<Ui::BiblioUi>;
827         connect(biblioModule->citeNatbibRB, SIGNAL(toggled(bool)),
828                 biblioModule->citationStyleL, SLOT(setEnabled(bool)));
829         connect(biblioModule->citeNatbibRB, SIGNAL(toggled(bool)),
830                 biblioModule->citeStyleCO, SLOT(setEnabled(bool)));
831         // biblio
832         connect(biblioModule->citeDefaultRB, SIGNAL(clicked()),
833                 this, SLOT(change_adaptor()));
834         connect(biblioModule->citeNatbibRB, SIGNAL(clicked()),
835                 this, SLOT(change_adaptor()));
836         connect(biblioModule->citeStyleCO, SIGNAL(activated(int)),
837                 this, SLOT(change_adaptor()));
838         connect(biblioModule->citeJurabibRB, SIGNAL(clicked()),
839                 this, SLOT(change_adaptor()));
840         connect(biblioModule->bibtopicCB, SIGNAL(clicked()),
841                 this, SLOT(change_adaptor()));
842         // biblio
843         biblioModule->citeStyleCO->addItem(qt_("Author-year"));
844         biblioModule->citeStyleCO->addItem(qt_("Numerical"));
845         biblioModule->citeStyleCO->setCurrentIndex(0);
846
847
848         mathsModule = new UiWidget<Ui::MathsUi>;
849         connect(mathsModule->amsautoCB, SIGNAL(toggled(bool)),
850                 mathsModule->amsCB, SLOT(setDisabled(bool)));
851         connect(mathsModule->esintautoCB, SIGNAL(toggled(bool)),
852                 mathsModule->esintCB, SLOT(setDisabled(bool)));
853         // maths
854         connect(mathsModule->amsCB, SIGNAL(clicked()),
855                 this, SLOT(change_adaptor()));
856         connect(mathsModule->amsautoCB, SIGNAL(clicked()),
857                 this, SLOT(change_adaptor()));
858         connect(mathsModule->esintCB, SIGNAL(clicked()),
859                 this, SLOT(change_adaptor()));
860         connect(mathsModule->esintautoCB, SIGNAL(clicked()),
861                 this, SLOT(change_adaptor()));
862
863         latexModule = new UiWidget<Ui::LaTeXUi>;
864         // latex class
865         connect(latexModule->optionsLE, SIGNAL(textChanged(const QString &)),
866                 this, SLOT(change_adaptor()));
867         connect(latexModule->psdriverCO, SIGNAL(activated(int)),
868                 this, SLOT(change_adaptor()));
869         connect(latexModule->classCO, SIGNAL(activated(int)),
870                 this, SLOT(classChanged()));
871         connect(latexModule->classCO, SIGNAL(activated(int)),
872                 this, SLOT(change_adaptor()));
873         
874         selectionManager = 
875                 new ModuleSelMan(latexModule->availableLV, latexModule->selectedLV, 
876                         latexModule->addPB, latexModule->deletePB, 
877                         latexModule->upPB, latexModule->downPB, 
878                         availableModel(), selectedModel());
879         connect(selectionManager, SIGNAL(updateHook()),
880                 this, SLOT(updateModuleInfo()));
881         connect(selectionManager, SIGNAL(updateHook()),
882                 this, SLOT(change_adaptor()));
883         
884         // postscript drivers
885         for (int n = 0; tex_graphics[n][0]; ++n) {
886                 QString enc = qt_(tex_graphics_gui[n]);
887                 latexModule->psdriverCO->addItem(enc);
888         }
889         // latex classes
890         latexModule->classCO->setModel(&classes_model_);
891         LayoutFileList const & bcl = LayoutFileList::get();
892         vector<LayoutFileIndex> classList = bcl.classList();
893         sort(classList.begin(), classList.end(), less_textclass_avail_desc());
894
895         vector<LayoutFileIndex>::const_iterator cit  = classList.begin();
896         vector<LayoutFileIndex>::const_iterator cen = classList.end();
897         for (int i = 0; cit != cen; ++cit, ++i) {
898                 LayoutFile const & tc = bcl[*cit];
899                 docstring item = (tc.isTeXClassAvailable()) ?
900                         from_utf8(tc.description()) :
901                         bformat(_("Unavailable: %1$s"), from_utf8(tc.description()));
902                 classes_model_.insertRow(i, toqstr(item), *cit);
903         }
904
905         // branches
906         branchesModule = new GuiBranches;
907         connect(branchesModule, SIGNAL(changed()),
908                 this, SLOT(change_adaptor()));
909
910         // preamble
911         preambleModule = new PreambleModule;
912         connect(preambleModule, SIGNAL(changed()),
913                 this, SLOT(change_adaptor()));
914
915         // bullets
916         bulletsModule = new BulletsModule;
917         connect(bulletsModule, SIGNAL(changed()),
918                 this, SLOT(change_adaptor()));
919
920         // embedded files
921         embeddedFilesModule = new UiWidget<Ui::EmbeddedFilesUi>;
922         connect(embeddedFilesModule->addPB, SIGNAL(clicked()),
923                 this, SLOT(addExtraEmbeddedFile()));
924         connect(embeddedFilesModule->removePB, SIGNAL(clicked()),
925                 this, SLOT(removeExtraEmbeddedFile()));
926
927         // PDF support
928         pdfSupportModule = new UiWidget<Ui::PDFSupportUi>;
929
930         connect(pdfSupportModule->use_hyperrefGB, SIGNAL(toggled(bool)),
931                 this, SLOT(change_adaptor()));
932         connect(pdfSupportModule->titleLE, SIGNAL(textChanged(const QString &)),
933                 this, SLOT(change_adaptor()));
934         connect(pdfSupportModule->authorLE, SIGNAL(textChanged(const QString &)),
935                 this, SLOT(change_adaptor()));
936         connect(pdfSupportModule->subjectLE, SIGNAL(textChanged(const QString &)),
937                 this, SLOT(change_adaptor()));
938         connect(pdfSupportModule->keywordsLE, SIGNAL(textChanged(const QString &)),
939                 this, SLOT(change_adaptor()));
940         connect(pdfSupportModule->bookmarksGB, SIGNAL(toggled(bool)),
941                 this, SLOT(change_adaptor()));
942         connect(pdfSupportModule->bookmarksnumberedCB, SIGNAL(toggled(bool)),
943                 this, SLOT(change_adaptor()));
944         connect(pdfSupportModule->bookmarksopenGB, SIGNAL(toggled(bool)),
945                 this, SLOT(change_adaptor()));
946         connect(pdfSupportModule->bookmarksopenlevelSB, SIGNAL(valueChanged(int)),
947                 this, SLOT(change_adaptor()));
948         connect(pdfSupportModule->breaklinksCB, SIGNAL(toggled(bool)),
949                 this, SLOT(change_adaptor()));
950         connect(pdfSupportModule->pdfborderCB, SIGNAL(toggled(bool)),
951                 this, SLOT(change_adaptor()));
952         connect(pdfSupportModule->colorlinksCB, SIGNAL(toggled(bool)),
953                 this, SLOT(change_adaptor()));
954         connect(pdfSupportModule->backrefCB, SIGNAL(toggled(bool)),
955                 this, SLOT(change_adaptor()));
956         connect(pdfSupportModule->pdfusetitleCB, SIGNAL(toggled(bool)),
957                 this, SLOT(change_adaptor()));
958         connect(pdfSupportModule->pagebackrefCB, SIGNAL(toggled(bool)),
959                 this, SLOT(change_adaptor()));
960         connect(pdfSupportModule->fullscreenCB, SIGNAL(toggled(bool)),
961                 this, SLOT(change_adaptor()));
962         connect(pdfSupportModule->optionsLE, SIGNAL(textChanged(const QString &)),
963                 this, SLOT(change_adaptor()));
964
965         // float
966         floatModule = new FloatPlacement;
967         connect(floatModule, SIGNAL(changed()),
968                 this, SLOT(change_adaptor()));
969
970         docPS->addPanel(latexModule, qt_("Document Class"));
971         docPS->addPanel(fontModule, qt_("Fonts"));
972         docPS->addPanel(textLayoutModule, qt_("Text Layout"));
973         docPS->addPanel(pageLayoutModule, qt_("Page Layout"));
974         docPS->addPanel(marginsModule, qt_("Page Margins"));
975         docPS->addPanel(langModule, qt_("Language"));
976         docPS->addPanel(numberingModule, qt_("Numbering & TOC"));
977         docPS->addPanel(biblioModule, qt_("Bibliography"));
978         docPS->addPanel(pdfSupportModule, qt_("PDF Properties"));
979         docPS->addPanel(mathsModule, qt_("Math Options"));
980         docPS->addPanel(floatModule, qt_("Float Placement"));
981         docPS->addPanel(bulletsModule, qt_("Bullets"));
982         docPS->addPanel(branchesModule, qt_("Branches"));
983         docPS->addPanel(embeddedFilesModule, qt_("Embedded Files"));
984         docPS->addPanel(preambleModule, qt_("LaTeX Preamble"));
985         docPS->setCurrentPanel(qt_("Document Class"));
986 // FIXME: hack to work around resizing bug in Qt >= 4.2
987 // bug verified with Qt 4.2.{0-3} (JSpitzm)
988 #if QT_VERSION >= 0x040200
989         docPS->updateGeometry();
990 #endif
991 }
992
993
994 void GuiDocument::showPreamble()
995 {
996         docPS->setCurrentPanel(qt_("LaTeX Preamble"));
997 }
998
999
1000 void GuiDocument::saveDefaultClicked()
1001 {
1002         saveDocDefault();
1003 }
1004
1005
1006 void GuiDocument::useDefaultsClicked()
1007 {
1008         useClassDefaults();
1009 }
1010
1011
1012 void GuiDocument::change_adaptor()
1013 {
1014         changed();
1015 }
1016
1017
1018 docstring GuiDocument::validate_listings_params()
1019 {
1020         // use a cache here to avoid repeated validation
1021         // of the same parameters
1022         static string param_cache = string();
1023         static docstring msg_cache = docstring();
1024         
1025         if (textLayoutModule->bypassCB->isChecked())
1026                 return docstring();
1027
1028         string params = fromqstr(textLayoutModule->listingsED->toPlainText());
1029         if (params != param_cache) {
1030                 param_cache = params;
1031                 msg_cache = InsetListingsParams(params).validate();
1032         }
1033         return msg_cache;
1034 }
1035
1036
1037 void GuiDocument::set_listings_msg()
1038 {
1039         static bool isOK = true;
1040         docstring msg = validate_listings_params();
1041         if (msg.empty()) {
1042                 if (isOK)
1043                         return;
1044                 isOK = true;
1045                 // listingsTB->setTextColor("black");
1046                 textLayoutModule->listingsTB->setPlainText(
1047                         qt_("Input listings parameters on the right. Enter ? for a list of parameters."));
1048         } else {
1049                 isOK = false;
1050                 // listingsTB->setTextColor("red");
1051                 textLayoutModule->listingsTB->setPlainText(toqstr(msg));
1052         }
1053 }
1054
1055
1056 void GuiDocument::setLSpacing(int item)
1057 {
1058         textLayoutModule->lspacingLE->setEnabled(item == 3);
1059 }
1060
1061
1062 void GuiDocument::setSkip(int item)
1063 {
1064         bool const enable = (item == 3);
1065         textLayoutModule->skipLE->setEnabled(enable);
1066         textLayoutModule->skipLengthCO->setEnabled(enable);
1067 }
1068
1069
1070 void GuiDocument::enableSkip(bool skip)
1071 {
1072         textLayoutModule->skipCO->setEnabled(skip);
1073         textLayoutModule->skipLE->setEnabled(skip);
1074         textLayoutModule->skipLengthCO->setEnabled(skip);
1075         if (skip)
1076                 setSkip(textLayoutModule->skipCO->currentIndex());
1077 }
1078
1079 void GuiDocument::portraitChanged()
1080 {
1081         setMargins(pageLayoutModule->papersizeCO->currentIndex());
1082 }
1083
1084 void GuiDocument::setMargins(bool custom)
1085 {
1086         marginsModule->marginCB->setChecked(custom);
1087         setCustomMargins(custom);
1088 }
1089
1090
1091 void GuiDocument::setCustomPapersize(int papersize)
1092 {
1093         bool const custom = (papersize == 1);
1094
1095         pageLayoutModule->paperwidthL->setEnabled(custom);
1096         pageLayoutModule->paperwidthLE->setEnabled(custom);
1097         pageLayoutModule->paperwidthUnitCO->setEnabled(custom);
1098         pageLayoutModule->paperheightL->setEnabled(custom);
1099         pageLayoutModule->paperheightLE->setEnabled(custom);
1100         pageLayoutModule->paperheightLE->setFocus();
1101         pageLayoutModule->paperheightUnitCO->setEnabled(custom);
1102 }
1103
1104
1105 void GuiDocument::setColSep()
1106 {
1107         setCustomMargins(marginsModule->marginCB->checkState() == Qt::Checked);
1108 }
1109
1110
1111 void GuiDocument::setCustomMargins(bool custom)
1112 {
1113         marginsModule->topL->setEnabled(!custom);
1114         marginsModule->topLE->setEnabled(!custom);
1115         marginsModule->topUnit->setEnabled(!custom);
1116
1117         marginsModule->bottomL->setEnabled(!custom);
1118         marginsModule->bottomLE->setEnabled(!custom);
1119         marginsModule->bottomUnit->setEnabled(!custom);
1120
1121         marginsModule->innerL->setEnabled(!custom);
1122         marginsModule->innerLE->setEnabled(!custom);
1123         marginsModule->innerUnit->setEnabled(!custom);
1124
1125         marginsModule->outerL->setEnabled(!custom);
1126         marginsModule->outerLE->setEnabled(!custom);
1127         marginsModule->outerUnit->setEnabled(!custom);
1128
1129         marginsModule->headheightL->setEnabled(!custom);
1130         marginsModule->headheightLE->setEnabled(!custom);
1131         marginsModule->headheightUnit->setEnabled(!custom);
1132
1133         marginsModule->headsepL->setEnabled(!custom);
1134         marginsModule->headsepLE->setEnabled(!custom);
1135         marginsModule->headsepUnit->setEnabled(!custom);
1136
1137         marginsModule->footskipL->setEnabled(!custom);
1138         marginsModule->footskipLE->setEnabled(!custom);
1139         marginsModule->footskipUnit->setEnabled(!custom);
1140
1141         bool const enableColSep = !custom && 
1142                         textLayoutModule->twoColumnCB->checkState() == Qt::Checked;
1143         marginsModule->columnsepL->setEnabled(enableColSep);
1144         marginsModule->columnsepLE->setEnabled(enableColSep);
1145         marginsModule->columnsepUnit->setEnabled(enableColSep);
1146 }
1147
1148
1149 void GuiDocument::updateFontsize(string const & items, string const & sel)
1150 {
1151         fontModule->fontsizeCO->clear();
1152         fontModule->fontsizeCO->addItem(qt_("Default"));
1153
1154         for (int n = 0; !token(items,'|',n).empty(); ++n)
1155                 fontModule->fontsizeCO->
1156                         addItem(toqstr(token(items,'|',n)));
1157
1158         for (int n = 0; n < fontModule->fontsizeCO->count(); ++n) {
1159                 if (fromqstr(fontModule->fontsizeCO->itemText(n)) == sel) {
1160                         fontModule->fontsizeCO->setCurrentIndex(n);
1161                         break;
1162                 }
1163         }
1164 }
1165
1166
1167 void GuiDocument::romanChanged(int item)
1168 {
1169         string const font = tex_fonts_roman[item];
1170         fontModule->fontScCB->setEnabled(providesSC(font));
1171         fontModule->fontOsfCB->setEnabled(providesOSF(font));
1172 }
1173
1174
1175 void GuiDocument::sansChanged(int item)
1176 {
1177         string const font = tex_fonts_sans[item];
1178         bool scaleable = providesScale(font);
1179         fontModule->scaleSansSB->setEnabled(scaleable);
1180         fontModule->scaleSansLA->setEnabled(scaleable);
1181 }
1182
1183
1184 void GuiDocument::ttChanged(int item)
1185 {
1186         string const font = tex_fonts_monospaced[item];
1187         bool scaleable = providesScale(font);
1188         fontModule->scaleTypewriterSB->setEnabled(scaleable);
1189         fontModule->scaleTypewriterLA->setEnabled(scaleable);
1190 }
1191
1192
1193 void GuiDocument::updatePagestyle(string const & items, string const & sel)
1194 {
1195         pagestyles.clear();
1196         pageLayoutModule->pagestyleCO->clear();
1197         pageLayoutModule->pagestyleCO->addItem(qt_("Default"));
1198
1199         for (int n = 0; !token(items,'|',n).empty(); ++n) {
1200                 string style = token(items, '|', n);
1201                 docstring style_gui = _(style);
1202                 pagestyles.push_back(pair<string, docstring>(style, style_gui));
1203                 pageLayoutModule->pagestyleCO->addItem(toqstr(style_gui));
1204         }
1205
1206         if (sel == "default") {
1207                 pageLayoutModule->pagestyleCO->setCurrentIndex(0);
1208                 return;
1209         }
1210
1211         int nn = 0;
1212
1213         for (size_t i = 0; i < pagestyles.size(); ++i)
1214                 if (pagestyles[i].first == sel)
1215                         nn = pageLayoutModule->pagestyleCO->findText(
1216                                         toqstr(pagestyles[i].second));
1217
1218         if (nn > 0)
1219                 pageLayoutModule->pagestyleCO->setCurrentIndex(nn);
1220 }
1221
1222
1223 void GuiDocument::classChanged()
1224 {
1225         int idx = latexModule->classCO->currentIndex();
1226         if (idx < 0) 
1227                 return;
1228         string const classname = classes_model_.getIDString(idx);
1229         // check if this is a local layout file
1230         if (prefixIs(classname, LayoutFileList::localPrefix)) {
1231                 int const ret = Alert::prompt(_("Local layout file"),
1232                                 _("The layout file you have selected is a local layout\n"
1233                                   "file, not one in the system or user directory. Your\n"
1234                                   "document may not work with this layout if you do not\n"
1235                                   "keep the layout file in the same directory."),
1236                                   1, 1, _("&Set Layout"), _("&Cancel"));
1237                 if (ret == 1) {
1238                         // try to reset the layout combo
1239                         setLayoutComboByIDString(bp_.baseClassID());
1240                         return;
1241                 }
1242         }
1243         if (!bp_.setBaseClass(classname)) {
1244                 Alert::error(_("Error"), _("Unable to set document class."));
1245                 return;
1246         }
1247         if (lyxrc.auto_reset_options) {
1248                 if (applyPB->isEnabled()) {
1249                         int const ret = Alert::prompt(_("Unapplied changes"),
1250                                         _("Some changes in the dialog were not yet applied.\n"
1251                                         "If you do not apply now, they will be lost after this action."),
1252                                         1, 1, _("&Apply"), _("&Dismiss"));
1253                         if (ret == 0)
1254                                 applyView();
1255                 }
1256                 bp_.useClassDefaults();
1257                 forceUpdate();
1258         }
1259 }
1260
1261
1262 namespace {
1263         // This is an insanely complicated attempt to make this sort of thing
1264         // work with RTL languages.
1265         docstring formatStrVec(vector<string> const & v, docstring const & s) 
1266         {
1267                 //this mess formats the list as "v[0], v[1], ..., [s] v[n]"
1268                 int const vSize = v.size();
1269                 if (v.size() == 0)
1270                         return docstring();
1271                 else if (v.size() == 1) 
1272                         return from_ascii(v[0]);
1273                 else if (v.size() == 2) {
1274                         docstring retval = _("%1$s and %2$s");
1275                         retval = subst(retval, _("and"), s);
1276                         return bformat(retval, from_ascii(v[0]), from_ascii(v[1]));
1277                 }
1278                 //The idea here is to format all but the last two items...
1279                 docstring t2 = _("%1$s, %2$s");
1280                 docstring retval = from_ascii(v[0]);
1281                 for (int i = 1; i < vSize - 2; ++i)
1282                         retval = bformat(t2, retval, from_ascii(v[i])); 
1283                 //...and then to  plug them, and the last two, into this schema
1284                 docstring t = _("%1$s, %2$s, and %3$s");
1285                 t = subst(t, _("and"), s);
1286                 return bformat(t, retval, from_ascii(v[vSize - 2]), from_ascii(v[vSize - 1]));
1287         }
1288         
1289         vector<string> idsToNames(vector<string> const & idList)
1290         {
1291                 vector<string> retval;
1292                 vector<string>::const_iterator it  = idList.begin();
1293                 vector<string>::const_iterator end = idList.end();
1294                 for (; it != end; ++it) {
1295                         LyXModule const * const mod = moduleList[*it];
1296                         if (!mod)
1297                                 retval.push_back(*it + " (Unavailable)");
1298                         else
1299                                 retval.push_back(mod->getName());
1300                 }
1301                 return retval;
1302         }
1303 }
1304
1305
1306 void GuiDocument::updateModuleInfo()
1307 {
1308         selectionManager->update();
1309         
1310         //Module description
1311         bool const focusOnSelected = selectionManager->selectedFocused();
1312         QListView const * const lv = 
1313                         focusOnSelected ? latexModule->selectedLV : latexModule->availableLV;
1314         if (lv->selectionModel()->selectedIndexes().isEmpty()) {
1315                 latexModule->infoML->document()->clear();
1316                 return;
1317         }
1318         QModelIndex const & idx = lv->selectionModel()->currentIndex();
1319         GuiIdListModel const & idModel = 
1320                         focusOnSelected  ? modules_sel_model_ : modules_av_model_;
1321         string const modName = idModel.getIDString(idx.row());
1322         docstring desc = getModuleDescription(modName);
1323
1324         vector<string> pkgList = getPackageList(modName);
1325         docstring pkgdesc = formatStrVec(pkgList, _("and"));
1326         if (!pkgdesc.empty()) {
1327                 if (!desc.empty())
1328                         desc += "\n";
1329                 desc += bformat(_("Package(s) required: %1$s."), pkgdesc);
1330         }
1331
1332         pkgList = getRequiredList(modName);
1333         if (!pkgList.empty()) {
1334                 vector<string> const reqDescs = idsToNames(pkgList);
1335                 pkgdesc = formatStrVec(reqDescs, _("or"));
1336                 if (!desc.empty())
1337                         desc += "\n";
1338                 desc += bformat(_("Module required: %1$s."), pkgdesc);
1339         }
1340
1341         pkgList = getExcludedList(modName);
1342         if (!pkgList.empty()) {
1343                 vector<string> const reqDescs = idsToNames(pkgList);
1344                 pkgdesc = formatStrVec(reqDescs, _( "and"));
1345                 if (!desc.empty())
1346                         desc += "\n";
1347                 desc += bformat(_("Modules excluded: %1$s."), pkgdesc);
1348         }
1349
1350         if (!isModuleAvailable(modName)) {
1351                 if (!desc.empty())
1352                         desc += "\n";
1353                 desc += _("WARNING: Some packages are unavailable!");
1354         }
1355
1356         latexModule->infoML->document()->setPlainText(toqstr(desc));
1357 }
1358
1359
1360 void GuiDocument::setExtraEmbeddedFileList()
1361 {
1362         embeddedFilesModule->extraLW->clear();
1363         // add current embedded files
1364         vector<string> const & files = buffer().params().extraEmbeddedFiles();
1365         vector<string>::const_iterator fit = files.begin();
1366         vector<string>::const_iterator fit_end = files.end();
1367         for (; fit != fit_end; ++fit)
1368                 embeddedFilesModule->extraLW->addItem(toqstr(*fit));
1369 }
1370
1371
1372 void GuiDocument::addExtraEmbeddedFile()
1373 {
1374         QString file = browseRelFile(QString(), bufferFilepath(),
1375                 qt_("Extra embedded file"), FileFilterList(), true);
1376
1377         if (embeddedFilesModule->extraLW->findItems(file, Qt::MatchExactly).empty())
1378                 embeddedFilesModule->extraLW->addItem(file);
1379 }
1380
1381
1382 void GuiDocument::removeExtraEmbeddedFile()
1383 {
1384         int index = embeddedFilesModule->extraLW->currentRow();
1385         delete embeddedFilesModule->extraLW->takeItem(index);
1386 }
1387
1388
1389 void GuiDocument::updateNumbering()
1390 {
1391         DocumentClass const & tclass = bp_.documentClass();
1392
1393         numberingModule->tocTW->setUpdatesEnabled(false);
1394         numberingModule->tocTW->clear();
1395
1396         int const depth = numberingModule->depthSL->value();
1397         int const toc = numberingModule->tocSL->value();
1398         QString const no = qt_("No");
1399         QString const yes = qt_("Yes");
1400         QTreeWidgetItem * item = 0;
1401
1402         DocumentClass::const_iterator lit = tclass.begin();
1403         DocumentClass::const_iterator len = tclass.end();
1404         for (; lit != len; ++lit) {
1405                 int const toclevel = lit->toclevel;
1406                 if (toclevel != Layout::NOT_IN_TOC && lit->labeltype == LABEL_COUNTER) {
1407                         item = new QTreeWidgetItem(numberingModule->tocTW);
1408                         item->setText(0, toqstr(translateIfPossible(lit->name())));
1409                         item->setText(1, (toclevel <= depth) ? yes : no);
1410                         item->setText(2, (toclevel <= toc) ? yes : no);
1411                 }
1412         }
1413
1414         numberingModule->tocTW->setUpdatesEnabled(true);
1415         numberingModule->tocTW->update();
1416 }
1417
1418
1419 void GuiDocument::apply(BufferParams & params)
1420 {
1421         // preamble
1422         preambleModule->apply(params);
1423
1424         // biblio
1425         params.setCiteEngine(biblio::ENGINE_BASIC);
1426
1427         if (biblioModule->citeNatbibRB->isChecked()) {
1428                 bool const use_numerical_citations =
1429                         biblioModule->citeStyleCO->currentIndex();
1430                 if (use_numerical_citations)
1431                         params.setCiteEngine(biblio::ENGINE_NATBIB_NUMERICAL);
1432                 else
1433                         params.setCiteEngine(biblio::ENGINE_NATBIB_AUTHORYEAR);
1434
1435         } else if (biblioModule->citeJurabibRB->isChecked())
1436                 params.setCiteEngine(biblio::ENGINE_JURABIB);
1437
1438         params.use_bibtopic =
1439                 biblioModule->bibtopicCB->isChecked();
1440
1441         // language & quotes
1442         if (langModule->defaultencodingRB->isChecked()) {
1443                 params.inputenc = "auto";
1444         } else {
1445                 int i = langModule->encodingCO->currentIndex();
1446                 if (i == 0)
1447                         params.inputenc = "default";
1448                 else
1449                         params.inputenc =
1450                                 fromqstr(langModule->encodingCO->currentText());
1451         }
1452
1453         InsetQuotes::quote_language lga = InsetQuotes::EnglishQ;
1454         switch (langModule->quoteStyleCO->currentIndex()) {
1455         case 0:
1456                 lga = InsetQuotes::EnglishQ;
1457                 break;
1458         case 1:
1459                 lga = InsetQuotes::SwedishQ;
1460                 break;
1461         case 2:
1462                 lga = InsetQuotes::GermanQ;
1463                 break;
1464         case 3:
1465                 lga = InsetQuotes::PolishQ;
1466                 break;
1467         case 4:
1468                 lga = InsetQuotes::FrenchQ;
1469                 break;
1470         case 5:
1471                 lga = InsetQuotes::DanishQ;
1472                 break;
1473         }
1474         params.quotes_language = lga;
1475
1476         int const pos = langModule->languageCO->currentIndex();
1477         params.language = lyx::languages.getLanguage(fromqstr(lang_[pos]));
1478
1479         // numbering
1480         if (params.documentClass().hasTocLevels()) {
1481                 params.tocdepth = numberingModule->tocSL->value();
1482                 params.secnumdepth = numberingModule->depthSL->value();
1483         }
1484
1485         // bullets
1486         params.user_defined_bullet(0) = bulletsModule->getBullet(0);
1487         params.user_defined_bullet(1) = bulletsModule->getBullet(1);
1488         params.user_defined_bullet(2) = bulletsModule->getBullet(2);
1489         params.user_defined_bullet(3) = bulletsModule->getBullet(3);
1490
1491         // packages
1492         params.graphicsDriver =
1493                 tex_graphics[latexModule->psdriverCO->currentIndex()];
1494         
1495         // text layout
1496         int idx = latexModule->classCO->currentIndex();
1497         if (idx >= 0) {
1498                 string const classname = classes_model_.getIDString(idx);
1499                 params.setBaseClass(classname);
1500         }
1501
1502         // Modules
1503         params.clearLayoutModules();
1504         int const srows = modules_sel_model_.rowCount();
1505         vector<string> selModList;
1506         for (int i = 0; i < srows; ++i)
1507                 params.addLayoutModule(modules_sel_model_.getIDString(i));
1508
1509         if (mathsModule->amsautoCB->isChecked()) {
1510                 params.use_amsmath = BufferParams::package_auto;
1511         } else {
1512                 if (mathsModule->amsCB->isChecked())
1513                         params.use_amsmath = BufferParams::package_on;
1514                 else
1515                         params.use_amsmath = BufferParams::package_off;
1516         }
1517
1518         if (mathsModule->esintautoCB->isChecked())
1519                 params.use_esint = BufferParams::package_auto;
1520         else {
1521                 if (mathsModule->esintCB->isChecked())
1522                         params.use_esint = BufferParams::package_on;
1523                 else
1524                         params.use_esint = BufferParams::package_off;
1525         }
1526
1527         if (pageLayoutModule->pagestyleCO->currentIndex() == 0)
1528                 params.pagestyle = "default";
1529         else {
1530                 docstring style_gui =
1531                         qstring_to_ucs4(pageLayoutModule->pagestyleCO->currentText());
1532                 for (size_t i = 0; i < pagestyles.size(); ++i)
1533                         if (pagestyles[i].second == style_gui)
1534                                 params.pagestyle = pagestyles[i].first;
1535         }
1536
1537         switch (textLayoutModule->lspacingCO->currentIndex()) {
1538         case 0:
1539                 params.spacing().set(Spacing::Single);
1540                 break;
1541         case 1:
1542                 params.spacing().set(Spacing::Onehalf);
1543                 break;
1544         case 2:
1545                 params.spacing().set(Spacing::Double);
1546                 break;
1547         case 3:
1548                 params.spacing().set(Spacing::Other,
1549                         fromqstr(textLayoutModule->lspacingLE->text()));
1550                 break;
1551         }
1552
1553         if (textLayoutModule->twoColumnCB->isChecked())
1554                 params.columns = 2;
1555         else
1556                 params.columns = 1;
1557
1558         // text should have passed validation
1559         params.listings_params =
1560                 InsetListingsParams(fromqstr(textLayoutModule->listingsED->toPlainText())).params();
1561
1562         if (textLayoutModule->indentRB->isChecked())
1563                 params.paragraph_separation = BufferParams::PARSEP_INDENT;
1564         else
1565                 params.paragraph_separation = BufferParams::PARSEP_SKIP;
1566
1567         switch (textLayoutModule->skipCO->currentIndex()) {
1568         case 0:
1569                 params.setDefSkip(VSpace(VSpace::SMALLSKIP));
1570                 break;
1571         case 1:
1572                 params.setDefSkip(VSpace(VSpace::MEDSKIP));
1573                 break;
1574         case 2:
1575                 params.setDefSkip(VSpace(VSpace::BIGSKIP));
1576                 break;
1577         case 3:
1578         {
1579                 VSpace vs = VSpace(
1580                         widgetsToLength(textLayoutModule->skipLE,
1581                                 textLayoutModule->skipLengthCO)
1582                         );
1583                 params.setDefSkip(vs);
1584                 break;
1585         }
1586         default:
1587                 // DocumentDefskipCB assures that this never happens
1588                 // so Assert then !!!  - jbl
1589                 params.setDefSkip(VSpace(VSpace::MEDSKIP));
1590                 break;
1591         }
1592
1593         params.options =
1594                 fromqstr(latexModule->optionsLE->text());
1595
1596         params.float_placement = floatModule->get();
1597
1598         // fonts
1599         params.fontsRoman =
1600                 tex_fonts_roman[fontModule->fontsRomanCO->currentIndex()];
1601
1602         params.fontsSans =
1603                 tex_fonts_sans[fontModule->fontsSansCO->currentIndex()];
1604
1605         params.fontsTypewriter =
1606                 tex_fonts_monospaced[fontModule->fontsTypewriterCO->currentIndex()];
1607
1608         params.fontsSansScale = fontModule->scaleSansSB->value();
1609
1610         params.fontsTypewriterScale = fontModule->scaleTypewriterSB->value();
1611
1612         params.fontsSC = fontModule->fontScCB->isChecked();
1613
1614         params.fontsOSF = fontModule->fontOsfCB->isChecked();
1615
1616         params.fontsDefaultFamily = GuiDocument::fontfamilies[
1617                 fontModule->fontsDefaultCO->currentIndex()];
1618
1619         if (fontModule->fontsizeCO->currentIndex() == 0)
1620                 params.fontsize = "default";
1621         else
1622                 params.fontsize =
1623                         fromqstr(fontModule->fontsizeCO->currentText());
1624
1625         // paper
1626         params.papersize = PAPER_SIZE(
1627                 pageLayoutModule->papersizeCO->currentIndex());
1628
1629         // custom, A3, B3 and B4 paper sizes need geometry
1630         int psize = pageLayoutModule->papersizeCO->currentIndex();
1631         bool geom_papersize = (psize == 1 || psize == 5 || psize == 8 || psize == 9);
1632
1633         params.paperwidth = widgetsToLength(pageLayoutModule->paperwidthLE,
1634                 pageLayoutModule->paperwidthUnitCO);
1635
1636         params.paperheight = widgetsToLength(pageLayoutModule->paperheightLE,
1637                 pageLayoutModule->paperheightUnitCO);
1638
1639         if (pageLayoutModule->facingPagesCB->isChecked())
1640                 params.sides = TwoSides;
1641         else
1642                 params.sides = OneSide;
1643
1644         if (pageLayoutModule->landscapeRB->isChecked())
1645                 params.orientation = ORIENTATION_LANDSCAPE;
1646         else
1647                 params.orientation = ORIENTATION_PORTRAIT;
1648
1649         // margins
1650         params.use_geometry = !marginsModule->marginCB->isChecked()
1651                 || geom_papersize;
1652
1653         Ui::MarginsUi const * m = marginsModule;
1654
1655         params.leftmargin = widgetsToLength(m->innerLE, m->innerUnit);
1656         params.topmargin = widgetsToLength(m->topLE, m->topUnit);
1657         params.rightmargin = widgetsToLength(m->outerLE, m->outerUnit);
1658         params.bottommargin = widgetsToLength(m->bottomLE, m->bottomUnit);
1659         params.headheight = widgetsToLength(m->headheightLE, m->headheightUnit);
1660         params.headsep = widgetsToLength(m->headsepLE, m->headsepUnit);
1661         params.footskip = widgetsToLength(m->footskipLE, m->footskipUnit);
1662         params.columnsep = widgetsToLength(m->columnsepLE, m->columnsepUnit);
1663
1664         branchesModule->apply(params);
1665
1666         // PDF support
1667         PDFOptions & pdf = params.pdfoptions();
1668         pdf.use_hyperref = pdfSupportModule->use_hyperrefGB->isChecked();
1669         pdf.title = fromqstr(pdfSupportModule->titleLE->text());
1670         pdf.author = fromqstr(pdfSupportModule->authorLE->text());
1671         pdf.subject = fromqstr(pdfSupportModule->subjectLE->text());
1672         pdf.keywords = fromqstr(pdfSupportModule->keywordsLE->text());
1673
1674         pdf.bookmarks = pdfSupportModule->bookmarksGB->isChecked();
1675         pdf.bookmarksnumbered = pdfSupportModule->bookmarksnumberedCB->isChecked();
1676         pdf.bookmarksopen = pdfSupportModule->bookmarksopenGB->isChecked();
1677         pdf.bookmarksopenlevel = pdfSupportModule->bookmarksopenlevelSB->value();
1678
1679         pdf.breaklinks = pdfSupportModule->breaklinksCB->isChecked();
1680         pdf.pdfborder = pdfSupportModule->pdfborderCB->isChecked();
1681         pdf.pdfusetitle = pdfSupportModule->pdfusetitleCB->isChecked();
1682         pdf.colorlinks = pdfSupportModule->colorlinksCB->isChecked();
1683         pdf.backref = pdfSupportModule->backrefCB->isChecked();
1684         pdf.pagebackref = pdfSupportModule->pagebackrefCB->isChecked();
1685         if (pdfSupportModule->fullscreenCB->isChecked())
1686                 pdf.pagemode = pdf.pagemode_fullscreen;
1687         else
1688                 pdf.pagemode.clear();
1689         pdf.quoted_options = pdf.quoted_options_check(
1690                                 fromqstr(pdfSupportModule->optionsLE->text()));
1691
1692         // Embedded files
1693         vector<string> & files = params.extraEmbeddedFiles();
1694         files.clear();
1695         for (size_t i = 0; i < embeddedFilesModule->extraLW->count(); ++i) {
1696                 QListWidgetItem * item = embeddedFilesModule->extraLW->item(i);
1697                 files.push_back(fromqstr(item->text()));
1698         }
1699 }
1700
1701
1702 static int findPos(QStringList const & vec, QString const & val)
1703 {
1704         for (int i = 0; i != vec.size(); ++i)
1705                 if (vec[i] == val)
1706                         return i;
1707         return 0;
1708 }
1709
1710
1711 void GuiDocument::updateParams()
1712 {
1713         updateParams(bp_);
1714 }
1715
1716
1717 void GuiDocument::updateParams(BufferParams const & params)
1718 {
1719         // set the default unit
1720         Length::UNIT defaultUnit = Length::CM;
1721         switch (lyxrc.default_papersize) {
1722                 case PAPER_DEFAULT: break;
1723
1724                 case PAPER_USLETTER:
1725                 case PAPER_USLEGAL:
1726                 case PAPER_USEXECUTIVE:
1727                         defaultUnit = Length::IN;
1728                         break;
1729
1730                 case PAPER_A3:
1731                 case PAPER_A4:
1732                 case PAPER_A5:
1733                 case PAPER_B3:
1734                 case PAPER_B4:
1735                 case PAPER_B5:
1736                         defaultUnit = Length::CM;
1737                         break;
1738                 case PAPER_CUSTOM:
1739                         break;
1740         }
1741
1742         // preamble
1743         preambleModule->update(params, id());
1744
1745         // biblio
1746         biblioModule->citeDefaultRB->setChecked(
1747                 params.getEngine() == biblio::ENGINE_BASIC);
1748
1749         biblioModule->citeNatbibRB->setChecked(
1750                 params.getEngine() == biblio::ENGINE_NATBIB_NUMERICAL ||
1751                 params.getEngine() == biblio::ENGINE_NATBIB_AUTHORYEAR);
1752
1753         biblioModule->citeStyleCO->setCurrentIndex(
1754                 params.getEngine() == biblio::ENGINE_NATBIB_NUMERICAL);
1755
1756         biblioModule->citeJurabibRB->setChecked(
1757                 params.getEngine() == biblio::ENGINE_JURABIB);
1758
1759         biblioModule->bibtopicCB->setChecked(
1760                 params.use_bibtopic);
1761
1762         // language & quotes
1763         int const pos = findPos(lang_, toqstr(params.language->lang()));
1764         langModule->languageCO->setCurrentIndex(pos);
1765
1766         langModule->quoteStyleCO->setCurrentIndex(
1767                 params.quotes_language);
1768
1769         bool default_enc = true;
1770         if (params.inputenc != "auto") {
1771                 default_enc = false;
1772                 if (params.inputenc == "default") {
1773                         langModule->encodingCO->setCurrentIndex(0);
1774                 } else {
1775                         int const i = langModule->encodingCO->findText(
1776                                         toqstr(params.inputenc));
1777                         if (i >= 0)
1778                                 langModule->encodingCO->setCurrentIndex(i);
1779                         else
1780                                 // unknown encoding. Set to default.
1781                                 default_enc = true;
1782                 }
1783         }
1784         langModule->defaultencodingRB->setChecked(default_enc);
1785         langModule->otherencodingRB->setChecked(!default_enc);
1786
1787         // numbering
1788         int const min_toclevel = documentClass().min_toclevel();
1789         int const max_toclevel = documentClass().max_toclevel();
1790         if (documentClass().hasTocLevels()) {
1791                 numberingModule->setEnabled(true);
1792                 numberingModule->depthSL->setMinimum(min_toclevel - 1);
1793                 numberingModule->depthSL->setMaximum(max_toclevel);
1794                 numberingModule->depthSL->setValue(params.secnumdepth);
1795                 numberingModule->tocSL->setMaximum(min_toclevel - 1);
1796                 numberingModule->tocSL->setMaximum(max_toclevel);
1797                 numberingModule->tocSL->setValue(params.tocdepth);
1798                 updateNumbering();
1799         } else {
1800                 numberingModule->setEnabled(false);
1801                 numberingModule->tocTW->clear();
1802         }
1803
1804         // bullets
1805         bulletsModule->setBullet(0, params.user_defined_bullet(0));
1806         bulletsModule->setBullet(1, params.user_defined_bullet(1));
1807         bulletsModule->setBullet(2, params.user_defined_bullet(2));
1808         bulletsModule->setBullet(3, params.user_defined_bullet(3));
1809         bulletsModule->init();
1810
1811         // packages
1812         int nitem = findToken(tex_graphics, params.graphicsDriver);
1813         if (nitem >= 0)
1814                 latexModule->psdriverCO->setCurrentIndex(nitem);
1815         updateModuleInfo();
1816         
1817         mathsModule->amsCB->setChecked(
1818                 params.use_amsmath == BufferParams::package_on);
1819         mathsModule->amsautoCB->setChecked(
1820                 params.use_amsmath == BufferParams::package_auto);
1821
1822         mathsModule->esintCB->setChecked(
1823                 params.use_esint == BufferParams::package_on);
1824         mathsModule->esintautoCB->setChecked(
1825                 params.use_esint == BufferParams::package_auto);
1826
1827         switch (params.spacing().getSpace()) {
1828                 case Spacing::Other: nitem = 3; break;
1829                 case Spacing::Double: nitem = 2; break;
1830                 case Spacing::Onehalf: nitem = 1; break;
1831                 case Spacing::Default: case Spacing::Single: nitem = 0; break;
1832         }
1833
1834         // text layout
1835         string const & layoutID = params.baseClassID();
1836         setLayoutComboByIDString(layoutID);
1837
1838         updatePagestyle(documentClass().opt_pagestyle(),
1839                                  params.pagestyle);
1840
1841         textLayoutModule->lspacingCO->setCurrentIndex(nitem);
1842         if (params.spacing().getSpace() == Spacing::Other) {
1843                 textLayoutModule->lspacingLE->setText(
1844                         toqstr(params.spacing().getValueAsString()));
1845         }
1846         setLSpacing(nitem);
1847
1848         if (params.paragraph_separation == BufferParams::PARSEP_INDENT)
1849                 textLayoutModule->indentRB->setChecked(true);
1850         else
1851                 textLayoutModule->skipRB->setChecked(true);
1852
1853         int skip = 0;
1854         switch (params.getDefSkip().kind()) {
1855         case VSpace::SMALLSKIP:
1856                 skip = 0;
1857                 break;
1858         case VSpace::MEDSKIP:
1859                 skip = 1;
1860                 break;
1861         case VSpace::BIGSKIP:
1862                 skip = 2;
1863                 break;
1864         case VSpace::LENGTH:
1865         {
1866                 skip = 3;
1867                 string const length = params.getDefSkip().asLyXCommand();
1868                 lengthToWidgets(textLayoutModule->skipLE,
1869                         textLayoutModule->skipLengthCO,
1870                         length, defaultUnit);
1871                 break;
1872         }
1873         default:
1874                 skip = 0;
1875                 break;
1876         }
1877         textLayoutModule->skipCO->setCurrentIndex(skip);
1878         setSkip(skip);
1879
1880         textLayoutModule->twoColumnCB->setChecked(
1881                 params.columns == 2);
1882
1883         // break listings_params to multiple lines
1884         string lstparams =
1885                 InsetListingsParams(params.listings_params).separatedParams();
1886         textLayoutModule->listingsED->setPlainText(toqstr(lstparams));
1887
1888         if (!params.options.empty()) {
1889                 latexModule->optionsLE->setText(
1890                         toqstr(params.options));
1891         } else {
1892                 latexModule->optionsLE->setText(QString());
1893         }
1894
1895         floatModule->set(params.float_placement);
1896
1897         // Fonts
1898         updateFontsize(documentClass().opt_fontsize(),
1899                         params.fontsize);
1900
1901         int n = findToken(tex_fonts_roman, params.fontsRoman);
1902         if (n >= 0) {
1903                 fontModule->fontsRomanCO->setCurrentIndex(n);
1904                 romanChanged(n);
1905         }
1906
1907         n = findToken(tex_fonts_sans, params.fontsSans);
1908         if (n >= 0)     {
1909                 fontModule->fontsSansCO->setCurrentIndex(n);
1910                 sansChanged(n);
1911         }
1912
1913         n = findToken(tex_fonts_monospaced, params.fontsTypewriter);
1914         if (n >= 0) {
1915                 fontModule->fontsTypewriterCO->setCurrentIndex(n);
1916                 ttChanged(n);
1917         }
1918
1919         fontModule->fontScCB->setChecked(params.fontsSC);
1920         fontModule->fontOsfCB->setChecked(params.fontsOSF);
1921         fontModule->scaleSansSB->setValue(params.fontsSansScale);
1922         fontModule->scaleTypewriterSB->setValue(params.fontsTypewriterScale);
1923         n = findToken(GuiDocument::fontfamilies, params.fontsDefaultFamily);
1924         if (n >= 0)
1925                 fontModule->fontsDefaultCO->setCurrentIndex(n);
1926
1927         // paper
1928         int const psize = params.papersize;
1929         pageLayoutModule->papersizeCO->setCurrentIndex(psize);
1930         setCustomPapersize(psize);
1931
1932         bool const landscape =
1933                 params.orientation == ORIENTATION_LANDSCAPE;
1934         pageLayoutModule->landscapeRB->setChecked(landscape);
1935         pageLayoutModule->portraitRB->setChecked(!landscape);
1936
1937         pageLayoutModule->facingPagesCB->setChecked(
1938                 params.sides == TwoSides);
1939
1940
1941         lengthToWidgets(pageLayoutModule->paperwidthLE,
1942                 pageLayoutModule->paperwidthUnitCO, params.paperwidth, defaultUnit);
1943
1944         lengthToWidgets(pageLayoutModule->paperheightLE,
1945                 pageLayoutModule->paperheightUnitCO, params.paperheight, defaultUnit);
1946
1947         // margins
1948         Ui::MarginsUi * m = marginsModule;
1949
1950         setMargins(!params.use_geometry);
1951
1952         lengthToWidgets(m->topLE, m->topUnit,
1953                 params.topmargin, defaultUnit);
1954
1955         lengthToWidgets(m->bottomLE, m->bottomUnit,
1956                 params.bottommargin, defaultUnit);
1957
1958         lengthToWidgets(m->innerLE, m->innerUnit,
1959                 params.leftmargin, defaultUnit);
1960
1961         lengthToWidgets(m->outerLE, m->outerUnit,
1962                 params.rightmargin, defaultUnit);
1963
1964         lengthToWidgets(m->headheightLE, m->headheightUnit,
1965                 params.headheight, defaultUnit);
1966
1967         lengthToWidgets(m->headsepLE, m->headsepUnit,
1968                 params.headsep, defaultUnit);
1969
1970         lengthToWidgets(m->footskipLE, m->footskipUnit,
1971                 params.footskip, defaultUnit);
1972
1973         lengthToWidgets(m->columnsepLE, m->columnsepUnit,
1974                 params.columnsep, defaultUnit);
1975
1976         branchesModule->update(params);
1977
1978         // PDF support
1979         PDFOptions const & pdf = params.pdfoptions();
1980         pdfSupportModule->use_hyperrefGB->setChecked(pdf.use_hyperref);
1981         pdfSupportModule->titleLE->setText(toqstr(pdf.title));
1982         pdfSupportModule->authorLE->setText(toqstr(pdf.author));
1983         pdfSupportModule->subjectLE->setText(toqstr(pdf.subject));
1984         pdfSupportModule->keywordsLE->setText(toqstr(pdf.keywords));
1985
1986         pdfSupportModule->bookmarksGB->setChecked(pdf.bookmarks);
1987         pdfSupportModule->bookmarksnumberedCB->setChecked(pdf.bookmarksnumbered);
1988         pdfSupportModule->bookmarksopenGB->setChecked(pdf.bookmarksopen);
1989
1990         pdfSupportModule->bookmarksopenlevelSB->setValue(pdf.bookmarksopenlevel);
1991
1992         pdfSupportModule->breaklinksCB->setChecked(pdf.breaklinks);
1993         pdfSupportModule->pdfborderCB->setChecked(pdf.pdfborder);
1994         pdfSupportModule->pdfusetitleCB->setChecked(pdf.pdfusetitle);
1995         pdfSupportModule->colorlinksCB->setChecked(pdf.colorlinks);
1996         pdfSupportModule->backrefCB->setChecked(pdf.backref);
1997         pdfSupportModule->pagebackrefCB->setChecked(pdf.pagebackref);
1998         pdfSupportModule->fullscreenCB->setChecked
1999                 (pdf.pagemode == pdf.pagemode_fullscreen);
2000
2001         pdfSupportModule->optionsLE->setText(
2002                 toqstr(pdf.quoted_options));
2003         
2004         setExtraEmbeddedFileList();
2005 }
2006
2007
2008 void GuiDocument::applyView()
2009 {
2010         apply(params());
2011 }
2012
2013
2014 void GuiDocument::saveDocDefault()
2015 {
2016         // we have to apply the params first
2017         applyView();
2018         saveAsDefault();
2019 }
2020
2021
2022 void GuiDocument::updateAvailableModules() 
2023 {
2024         modules_av_model_.clear();
2025         vector<modInfoStruct> const modInfoList = getModuleInfo();
2026         int const mSize = modInfoList.size();
2027         for (int i = 0; i != mSize; ++i) {
2028                 modInfoStruct const & modInfo = modInfoList[i];
2029                 modules_av_model_.insertRow(i, qt_(modInfo.name), modInfo.id);
2030         }
2031 }
2032
2033
2034 void GuiDocument::updateSelectedModules() 
2035 {
2036         // and selected ones, too
2037         modules_sel_model_.clear();
2038         vector<modInfoStruct> const selModList = getSelectedModules();
2039         int const sSize = selModList.size();
2040         for (int i = 0; i != sSize; ++i) {
2041                 modInfoStruct const & modInfo = selModList[i];
2042                 modules_sel_model_.insertRow(i, qt_(modInfo.name), modInfo.id);
2043         }
2044 }
2045
2046
2047 void GuiDocument::updateContents()
2048 {
2049         if (id() == current_id_)
2050                 return;
2051
2052         updateAvailableModules();
2053         updateSelectedModules();
2054         
2055         //FIXME It'd be nice to make sure here that the selected
2056         //modules are consistent: That required modules are actually
2057         //selected, and that we don't have conflicts. If so, we could
2058         //at least pop up a warning.
2059         updateParams(bp_);
2060         current_id_ = id();
2061 }
2062
2063
2064 void GuiDocument::forceUpdate()
2065 {
2066         // reset to force dialog update
2067         current_id_ = 0;
2068         updateContents();
2069 }
2070
2071
2072 void GuiDocument::useClassDefaults()
2073 {
2074         if (applyPB->isEnabled()) {
2075                 int const ret = Alert::prompt(_("Unapplied changes"),
2076                                 _("Some changes in the dialog were not yet applied.\n"
2077                                   "If you do not apply now, they will be lost after this action."),
2078                                 1, 1, _("&Apply"), _("&Dismiss"));
2079                 if (ret == 0)
2080                         applyView();
2081         }
2082
2083         int idx = latexModule->classCO->currentIndex();
2084         string const classname = classes_model_.getIDString(idx);
2085         if (!bp_.setBaseClass(classname)) {
2086                 Alert::error(_("Error"), _("Unable to set document class."));
2087                 return;
2088         }
2089         bp_.useClassDefaults();
2090         forceUpdate();
2091 }
2092
2093
2094 void GuiDocument::setLayoutComboByIDString(std::string const & idString)
2095 {
2096         int idx = classes_model_.findIDString(idString);
2097         if (idx < 0)
2098                 Alert::warning(_("Can't set layout!"), 
2099                         bformat(_("Unable to set layout for ID: %1$s"), from_utf8(idString)));
2100         else 
2101                 latexModule->classCO->setCurrentIndex(idx);
2102 }
2103
2104
2105 bool GuiDocument::isValid()
2106 {
2107         return validate_listings_params().empty()
2108                 && (textLayoutModule->skipCO->currentIndex() != 3
2109                         || !textLayoutModule->skipLE->text().isEmpty());
2110 }
2111
2112
2113 char const * const GuiDocument::fontfamilies[5] = {
2114         "default", "rmdefault", "sfdefault", "ttdefault", ""
2115 };
2116
2117
2118 char const * GuiDocument::fontfamilies_gui[5] = {
2119         N_("Default"), N_("Roman"), N_("Sans Serif"), N_("Typewriter"), ""
2120 };
2121
2122
2123 bool GuiDocument::initialiseParams(string const &)
2124 {
2125         bp_ = buffer().params();
2126         loadModuleInfo();
2127         return true;
2128 }
2129
2130
2131 void GuiDocument::clearParams()
2132 {
2133         bp_ = BufferParams();
2134 }
2135
2136
2137 BufferId GuiDocument::id() const
2138 {
2139         return &buffer();
2140 }
2141
2142
2143 vector<GuiDocument::modInfoStruct> const & GuiDocument::getModuleInfo()
2144 {
2145         return moduleNames_;
2146 }
2147
2148
2149 vector<GuiDocument::modInfoStruct> const GuiDocument::getSelectedModules()
2150 {
2151         vector<string> const & mods = params().getModules();
2152         vector<string>::const_iterator it =  mods.begin();
2153         vector<string>::const_iterator end = mods.end();
2154         vector<modInfoStruct> mInfo;
2155         for (; it != end; ++it) {
2156                 modInfoStruct m;
2157                 m.id = *it;
2158                 LyXModule * mod = moduleList[*it];
2159                 if (mod)
2160                         m.name = mod->getName();
2161                 else 
2162                         m.name = *it + " (Not Found)";
2163                 mInfo.push_back(m);
2164         }
2165         return mInfo;
2166 }
2167
2168
2169 DocumentClass const & GuiDocument::documentClass() const
2170 {
2171         return bp_.documentClass();
2172 }
2173
2174
2175 static void dispatch_bufferparams(Dialog const & dialog,
2176         BufferParams const & bp, kb_action lfun)
2177 {
2178         ostringstream ss;
2179         ss << "\\begin_header\n";
2180         bp.writeFile(ss);
2181         ss << "\\end_header\n";
2182         dialog.dispatch(FuncRequest(lfun, ss.str()));
2183 }
2184
2185
2186 void GuiDocument::dispatchParams()
2187 {
2188         // This must come first so that a language change is correctly noticed
2189         setLanguage();
2190
2191         // Apply the BufferParams. Note that this will set the base class
2192         // and then update the buffer's layout.
2193         dispatch_bufferparams(*this, params(), LFUN_BUFFER_PARAMS_APPLY);
2194
2195         // Generate the colours requested by each new branch.
2196         BranchList & branchlist = params().branchlist();
2197         if (!branchlist.empty()) {
2198                 BranchList::const_iterator it = branchlist.begin();
2199                 BranchList::const_iterator const end = branchlist.end();
2200                 for (; it != end; ++it) {
2201                         docstring const & current_branch = it->getBranch();
2202                         Branch const * branch = branchlist.find(current_branch);
2203                         string const x11hexname = X11hexname(branch->getColor());
2204                         // display the new color
2205                         docstring const str = current_branch + ' ' + from_ascii(x11hexname);
2206                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
2207                 }
2208
2209                 // Open insets of selected branches, close deselected ones
2210                 dispatch(FuncRequest(LFUN_ALL_INSETS_TOGGLE,
2211                         "assign branch"));
2212         }
2213         // FIXME: If we used an LFUN, we would not need those two lines:
2214         bufferview()->processUpdateFlags(Update::Force | Update::FitCursor);
2215 }
2216
2217
2218 void GuiDocument::setLanguage() const
2219 {
2220         Language const * const newL = bp_.language;
2221         if (buffer().params().language == newL)
2222                 return;
2223
2224         string const & lang_name = newL->lang();
2225         dispatch(FuncRequest(LFUN_BUFFER_LANGUAGE, lang_name));
2226 }
2227
2228
2229 void GuiDocument::saveAsDefault() const
2230 {
2231         dispatch_bufferparams(*this, params(), LFUN_BUFFER_SAVE_AS_DEFAULT);
2232 }
2233
2234
2235 bool GuiDocument::isFontAvailable(string const & font) const
2236 {
2237         if (font == "default" || font == "cmr"
2238             || font == "cmss" || font == "cmtt")
2239                 // these are standard
2240                 return true;
2241         if (font == "lmodern" || font == "lmss" || font == "lmtt")
2242                 return LaTeXFeatures::isAvailable("lmodern");
2243         if (font == "times" || font == "palatino"
2244                  || font == "helvet" || font == "courier")
2245                 return LaTeXFeatures::isAvailable("psnfss");
2246         if (font == "cmbr" || font == "cmtl")
2247                 return LaTeXFeatures::isAvailable("cmbright");
2248         if (font == "utopia")
2249                 return LaTeXFeatures::isAvailable("utopia")
2250                         || LaTeXFeatures::isAvailable("fourier");
2251         if (font == "beraserif" || font == "berasans"
2252                 || font == "beramono")
2253                 return LaTeXFeatures::isAvailable("bera");
2254         return LaTeXFeatures::isAvailable(font);
2255 }
2256
2257
2258 bool GuiDocument::providesOSF(string const & font) const
2259 {
2260         if (font == "cmr")
2261                 return isFontAvailable("eco");
2262         if (font == "palatino")
2263                 return isFontAvailable("mathpazo");
2264         return false;
2265 }
2266
2267
2268 bool GuiDocument::providesSC(string const & font) const
2269 {
2270         if (font == "palatino")
2271                 return isFontAvailable("mathpazo");
2272         if (font == "utopia")
2273                 return isFontAvailable("fourier");
2274         return false;
2275 }
2276
2277
2278 bool GuiDocument::providesScale(string const & font) const
2279 {
2280         return font == "helvet" || font == "luximono"
2281                 || font == "berasans"  || font == "beramono";
2282 }
2283
2284
2285 void GuiDocument::loadModuleInfo()
2286 {
2287         moduleNames_.clear();
2288         LyXModuleList::const_iterator it  = moduleList.begin();
2289         LyXModuleList::const_iterator end = moduleList.end();
2290         for (; it != end; ++it) {
2291                 modInfoStruct m;
2292                 m.id = it->getID();
2293                 m.name = it->getName();
2294                 moduleNames_.push_back(m);
2295         }
2296 }
2297
2298
2299 Dialog * createGuiDocument(GuiView & lv) { return new GuiDocument(lv); }
2300
2301
2302 } // namespace frontend
2303 } // namespace lyx
2304
2305 #include "GuiDocument_moc.cpp"