]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiDocument.cpp
ee3d4e8d6ca9262e664b4dc7cd9cb70d3c62ea4d
[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 "GuiApplication.h"
17 #include "GuiBranches.h"
18 #include "GuiIndices.h"
19 #include "GuiSelectionManager.h"
20 #include "LaTeXHighlighter.h"
21 #include "LengthCombo.h"
22 #include "PanelStack.h"
23 #include "Validator.h"
24
25 #include "LayoutFile.h"
26 #include "BranchList.h"
27 #include "buffer_funcs.h"
28 #include "Buffer.h"
29 #include "BufferParams.h"
30 #include "BufferView.h"
31 #include "Color.h"
32 #include "ColorCache.h"
33 #include "Encoding.h"
34 #include "FloatPlacement.h"
35 #include "Format.h"
36 #include "FuncRequest.h"
37 #include "HSpace.h"
38 #include "IndicesList.h"
39 #include "Language.h"
40 #include "LaTeXFeatures.h"
41 #include "Layout.h"
42 #include "LayoutModuleList.h"
43 #include "LyXRC.h"
44 #include "ModuleList.h"
45 #include "OutputParams.h"
46 #include "PDFOptions.h"
47 #include "qt_helpers.h"
48 #include "Spacing.h"
49
50 #include "insets/InsetListingsParams.h"
51
52 #include "support/debug.h"
53 #include "support/FileName.h"
54 #include "support/filetools.h"
55 #include "support/gettext.h"
56 #include "support/lstrings.h"
57
58 #include "frontends/alert.h"
59
60 #include <QAbstractItemModel>
61 #include <QHeaderView>
62 #include <QColor>
63 #include <QColorDialog>
64 #include <QCloseEvent>
65 #include <QFontDatabase>
66 #include <QScrollBar>
67 #include <QTextCursor>
68
69 #include <sstream>
70 #include <vector>
71
72 #ifdef IN
73 #undef IN
74 #endif
75
76
77 // a style sheet for buttons
78 // this is for example used for the background color setting button
79 static inline QString colorButtonStyleSheet(QColor const & bgColor)
80 {
81         if (bgColor.isValid()) {
82                 QString rc = QLatin1String("background:");
83                 rc += bgColor.name();
84                 return rc;
85         }
86         return QString();
87 }
88
89
90 using namespace std;
91 using namespace lyx::support;
92
93
94 namespace {
95
96 char const * const tex_graphics[] =
97 {
98         "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
99         "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
100         "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
101         "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
102         "xetex", "none", ""
103 };
104
105
106 char const * const tex_graphics_gui[] =
107 {
108         N_("Default"), "dvialw", "DviLaser", "dvipdf", "DVIPDFM", "DVIPDFMx",
109         "Dvips", "DVIPSONE", "DVItoPS", "DVIWIN", "DVIWindo", "dvi2ps", "EmTeX",
110         "LN", "OzTeX", "pctexhp", "pctexps", "pctexwin", "PCTeX32", "pdfTeX",
111         "psprint", "pubps", "tcidvi", "Textures", "TrueTeX", "VTeX", "xdvi",
112         "XeTeX", N_("None"), ""
113 };
114
115
116 char const * const tex_fonts_roman[] =
117 {
118         "default", "cmr", "lmodern", "ae", "times", "palatino",
119         "charter", "newcent", "bookman", "utopia", "beraserif",
120         "ccfonts", "chancery", ""
121 };
122
123
124 char const * tex_fonts_roman_gui[] =
125 {
126         N_("Default"), N_("Computer Modern Roman"), N_("Latin Modern Roman"),
127         N_("AE (Almost European)"), N_("Times Roman"), N_("Palatino"),
128         N_("Bitstream Charter"), N_("New Century Schoolbook"), N_("Bookman"),
129         N_("Utopia"),  N_("Bera Serif"), N_("Concrete Roman"), N_("Zapf Chancery"),
130         ""
131 };
132
133
134 char const * const tex_fonts_sans[] =
135 {
136         "default", "cmss", "lmss", "helvet", "avant", "berasans", "cmbr", ""
137 };
138
139
140 char const * tex_fonts_sans_gui[] =
141 {
142         N_("Default"), N_("Computer Modern Sans"), N_("Latin Modern Sans"),
143         N_("Helvetica"), N_("Avant Garde"), N_("Bera Sans"), N_("CM Bright"), ""
144 };
145
146
147 char const * const tex_fonts_monospaced[] =
148 {
149         "default", "cmtt", "lmtt", "courier", "beramono", "luximono", "cmtl", ""
150 };
151
152
153 char const * tex_fonts_monospaced_gui[] =
154 {
155         N_("Default"), N_("Computer Modern Typewriter"),
156         N_("Latin Modern Typewriter"), N_("Courier"), N_("Bera Mono"),
157         N_("LuxiMono"), N_("CM Typewriter Light"), ""
158 };
159
160
161 char const * backref_opts[] =
162 {
163         "false", "section", "slide", "page", ""
164 };
165
166
167 char const * backref_opts_gui[] =
168 {
169         N_("Off"), N_("Section"), N_("Slide"), N_("Page"), ""
170 };
171
172
173 vector<pair<string, QString> > pagestyles;
174
175
176 } // anonymous namespace
177
178 namespace lyx {
179
180 RGBColor set_backgroundcolor;
181
182 namespace {
183 // used when sorting the textclass list.
184 class less_textclass_avail_desc
185         : public binary_function<string, string, int>
186 {
187 public:
188         bool operator()(string const & lhs, string const & rhs) const
189         {
190                 // Ordering criteria:
191                 //   1. Availability of text class
192                 //   2. Description (lexicographic)
193                 LayoutFile const & tc1 = LayoutFileList::get()[lhs];
194                 LayoutFile const & tc2 = LayoutFileList::get()[rhs];
195                 int const order = compare_no_case(
196                         translateIfPossible(from_utf8(tc1.description())),
197                         translateIfPossible(from_utf8(tc2.description())));
198                 return (tc1.isTeXClassAvailable() && !tc2.isTeXClassAvailable()) ||
199                         (tc1.isTeXClassAvailable() == tc2.isTeXClassAvailable() && order < 0);
200         }
201 };
202
203 }
204
205 namespace frontend {
206 namespace {
207
208 vector<string> getRequiredList(string const & modName) 
209 {
210         LyXModule const * const mod = theModuleList[modName];
211         if (!mod)
212                 return vector<string>(); //empty such thing
213         return mod->getRequiredModules();
214 }
215
216
217 vector<string> getExcludedList(string const & modName)
218 {
219         LyXModule const * const mod = theModuleList[modName];
220         if (!mod)
221                 return vector<string>(); //empty such thing
222         return mod->getExcludedModules();
223 }
224
225
226 docstring getModuleDescription(string const & modName)
227 {
228         LyXModule const * const mod = theModuleList[modName];
229         if (!mod)
230                 return _("Module not found!");
231         // FIXME Unicode
232         return translateIfPossible(from_utf8(mod->getDescription()));
233 }
234
235
236 vector<string> getPackageList(string const & modName)
237 {
238         LyXModule const * const mod = theModuleList[modName];
239         if (!mod)
240                 return vector<string>(); //empty such thing
241         return mod->getPackageList();
242 }
243
244
245 bool isModuleAvailable(string const & modName)
246 {
247         LyXModule const * const mod = theModuleList[modName];
248         if (!mod)
249                 return false;
250         return mod->isAvailable();
251 }
252
253 } // anonymous namespace
254
255
256 /////////////////////////////////////////////////////////////////////
257 //
258 // ModuleSelectionManager
259 //
260 /////////////////////////////////////////////////////////////////////
261
262 /// SelectionManager for use with modules
263 class ModuleSelectionManager : public GuiSelectionManager 
264 {
265 public:
266         ///
267         ModuleSelectionManager(
268                 QTreeView * availableLV,
269                 QListView * selectedLV,
270                 QPushButton * addPB, 
271                 QPushButton * delPB, 
272                 QPushButton * upPB, 
273                 QPushButton * downPB,
274                 GuiIdListModel * availableModel,
275                 GuiIdListModel * selectedModel,
276                 GuiDocument const * container)
277         : GuiSelectionManager(availableLV, selectedLV, addPB, delPB,
278                                 upPB, downPB, availableModel, selectedModel), container_(container)
279                 {}
280         ///
281         void updateProvidedModules(LayoutModuleList const & pm) 
282                         { provided_modules_ = pm.list(); }
283         ///
284         void updateExcludedModules(LayoutModuleList const & em) 
285                         { excluded_modules_ = em.list(); }
286 private:
287         ///
288         virtual void updateAddPB();
289         ///
290         virtual void updateUpPB();
291         ///
292         virtual void updateDownPB();
293         ///
294         virtual void updateDelPB();
295         /// returns availableModel as a GuiIdListModel
296         GuiIdListModel * getAvailableModel() 
297         {
298                 return dynamic_cast<GuiIdListModel *>(availableModel);
299         }
300         /// returns selectedModel as a GuiIdListModel
301         GuiIdListModel * getSelectedModel() 
302         {
303                 return dynamic_cast<GuiIdListModel *>(selectedModel);
304         }
305         /// keeps a list of the modules the text class provides
306         std::list<std::string> provided_modules_;
307         /// similarly...
308         std::list<std::string> excluded_modules_;
309         /// 
310         GuiDocument const * container_;
311 };
312
313 void ModuleSelectionManager::updateAddPB() 
314 {
315         int const arows = availableModel->rowCount();
316         QModelIndexList const avail_sels = 
317                         availableLV->selectionModel()->selectedIndexes();
318
319         // disable if there aren't any modules (?), if none of them is chosen
320         // in the dialog, or if the chosen one is already selected for use.
321         if (arows == 0 || avail_sels.isEmpty() || isSelected(avail_sels.first())) {
322                 addPB->setEnabled(false);
323                 return;
324         }
325
326         QModelIndex const & idx = availableLV->selectionModel()->currentIndex();
327         string const modname = getAvailableModel()->getIDString(idx.row());
328
329         bool const enable = 
330                 container_->params().moduleCanBeAdded(modname);
331         addPB->setEnabled(enable);
332 }
333
334
335 void ModuleSelectionManager::updateDownPB()
336 {
337         int const srows = selectedModel->rowCount();
338         if (srows == 0) {
339                 downPB->setEnabled(false);
340                 return;
341         }
342         QModelIndex const & curidx = selectedLV->selectionModel()->currentIndex();
343         int const curRow = curidx.row();
344         if (curRow < 0 || curRow >= srows - 1) { // invalid or last item
345                 downPB->setEnabled(false);
346                 return;
347         }
348
349         // determine whether immediately succeding element requires this one
350         string const curmodname = getSelectedModel()->getIDString(curRow);
351         string const nextmodname = getSelectedModel()->getIDString(curRow + 1);
352
353         vector<string> reqs = getRequiredList(nextmodname);
354
355         // if it doesn't require anything....
356         if (reqs.empty()) {
357                 downPB->setEnabled(true);
358                 return;
359         }
360
361         // Enable it if this module isn't required.
362         // FIXME This should perhaps be more flexible and check whether, even 
363         // if the next one is required, there is also an earlier one that will do.
364         downPB->setEnabled(
365                         find(reqs.begin(), reqs.end(), curmodname) == reqs.end());
366 }
367
368 void ModuleSelectionManager::updateUpPB() 
369 {
370         int const srows = selectedModel->rowCount();
371         if (srows == 0) {
372                 upPB->setEnabled(false);
373                 return;
374         }
375
376         QModelIndex const & curIdx = selectedLV->selectionModel()->currentIndex();
377         int curRow = curIdx.row();
378         if (curRow <= 0 || curRow > srows - 1) { // first item or invalid
379                 upPB->setEnabled(false);
380                 return;
381         }
382         string const curmodname = getSelectedModel()->getIDString(curRow);
383
384         // determine whether immediately preceding element is required by this one
385         vector<string> reqs = getRequiredList(curmodname);
386
387         // if this one doesn't require anything....
388         if (reqs.empty()) {
389                 upPB->setEnabled(true);
390                 return;
391         }
392
393
394         // Enable it if the preceding module isn't required.
395         // NOTE This is less flexible than it might be. We could check whether, even 
396         // if the previous one is required, there is an earlier one that would do.
397         string const premod = getSelectedModel()->getIDString(curRow - 1);
398         upPB->setEnabled(find(reqs.begin(), reqs.end(), premod) == reqs.end());
399 }
400
401 void ModuleSelectionManager::updateDelPB() 
402 {
403         int const srows = selectedModel->rowCount();
404         if (srows == 0) {
405                 deletePB->setEnabled(false);
406                 return;
407         }
408
409         QModelIndex const & curidx = 
410                 selectedLV->selectionModel()->currentIndex();
411         int const curRow = curidx.row();
412         if (curRow < 0 || curRow >= srows) { // invalid index?
413                 deletePB->setEnabled(false);
414                 return;
415         }
416
417         string const curmodname = getSelectedModel()->getIDString(curRow);
418
419         // We're looking here for a reason NOT to enable the button. If we
420         // find one, we disable it and return. If we don't, we'll end up at
421         // the end of the function, and then we enable it.
422         for (int i = curRow + 1; i < srows; ++i) {
423                 string const thisMod = getSelectedModel()->getIDString(i);
424                 vector<string> reqs = getRequiredList(thisMod);
425                 //does this one require us?
426                 if (find(reqs.begin(), reqs.end(), curmodname) == reqs.end())
427                         //no...
428                         continue;
429
430                 // OK, so this module requires us
431                 // is there an EARLIER module that also satisfies the require?
432                 // NOTE We demand that it be earlier to keep the list of modules
433                 // consistent with the rule that a module must be proceeded by a
434                 // required module. There would be more flexible ways to proceed,
435                 // but that would be a lot more complicated, and the logic here is
436                 // already complicated. (That's why I've left the debugging code.)
437                 // lyxerr << "Testing " << thisMod << std::endl;
438                 bool foundone = false;
439                 for (int j = 0; j < curRow; ++j) {
440                         string const mod = getSelectedModel()->getIDString(j);
441                         // lyxerr << "In loop: Testing " << mod << std::endl;
442                         // do we satisfy the require? 
443                         if (find(reqs.begin(), reqs.end(), mod) != reqs.end()) {
444                                 // lyxerr << mod << " does the trick." << std::endl;
445                                 foundone = true;
446                                 break;
447                         }
448                 }
449                 // did we find a module to satisfy the require?
450                 if (!foundone) {
451                         // lyxerr << "No matching module found." << std::endl;
452                         deletePB->setEnabled(false);
453                         return;
454                 }
455         }
456         // lyxerr << "All's well that ends well." << std::endl; 
457         deletePB->setEnabled(true);
458 }
459
460
461 /////////////////////////////////////////////////////////////////////
462 //
463 // PreambleModule
464 //
465 /////////////////////////////////////////////////////////////////////
466
467 PreambleModule::PreambleModule() : current_id_(0)
468 {
469         // This is not a memory leak. The object will be destroyed
470         // with this.
471         (void) new LaTeXHighlighter(preambleTE->document());
472         setFocusProxy(preambleTE);
473         connect(preambleTE, SIGNAL(textChanged()), this, SIGNAL(changed()));
474 }
475
476
477 void PreambleModule::update(BufferParams const & params, BufferId id)
478 {
479         QString preamble = toqstr(params.preamble);
480         // Nothing to do if the params and preamble are unchanged.
481         if (id == current_id_
482                 && preamble == preambleTE->document()->toPlainText())
483                 return;
484
485         QTextCursor cur = preambleTE->textCursor();
486         // Save the coords before switching to the new one.
487         preamble_coords_[current_id_] =
488                 make_pair(cur.position(), preambleTE->verticalScrollBar()->value());
489
490         // Save the params address for further use.
491         current_id_ = id;
492         preambleTE->document()->setPlainText(preamble);
493         Coords::const_iterator it = preamble_coords_.find(current_id_);
494         if (it == preamble_coords_.end())
495                 // First time we open this one.
496                 preamble_coords_[current_id_] = make_pair(0, 0);
497         else {
498                 // Restore saved coords.
499                 QTextCursor cur = preambleTE->textCursor();
500                 cur.setPosition(it->second.first);
501                 preambleTE->setTextCursor(cur);
502                 preambleTE->verticalScrollBar()->setValue(it->second.second);
503         }
504 }
505
506
507 void PreambleModule::apply(BufferParams & params)
508 {
509         params.preamble = fromqstr(preambleTE->document()->toPlainText());
510 }
511
512
513 void PreambleModule::closeEvent(QCloseEvent * e)
514 {
515         // Save the coords before closing.
516         QTextCursor cur = preambleTE->textCursor();
517         preamble_coords_[current_id_] =
518                 make_pair(cur.position(), preambleTE->verticalScrollBar()->value());
519         e->accept();
520 }
521
522
523 /////////////////////////////////////////////////////////////////////
524 //
525 // DocumentDialog
526 //
527 /////////////////////////////////////////////////////////////////////
528
529
530 GuiDocument::GuiDocument(GuiView & lv)
531         : GuiDialog(lv, "document", qt_("Document Settings"))
532 {
533         setupUi(this);
534
535         connect(okPB, SIGNAL(clicked()), this, SLOT(slotOK()));
536         connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
537         connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
538         connect(restorePB, SIGNAL(clicked()), this, SLOT(slotRestore()));
539
540         connect(savePB, SIGNAL(clicked()), this, SLOT(saveDefaultClicked()));
541         connect(defaultPB, SIGNAL(clicked()), this, SLOT(useDefaultsClicked()));
542
543         // Manage the restore, ok, apply, restore and cancel/close buttons
544         bc().setPolicy(ButtonPolicy::NoRepeatedApplyReadOnlyPolicy);
545         bc().setOK(okPB);
546         bc().setApply(applyPB);
547         bc().setCancel(closePB);
548         bc().setRestore(restorePB);
549
550         textLayoutModule = new UiWidget<Ui::TextLayoutUi>;
551         // text layout
552         connect(textLayoutModule->lspacingCO, SIGNAL(activated(int)),
553                 this, SLOT(change_adaptor()));
554         connect(textLayoutModule->lspacingCO, SIGNAL(activated(int)),
555                 this, SLOT(setLSpacing(int)));
556         connect(textLayoutModule->lspacingLE, SIGNAL(textChanged(const QString &)),
557                 this, SLOT(change_adaptor()));
558
559         connect(textLayoutModule->indentRB, SIGNAL(clicked()),
560                 this, SLOT(change_adaptor()));
561         connect(textLayoutModule->indentRB, SIGNAL(toggled(bool)),
562                 textLayoutModule->indentCO, SLOT(setEnabled(bool)));
563         connect(textLayoutModule->indentCO, SIGNAL(activated(int)),
564                 this, SLOT(change_adaptor()));
565         connect(textLayoutModule->indentCO, SIGNAL(activated(int)),
566                 this, SLOT(setIndent(int)));
567         connect(textLayoutModule->indentLE, SIGNAL(textChanged(const QString &)),
568                 this, SLOT(change_adaptor()));
569         connect(textLayoutModule->indentLengthCO, SIGNAL(activated(int)),
570                 this, SLOT(change_adaptor()));
571
572         connect(textLayoutModule->skipRB, SIGNAL(clicked()),
573                 this, SLOT(change_adaptor()));
574         connect(textLayoutModule->skipRB, SIGNAL(toggled(bool)),
575                 textLayoutModule->skipCO, SLOT(setEnabled(bool)));
576         connect(textLayoutModule->skipCO, SIGNAL(activated(int)),
577                 this, SLOT(change_adaptor()));
578         connect(textLayoutModule->skipCO, SIGNAL(activated(int)),
579                 this, SLOT(setSkip(int)));
580         connect(textLayoutModule->skipLE, SIGNAL(textChanged(const QString &)),
581                 this, SLOT(change_adaptor()));
582         connect(textLayoutModule->skipLengthCO, SIGNAL(activated(int)),
583                 this, SLOT(change_adaptor()));
584
585         connect(textLayoutModule->indentRB, SIGNAL(toggled(bool)),
586                 this, SLOT(enableIndent(bool)));
587         connect(textLayoutModule->skipRB, SIGNAL(toggled(bool)),
588                 this, SLOT(enableSkip(bool)));
589
590         connect(textLayoutModule->twoColumnCB, SIGNAL(clicked()),
591                 this, SLOT(change_adaptor()));
592         connect(textLayoutModule->twoColumnCB, SIGNAL(clicked()),
593                 this, SLOT(setColSep()));
594
595         textLayoutModule->lspacingLE->setValidator(new QDoubleValidator(
596                 textLayoutModule->lspacingLE));
597         textLayoutModule->indentLE->setValidator(unsignedLengthValidator(
598                 textLayoutModule->indentLE));
599         textLayoutModule->skipLE->setValidator(unsignedGlueLengthValidator(
600                 textLayoutModule->skipLE));
601
602         textLayoutModule->indentCO->addItem(qt_("Default"));
603         textLayoutModule->indentCO->addItem(qt_("Custom"));
604         textLayoutModule->skipCO->addItem(qt_("SmallSkip"));
605         textLayoutModule->skipCO->addItem(qt_("MedSkip"));
606         textLayoutModule->skipCO->addItem(qt_("BigSkip"));
607         textLayoutModule->skipCO->addItem(qt_("Custom"));
608         textLayoutModule->lspacingCO->insertItem(
609                 Spacing::Single, qt_("Single"));
610         textLayoutModule->lspacingCO->insertItem(
611                 Spacing::Onehalf, qt_("OneHalf"));
612         textLayoutModule->lspacingCO->insertItem(
613                 Spacing::Double, qt_("Double"));
614         textLayoutModule->lspacingCO->insertItem(
615                 Spacing::Other, qt_("Custom"));
616         // initialize the length validator
617         bc().addCheckedLineEdit(textLayoutModule->indentLE);
618         bc().addCheckedLineEdit(textLayoutModule->skipLE);
619
620         // output
621         outputModule = new UiWidget<Ui::OutputUi>;
622
623         connect(outputModule->xetexCB, SIGNAL(clicked()),
624                 this, SLOT(change_adaptor()));
625         connect(outputModule->xetexCB, SIGNAL(toggled(bool)),
626                 this, SLOT(xetexChanged(bool)));
627         connect(outputModule->defaultFormatCO, SIGNAL(activated(int)),
628                 this, SLOT(change_adaptor()));
629
630         // fonts
631         fontModule = new UiWidget<Ui::FontUi>;
632         connect(fontModule->fontsRomanCO, SIGNAL(activated(int)),
633                 this, SLOT(change_adaptor()));
634         connect(fontModule->fontsRomanCO, SIGNAL(activated(int)),
635                 this, SLOT(romanChanged(int)));
636         connect(fontModule->fontsSansCO, SIGNAL(activated(int)),
637                 this, SLOT(change_adaptor()));
638         connect(fontModule->fontsSansCO, SIGNAL(activated(int)),
639                 this, SLOT(sansChanged(int)));
640         connect(fontModule->fontsTypewriterCO, SIGNAL(activated(int)),
641                 this, SLOT(change_adaptor()));
642         connect(fontModule->fontsTypewriterCO, SIGNAL(activated(int)),
643                 this, SLOT(ttChanged(int)));
644         connect(fontModule->fontsDefaultCO, SIGNAL(activated(int)),
645                 this, SLOT(change_adaptor()));
646         connect(fontModule->fontsizeCO, SIGNAL(activated(int)),
647                 this, SLOT(change_adaptor()));
648         connect(fontModule->cjkFontLE, SIGNAL(textChanged(const QString &)),
649                 this, SLOT(change_adaptor()));
650         connect(fontModule->scaleSansSB, SIGNAL(valueChanged(int)),
651                 this, SLOT(change_adaptor()));
652         connect(fontModule->scaleTypewriterSB, SIGNAL(valueChanged(int)),
653                 this, SLOT(change_adaptor()));
654         connect(fontModule->fontScCB, SIGNAL(clicked()),
655                 this, SLOT(change_adaptor()));
656         connect(fontModule->fontOsfCB, SIGNAL(clicked()),
657                 this, SLOT(change_adaptor()));
658
659         updateFontlist();
660
661         fontModule->fontsizeCO->addItem(qt_("Default"));
662         fontModule->fontsizeCO->addItem(qt_("10"));
663         fontModule->fontsizeCO->addItem(qt_("11"));
664         fontModule->fontsizeCO->addItem(qt_("12"));
665
666         for (int n = 0; GuiDocument::fontfamilies_gui[n][0]; ++n)
667                 fontModule->fontsDefaultCO->addItem(
668                         qt_(GuiDocument::fontfamilies_gui[n]));
669
670
671         pageLayoutModule = new UiWidget<Ui::PageLayoutUi>;
672         // page layout
673         connect(pageLayoutModule->papersizeCO, SIGNAL(activated(int)),
674                 this, SLOT(papersizeChanged(int)));
675         connect(pageLayoutModule->papersizeCO, SIGNAL(activated(int)),
676                 this, SLOT(papersizeChanged(int)));
677         connect(pageLayoutModule->portraitRB, SIGNAL(clicked()),
678                 this, SLOT(portraitChanged()));
679         connect(pageLayoutModule->papersizeCO, SIGNAL(activated(int)),
680                 this, SLOT(change_adaptor()));
681         connect(pageLayoutModule->paperheightLE, SIGNAL(textChanged(const QString &)),
682                 this, SLOT(change_adaptor()));
683         connect(pageLayoutModule->paperwidthLE, SIGNAL(textChanged(const QString &)),
684                 this, SLOT(change_adaptor()));
685         connect(pageLayoutModule->paperwidthUnitCO, SIGNAL(activated(int)),
686                 this, SLOT(change_adaptor()));
687         connect(pageLayoutModule->paperheightUnitCO, SIGNAL(activated(int)),
688                 this, SLOT(change_adaptor()));
689         connect(pageLayoutModule->portraitRB, SIGNAL(clicked()),
690                 this, SLOT(change_adaptor()));
691         connect(pageLayoutModule->landscapeRB, SIGNAL(clicked()),
692                 this, SLOT(change_adaptor()));
693         connect(pageLayoutModule->facingPagesCB, SIGNAL(clicked()),
694                 this, SLOT(change_adaptor()));
695         connect(pageLayoutModule->pagestyleCO, SIGNAL(activated(int)),
696                 this, SLOT(change_adaptor()));
697         connect(pageLayoutModule->backgroundPB, SIGNAL(clicked()),
698                 this, SLOT(changeBackgroundColor()));
699         connect(pageLayoutModule->delbackgroundTB, SIGNAL(clicked()),
700                 this, SLOT(deleteBackgroundColor()));
701
702         pageLayoutModule->pagestyleCO->addItem(qt_("Default"));
703         pageLayoutModule->pagestyleCO->addItem(qt_("empty"));
704         pageLayoutModule->pagestyleCO->addItem(qt_("plain"));
705         pageLayoutModule->pagestyleCO->addItem(qt_("headings"));
706         pageLayoutModule->pagestyleCO->addItem(qt_("fancy"));
707         bc().addCheckedLineEdit(pageLayoutModule->paperheightLE,
708                 pageLayoutModule->paperheightL);
709         bc().addCheckedLineEdit(pageLayoutModule->paperwidthLE,
710                 pageLayoutModule->paperwidthL);
711
712         // paper
713         QComboBox * cb = pageLayoutModule->papersizeCO;
714         cb->addItem(qt_("Default"));
715         cb->addItem(qt_("Custom"));
716         cb->addItem(qt_("US letter"));
717         cb->addItem(qt_("US legal"));
718         cb->addItem(qt_("US executive"));
719         cb->addItem(qt_("A3"));
720         cb->addItem(qt_("A4"));
721         cb->addItem(qt_("A5"));
722         cb->addItem(qt_("B3"));
723         cb->addItem(qt_("B4"));
724         cb->addItem(qt_("B5"));
725         // remove the %-items from the unit choice
726         pageLayoutModule->paperwidthUnitCO->noPercents();
727         pageLayoutModule->paperheightUnitCO->noPercents();
728         pageLayoutModule->paperheightLE->setValidator(unsignedLengthValidator(
729                 pageLayoutModule->paperheightLE));
730         pageLayoutModule->paperwidthLE->setValidator(unsignedLengthValidator(
731                 pageLayoutModule->paperwidthLE));
732
733
734         marginsModule = new UiWidget<Ui::MarginsUi>;
735         // margins
736         connect(marginsModule->marginCB, SIGNAL(toggled(bool)),
737                 this, SLOT(setCustomMargins(bool)));
738         connect(marginsModule->marginCB, SIGNAL(clicked()),
739                 this, SLOT(change_adaptor()));
740         connect(marginsModule->topLE, SIGNAL(textChanged(QString)),
741                 this, SLOT(change_adaptor()));
742         connect(marginsModule->topUnit, SIGNAL(activated(int)),
743                 this, SLOT(change_adaptor()));
744         connect(marginsModule->bottomLE, SIGNAL(textChanged(QString)),
745                 this, SLOT(change_adaptor()));
746         connect(marginsModule->bottomUnit, SIGNAL(activated(int)),
747                 this, SLOT(change_adaptor()));
748         connect(marginsModule->innerLE, SIGNAL(textChanged(QString)),
749                 this, SLOT(change_adaptor()));
750         connect(marginsModule->innerUnit, SIGNAL(activated(int)),
751                 this, SLOT(change_adaptor()));
752         connect(marginsModule->outerLE, SIGNAL(textChanged(QString)),
753                 this, SLOT(change_adaptor()));
754         connect(marginsModule->outerUnit, SIGNAL(activated(int)),
755                 this, SLOT(change_adaptor()));
756         connect(marginsModule->headheightLE, SIGNAL(textChanged(QString)),
757                 this, SLOT(change_adaptor()));
758         connect(marginsModule->headheightUnit, SIGNAL(activated(int)),
759                 this, SLOT(change_adaptor()));
760         connect(marginsModule->headsepLE, SIGNAL(textChanged(QString)),
761                 this, SLOT(change_adaptor()));
762         connect(marginsModule->headsepUnit, SIGNAL(activated(int)),
763                 this, SLOT(change_adaptor()));
764         connect(marginsModule->footskipLE, SIGNAL(textChanged(QString)),
765                 this, SLOT(change_adaptor()));
766         connect(marginsModule->footskipUnit, SIGNAL(activated(int)),
767                 this, SLOT(change_adaptor()));
768         connect(marginsModule->columnsepLE, SIGNAL(textChanged(QString)),
769                 this, SLOT(change_adaptor()));
770         connect(marginsModule->columnsepUnit, SIGNAL(activated(int)),
771                 this, SLOT(change_adaptor()));
772         marginsModule->topLE->setValidator(unsignedLengthValidator(
773                 marginsModule->topLE));
774         marginsModule->bottomLE->setValidator(unsignedLengthValidator(
775                 marginsModule->bottomLE));
776         marginsModule->innerLE->setValidator(unsignedLengthValidator(
777                 marginsModule->innerLE));
778         marginsModule->outerLE->setValidator(unsignedLengthValidator(
779                 marginsModule->outerLE));
780         marginsModule->headsepLE->setValidator(unsignedLengthValidator(
781                 marginsModule->headsepLE));
782         marginsModule->headheightLE->setValidator(unsignedLengthValidator(
783                 marginsModule->headheightLE));
784         marginsModule->footskipLE->setValidator(unsignedLengthValidator(
785                 marginsModule->footskipLE));
786         marginsModule->columnsepLE->setValidator(unsignedLengthValidator(
787                 marginsModule->columnsepLE));
788
789         bc().addCheckedLineEdit(marginsModule->topLE,
790                 marginsModule->topL);
791         bc().addCheckedLineEdit(marginsModule->bottomLE,
792                 marginsModule->bottomL);
793         bc().addCheckedLineEdit(marginsModule->innerLE,
794                 marginsModule->innerL);
795         bc().addCheckedLineEdit(marginsModule->outerLE,
796                 marginsModule->outerL);
797         bc().addCheckedLineEdit(marginsModule->headsepLE,
798                 marginsModule->headsepL);
799         bc().addCheckedLineEdit(marginsModule->headheightLE,
800                 marginsModule->headheightL);
801         bc().addCheckedLineEdit(marginsModule->footskipLE,
802                 marginsModule->footskipL);
803         bc().addCheckedLineEdit(marginsModule->columnsepLE,
804                 marginsModule->columnsepL);
805
806
807         langModule = new UiWidget<Ui::LanguageUi>;
808         // language & quote
809         connect(langModule->languageCO, SIGNAL(activated(int)),
810                 this, SLOT(change_adaptor()));
811         connect(langModule->defaultencodingRB, SIGNAL(clicked()),
812                 this, SLOT(change_adaptor()));
813         connect(langModule->otherencodingRB, SIGNAL(clicked()),
814                 this, SLOT(change_adaptor()));
815         connect(langModule->encodingCO, SIGNAL(activated(int)),
816                 this, SLOT(change_adaptor()));
817         connect(langModule->quoteStyleCO, SIGNAL(activated(int)),
818                 this, SLOT(change_adaptor()));
819         // language & quotes
820         QAbstractItemModel * language_model = guiApp->languageModel();
821         // FIXME: it would be nice if sorting was enabled/disabled via a checkbox.
822         language_model->sort(0);
823         langModule->languageCO->setModel(language_model);
824
825         // Always put the default encoding in the first position.
826         langModule->encodingCO->addItem(qt_("Language Default (no inputenc)"));
827         QStringList encodinglist;
828         Encodings::const_iterator it = encodings.begin();
829         Encodings::const_iterator const end = encodings.end();
830         for (; it != end; ++it)
831                 encodinglist.append(qt_(it->guiName()));
832         encodinglist.sort();
833         langModule->encodingCO->addItems(encodinglist);
834
835         langModule->quoteStyleCO->addItem(qt_("``text''"));
836         langModule->quoteStyleCO->addItem(qt_("''text''"));
837         langModule->quoteStyleCO->addItem(qt_(",,text``"));
838         langModule->quoteStyleCO->addItem(qt_(",,text''"));
839         langModule->quoteStyleCO->addItem(qt_("<<text>>"));
840         langModule->quoteStyleCO->addItem(qt_(">>text<<"));
841
842
843         numberingModule = new UiWidget<Ui::NumberingUi>;
844         // numbering
845         connect(numberingModule->depthSL, SIGNAL(valueChanged(int)),
846                 this, SLOT(change_adaptor()));
847         connect(numberingModule->tocSL, SIGNAL(valueChanged(int)),
848                 this, SLOT(change_adaptor()));
849         connect(numberingModule->depthSL, SIGNAL(valueChanged(int)),
850                 this, SLOT(updateNumbering()));
851         connect(numberingModule->tocSL, SIGNAL(valueChanged(int)),
852                 this, SLOT(updateNumbering()));
853         numberingModule->tocTW->setColumnCount(3);
854         numberingModule->tocTW->headerItem()->setText(0, qt_("Example"));
855         numberingModule->tocTW->headerItem()->setText(1, qt_("Numbered"));
856         numberingModule->tocTW->headerItem()->setText(2, qt_("Appears in TOC"));
857
858
859         biblioModule = new UiWidget<Ui::BiblioUi>;
860         connect(biblioModule->citeNatbibRB, SIGNAL(toggled(bool)),
861                 biblioModule->citationStyleL, SLOT(setEnabled(bool)));
862         connect(biblioModule->citeNatbibRB, SIGNAL(toggled(bool)),
863                 biblioModule->citeStyleCO, SLOT(setEnabled(bool)));
864         // biblio
865         connect(biblioModule->citeDefaultRB, SIGNAL(clicked()),
866                 this, SLOT(change_adaptor()));
867         connect(biblioModule->citeNatbibRB, SIGNAL(clicked()),
868                 this, SLOT(change_adaptor()));
869         connect(biblioModule->citeStyleCO, SIGNAL(activated(int)),
870                 this, SLOT(change_adaptor()));
871         connect(biblioModule->citeJurabibRB, SIGNAL(clicked()),
872                 this, SLOT(change_adaptor()));
873         connect(biblioModule->bibtopicCB, SIGNAL(clicked()),
874                 this, SLOT(change_adaptor()));
875         connect(biblioModule->bibtexCO, SIGNAL(activated(int)),
876                 this, SLOT(bibtexChanged(int)));
877         connect(biblioModule->bibtexOptionsED, SIGNAL(textChanged(QString)),
878                 this, SLOT(change_adaptor()));
879         // biblio
880         biblioModule->citeStyleCO->addItem(qt_("Author-year"));
881         biblioModule->citeStyleCO->addItem(qt_("Numerical"));
882         biblioModule->citeStyleCO->setCurrentIndex(0);
883         
884         biblioModule->bibtexCO->clear();
885
886         biblioModule->bibtexCO->addItem(qt_("Default"), QString("default"));
887         for (set<string>::const_iterator it = lyxrc.bibtex_alternatives.begin();
888                              it != lyxrc.bibtex_alternatives.end(); ++it) {
889                 QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
890                 biblioModule->bibtexCO->addItem(command, command);
891         }
892
893         // indices
894         indicesModule = new GuiIndices;
895         connect(indicesModule, SIGNAL(changed()),
896                 this, SLOT(change_adaptor()));
897
898
899         mathsModule = new UiWidget<Ui::MathsUi>;
900         connect(mathsModule->amsautoCB, SIGNAL(toggled(bool)),
901                 mathsModule->amsCB, SLOT(setDisabled(bool)));
902         connect(mathsModule->esintautoCB, SIGNAL(toggled(bool)),
903                 mathsModule->esintCB, SLOT(setDisabled(bool)));
904         connect(mathsModule->mhchemautoCB, SIGNAL(toggled(bool)),
905                 mathsModule->mhchemCB, SLOT(setDisabled(bool)));
906         // maths
907         connect(mathsModule->amsCB, SIGNAL(clicked()),
908                 this, SLOT(change_adaptor()));
909         connect(mathsModule->amsautoCB, SIGNAL(clicked()),
910                 this, SLOT(change_adaptor()));
911         connect(mathsModule->esintCB, SIGNAL(clicked()),
912                 this, SLOT(change_adaptor()));
913         connect(mathsModule->esintautoCB, SIGNAL(clicked()),
914                 this, SLOT(change_adaptor()));
915         connect(mathsModule->mhchemCB, SIGNAL(clicked()),
916                 this, SLOT(change_adaptor()));
917         connect(mathsModule->mhchemautoCB, SIGNAL(clicked()),
918                 this, SLOT(change_adaptor()));
919
920         latexModule = new UiWidget<Ui::LaTeXUi>;
921         // latex class
922         connect(latexModule->optionsLE, SIGNAL(textChanged(QString)),
923                 this, SLOT(change_adaptor()));
924         connect(latexModule->defaultOptionsCB, SIGNAL(clicked()),
925                 this, SLOT(change_adaptor()));
926         connect(latexModule->psdriverCO, SIGNAL(activated(int)),
927                 this, SLOT(change_adaptor()));
928         connect(latexModule->classCO, SIGNAL(activated(int)),
929                 this, SLOT(classChanged()));
930         connect(latexModule->classCO, SIGNAL(activated(int)),
931                 this, SLOT(change_adaptor()));
932         connect(latexModule->layoutPB, SIGNAL(clicked()),
933                 this, SLOT(browseLayout()));
934         connect(latexModule->layoutPB, SIGNAL(clicked()),
935                 this, SLOT(change_adaptor()));
936         connect(latexModule->childDocGB, SIGNAL(clicked()),
937                 this, SLOT(change_adaptor()));
938         connect(latexModule->childDocLE, SIGNAL(textChanged(QString)),
939                 this, SLOT(change_adaptor()));
940         connect(latexModule->childDocPB, SIGNAL(clicked()),
941                 this, SLOT(browseMaster()));
942         connect(latexModule->suppressDateCB, SIGNAL(clicked()),
943                 this, SLOT(change_adaptor()));
944
945         // postscript drivers
946         for (int n = 0; tex_graphics[n][0]; ++n) {
947                 QString enc = qt_(tex_graphics_gui[n]);
948                 latexModule->psdriverCO->addItem(enc);
949         }
950         // latex classes
951         latexModule->classCO->setModel(&classes_model_);
952         LayoutFileList const & bcl = LayoutFileList::get();
953         vector<LayoutFileIndex> classList = bcl.classList();
954         sort(classList.begin(), classList.end(), less_textclass_avail_desc());
955
956         vector<LayoutFileIndex>::const_iterator cit  = classList.begin();
957         vector<LayoutFileIndex>::const_iterator cen = classList.end();
958         for (int i = 0; cit != cen; ++cit, ++i) {
959                 LayoutFile const & tc = bcl[*cit];
960                 docstring item = (tc.isTeXClassAvailable()) ?
961                         from_utf8(tc.description()) :
962                         bformat(_("Unavailable: %1$s"), from_utf8(tc.description()));
963                 classes_model_.insertRow(i, toqstr(item), *cit);
964         }
965
966         // branches
967         branchesModule = new GuiBranches;
968         connect(branchesModule, SIGNAL(changed()),
969                 this, SLOT(change_adaptor()));
970         connect(branchesModule, SIGNAL(renameBranches(docstring const &, docstring const &)),
971                 this, SLOT(branchesRename(docstring const &, docstring const &)));
972         updateUnknownBranches();
973
974         // preamble
975         preambleModule = new PreambleModule;
976         connect(preambleModule, SIGNAL(changed()),
977                 this, SLOT(change_adaptor()));
978
979         // bullets
980         bulletsModule = new BulletsModule;
981         connect(bulletsModule, SIGNAL(changed()),
982                 this, SLOT(change_adaptor()));
983
984         // Modules
985         modulesModule = new UiWidget<Ui::ModulesUi>;
986         modulesModule->availableLV->header()->setVisible(false);
987         selectionManager =
988                 new ModuleSelectionManager(modulesModule->availableLV,
989                         modulesModule->selectedLV,
990                         modulesModule->addPB, modulesModule->deletePB,
991                         modulesModule->upPB, modulesModule->downPB,
992                         availableModel(), selectedModel(), this);
993         connect(selectionManager, SIGNAL(updateHook()),
994                 this, SLOT(updateModuleInfo()));
995         connect(selectionManager, SIGNAL(updateHook()),
996                 this, SLOT(change_adaptor()));
997         connect(selectionManager, SIGNAL(selectionChanged()),
998                 this, SLOT(modulesChanged()));
999
1000         // PDF support
1001         pdfSupportModule = new UiWidget<Ui::PDFSupportUi>;
1002
1003         connect(pdfSupportModule->use_hyperrefGB, SIGNAL(toggled(bool)),
1004                 this, SLOT(change_adaptor()));
1005         connect(pdfSupportModule->titleLE, SIGNAL(textChanged(QString)),
1006                 this, SLOT(change_adaptor()));
1007         connect(pdfSupportModule->authorLE, SIGNAL(textChanged(QString)),
1008                 this, SLOT(change_adaptor()));
1009         connect(pdfSupportModule->subjectLE, SIGNAL(textChanged(QString)),
1010                 this, SLOT(change_adaptor()));
1011         connect(pdfSupportModule->keywordsLE, SIGNAL(textChanged(QString)),
1012                 this, SLOT(change_adaptor()));
1013         connect(pdfSupportModule->bookmarksGB, SIGNAL(toggled(bool)),
1014                 this, SLOT(change_adaptor()));
1015         connect(pdfSupportModule->bookmarksnumberedCB, SIGNAL(toggled(bool)),
1016                 this, SLOT(change_adaptor()));
1017         connect(pdfSupportModule->bookmarksopenGB, SIGNAL(toggled(bool)),
1018                 this, SLOT(change_adaptor()));
1019         connect(pdfSupportModule->bookmarksopenlevelSB, SIGNAL(valueChanged(int)),
1020                 this, SLOT(change_adaptor()));
1021         connect(pdfSupportModule->breaklinksCB, SIGNAL(toggled(bool)),
1022                 this, SLOT(change_adaptor()));
1023         connect(pdfSupportModule->pdfborderCB, SIGNAL(toggled(bool)),
1024                 this, SLOT(change_adaptor()));
1025         connect(pdfSupportModule->colorlinksCB, SIGNAL(toggled(bool)),
1026                 this, SLOT(change_adaptor()));
1027         connect(pdfSupportModule->backrefCO, SIGNAL(activated(int)),
1028                 this, SLOT(change_adaptor()));
1029         connect(pdfSupportModule->pdfusetitleCB, SIGNAL(toggled(bool)),
1030                 this, SLOT(change_adaptor()));
1031         connect(pdfSupportModule->fullscreenCB, SIGNAL(toggled(bool)),
1032                 this, SLOT(change_adaptor()));
1033         connect(pdfSupportModule->optionsLE, SIGNAL(textChanged(QString)),
1034                 this, SLOT(change_adaptor()));
1035
1036         for (int i = 0; backref_opts[i][0]; ++i)
1037                 pdfSupportModule->backrefCO->addItem(qt_(backref_opts_gui[i]));
1038
1039         // float
1040         floatModule = new FloatPlacement;
1041         connect(floatModule, SIGNAL(changed()),
1042                 this, SLOT(change_adaptor()));
1043
1044         // listings
1045         listingsModule = new UiWidget<Ui::ListingsSettingsUi>;
1046         connect(listingsModule->listingsED, SIGNAL(textChanged()),
1047                 this, SLOT(change_adaptor()));
1048         connect(listingsModule->bypassCB, SIGNAL(clicked()), 
1049                 this, SLOT(change_adaptor()));
1050         connect(listingsModule->bypassCB, SIGNAL(clicked()), 
1051                 this, SLOT(setListingsMessage()));
1052         connect(listingsModule->listingsED, SIGNAL(textChanged()),
1053                 this, SLOT(setListingsMessage()));
1054         listingsModule->listingsTB->setPlainText(
1055                 qt_("Input listings parameters below. Enter ? for a list of parameters."));
1056
1057         docPS->addPanel(latexModule, qt_("Document Class"));
1058         docPS->addPanel(modulesModule, qt_("Modules"));
1059         docPS->addPanel(fontModule, qt_("Fonts"));
1060         docPS->addPanel(textLayoutModule, qt_("Text Layout"));
1061         docPS->addPanel(pageLayoutModule, qt_("Page Layout"));
1062         docPS->addPanel(marginsModule, qt_("Page Margins"));
1063         docPS->addPanel(langModule, qt_("Language"));
1064         docPS->addPanel(numberingModule, qt_("Numbering & TOC"));
1065         docPS->addPanel(biblioModule, qt_("Bibliography"));
1066         docPS->addPanel(indicesModule, qt_("Indexes"));
1067         docPS->addPanel(pdfSupportModule, qt_("PDF Properties"));
1068         docPS->addPanel(mathsModule, qt_("Math Options"));
1069         docPS->addPanel(floatModule, qt_("Float Placement"));
1070         docPS->addPanel(listingsModule, qt_("Listings"));
1071         docPS->addPanel(bulletsModule, qt_("Bullets"));
1072         docPS->addPanel(branchesModule, qt_("Branches"));
1073         docPS->addPanel(outputModule, qt_("Output"));
1074         docPS->addPanel(preambleModule, qt_("LaTeX Preamble"));
1075         docPS->setCurrentPanel(qt_("Document Class"));
1076 // FIXME: hack to work around resizing bug in Qt >= 4.2
1077 // bug verified with Qt 4.2.{0-3} (JSpitzm)
1078 #if QT_VERSION >= 0x040200
1079         docPS->updateGeometry();
1080 #endif
1081 }
1082
1083
1084 void GuiDocument::showPreamble()
1085 {
1086         docPS->setCurrentPanel(qt_("LaTeX Preamble"));
1087 }
1088
1089
1090 void GuiDocument::saveDefaultClicked()
1091 {
1092         saveDocDefault();
1093 }
1094
1095
1096 void GuiDocument::useDefaultsClicked()
1097 {
1098         useClassDefaults();
1099 }
1100
1101
1102 void GuiDocument::change_adaptor()
1103 {
1104         changed();
1105 }
1106
1107
1108 QString GuiDocument::validateListingsParameters()
1109 {
1110         // use a cache here to avoid repeated validation
1111         // of the same parameters
1112         static string param_cache;
1113         static QString msg_cache;
1114         
1115         if (listingsModule->bypassCB->isChecked())
1116                 return QString();
1117
1118         string params = fromqstr(listingsModule->listingsED->toPlainText());
1119         if (params != param_cache) {
1120                 param_cache = params;
1121                 msg_cache = toqstr(InsetListingsParams(params).validate());
1122         }
1123         return msg_cache;
1124 }
1125
1126
1127 void GuiDocument::setListingsMessage()
1128 {
1129         static bool isOK = true;
1130         QString msg = validateListingsParameters();
1131         if (msg.isEmpty()) {
1132                 if (isOK)
1133                         return;
1134                 isOK = true;
1135                 // listingsTB->setTextColor("black");
1136                 listingsModule->listingsTB->setPlainText(
1137                         qt_("Input listings parameters below. "
1138                 "Enter ? for a list of parameters."));
1139         } else {
1140                 isOK = false;
1141                 // listingsTB->setTextColor("red");
1142                 listingsModule->listingsTB->setPlainText(msg);
1143         }
1144 }
1145
1146
1147 void GuiDocument::setLSpacing(int item)
1148 {
1149         textLayoutModule->lspacingLE->setEnabled(item == 3);
1150 }
1151
1152
1153 void GuiDocument::setIndent(int item)
1154 {
1155         bool const enable = (item == 1);
1156         textLayoutModule->indentLE->setEnabled(enable);
1157         textLayoutModule->indentLengthCO->setEnabled(enable);
1158         textLayoutModule->skipLE->setEnabled(false);
1159         textLayoutModule->skipLengthCO->setEnabled(false);
1160         isValid();
1161 }
1162
1163
1164 void GuiDocument::enableIndent(bool indent)
1165 {
1166         textLayoutModule->skipLE->setEnabled(!indent);
1167         textLayoutModule->skipLengthCO->setEnabled(!indent);
1168         if (indent)
1169                 setIndent(textLayoutModule->indentCO->currentIndex());
1170 }
1171
1172
1173 void GuiDocument::setSkip(int item)
1174 {
1175         bool const enable = (item == 3);
1176         textLayoutModule->skipLE->setEnabled(enable);
1177         textLayoutModule->skipLengthCO->setEnabled(enable);
1178         isValid();
1179 }
1180
1181
1182 void GuiDocument::enableSkip(bool skip)
1183 {
1184         textLayoutModule->indentLE->setEnabled(!skip);
1185         textLayoutModule->indentLengthCO->setEnabled(!skip);
1186         if (skip)
1187                 setSkip(textLayoutModule->skipCO->currentIndex());
1188 }
1189
1190
1191 void GuiDocument::portraitChanged()
1192 {
1193         setMargins(pageLayoutModule->papersizeCO->currentIndex());
1194 }
1195
1196
1197 void GuiDocument::setMargins(bool custom)
1198 {
1199         bool const extern_geometry =
1200                 documentClass().provides("geometry");
1201         marginsModule->marginCB->setEnabled(!extern_geometry);
1202         if (extern_geometry) {
1203                 marginsModule->marginCB->setChecked(false);
1204                 setCustomMargins(true);
1205                 return;
1206         }
1207         marginsModule->marginCB->setChecked(custom);
1208         setCustomMargins(custom);
1209 }
1210
1211
1212 void GuiDocument::papersizeChanged(int paper_size)
1213 {
1214         setCustomPapersize(paper_size == 1);
1215 }
1216
1217
1218 void GuiDocument::setCustomPapersize(bool custom)
1219 {
1220         pageLayoutModule->paperwidthL->setEnabled(custom);
1221         pageLayoutModule->paperwidthLE->setEnabled(custom);
1222         pageLayoutModule->paperwidthUnitCO->setEnabled(custom);
1223         pageLayoutModule->paperheightL->setEnabled(custom);
1224         pageLayoutModule->paperheightLE->setEnabled(custom);
1225         pageLayoutModule->paperheightLE->setFocus();
1226         pageLayoutModule->paperheightUnitCO->setEnabled(custom);
1227 }
1228
1229
1230 void GuiDocument::setColSep()
1231 {
1232         setCustomMargins(marginsModule->marginCB->checkState() == Qt::Checked);
1233 }
1234
1235
1236 void GuiDocument::setCustomMargins(bool custom)
1237 {
1238         marginsModule->topL->setEnabled(!custom);
1239         marginsModule->topLE->setEnabled(!custom);
1240         marginsModule->topUnit->setEnabled(!custom);
1241
1242         marginsModule->bottomL->setEnabled(!custom);
1243         marginsModule->bottomLE->setEnabled(!custom);
1244         marginsModule->bottomUnit->setEnabled(!custom);
1245
1246         marginsModule->innerL->setEnabled(!custom);
1247         marginsModule->innerLE->setEnabled(!custom);
1248         marginsModule->innerUnit->setEnabled(!custom);
1249
1250         marginsModule->outerL->setEnabled(!custom);
1251         marginsModule->outerLE->setEnabled(!custom);
1252         marginsModule->outerUnit->setEnabled(!custom);
1253
1254         marginsModule->headheightL->setEnabled(!custom);
1255         marginsModule->headheightLE->setEnabled(!custom);
1256         marginsModule->headheightUnit->setEnabled(!custom);
1257
1258         marginsModule->headsepL->setEnabled(!custom);
1259         marginsModule->headsepLE->setEnabled(!custom);
1260         marginsModule->headsepUnit->setEnabled(!custom);
1261
1262         marginsModule->footskipL->setEnabled(!custom);
1263         marginsModule->footskipLE->setEnabled(!custom);
1264         marginsModule->footskipUnit->setEnabled(!custom);
1265
1266         bool const enableColSep = !custom && 
1267                         textLayoutModule->twoColumnCB->checkState() == Qt::Checked;
1268         marginsModule->columnsepL->setEnabled(enableColSep);
1269         marginsModule->columnsepLE->setEnabled(enableColSep);
1270         marginsModule->columnsepUnit->setEnabled(enableColSep);
1271 }
1272
1273 void GuiDocument::changeBackgroundColor()
1274 {
1275         QColor const & newColor = QColorDialog::getColor(
1276                 rgb2qcolor(set_backgroundcolor), asQWidget());
1277         if (!newColor.isValid())
1278                 return;
1279         // set the button color
1280         pageLayoutModule->backgroundPB->setStyleSheet(
1281                 colorButtonStyleSheet(newColor));
1282         // save color
1283         set_backgroundcolor = rgbFromHexName(fromqstr(newColor.name()));
1284         changed();
1285 }
1286
1287
1288 void GuiDocument::deleteBackgroundColor()
1289 {
1290         // set the button color back to white
1291         pageLayoutModule->backgroundPB->setStyleSheet(
1292                 colorButtonStyleSheet(QColor(Qt::white)));
1293         // save white as the set color
1294         set_backgroundcolor = rgbFromHexName("#ffffff");
1295         changed();
1296 }
1297
1298
1299 void GuiDocument::xetexChanged(bool xetex)
1300 {
1301         updateFontlist();
1302         updateDefaultFormat();
1303         langModule->encodingCO->setEnabled(!xetex &&
1304                 !langModule->defaultencodingRB->isChecked());
1305         langModule->defaultencodingRB->setEnabled(!xetex);
1306         langModule->otherencodingRB->setEnabled(!xetex);
1307
1308         fontModule->fontsDefaultCO->setEnabled(!xetex);
1309         fontModule->fontsDefaultLA->setEnabled(!xetex);
1310         fontModule->cjkFontLE->setEnabled(!xetex);
1311         fontModule->cjkFontLA->setEnabled(!xetex);
1312         string font;
1313         if (!xetex)
1314                 font = tex_fonts_sans[fontModule->fontsSansCO->currentIndex()];
1315         bool scaleable = providesScale(font);
1316         fontModule->scaleSansSB->setEnabled(scaleable);
1317         fontModule->scaleSansLA->setEnabled(scaleable);
1318         if (!xetex)
1319                 font = tex_fonts_monospaced[fontModule->fontsTypewriterCO->currentIndex()];
1320         scaleable = providesScale(font);
1321         fontModule->scaleTypewriterSB->setEnabled(scaleable);
1322         fontModule->scaleTypewriterLA->setEnabled(scaleable);
1323         if (!xetex)
1324                 font = tex_fonts_roman[fontModule->fontsRomanCO->currentIndex()];
1325         fontModule->fontScCB->setEnabled(providesSC(font));
1326         fontModule->fontOsfCB->setEnabled(providesOSF(font));
1327 }
1328
1329
1330 void GuiDocument::updateFontsize(string const & items, string const & sel)
1331 {
1332         fontModule->fontsizeCO->clear();
1333         fontModule->fontsizeCO->addItem(qt_("Default"));
1334
1335         for (int n = 0; !token(items,'|',n).empty(); ++n)
1336                 fontModule->fontsizeCO->
1337                         addItem(toqstr(token(items,'|',n)));
1338
1339         for (int n = 0; n < fontModule->fontsizeCO->count(); ++n) {
1340                 if (fromqstr(fontModule->fontsizeCO->itemText(n)) == sel) {
1341                         fontModule->fontsizeCO->setCurrentIndex(n);
1342                         break;
1343                 }
1344         }
1345 }
1346
1347
1348 void GuiDocument::updateFontlist()
1349 {
1350         fontModule->fontsRomanCO->clear();
1351         fontModule->fontsSansCO->clear();
1352         fontModule->fontsTypewriterCO->clear();
1353
1354         // With XeTeX, we have access to all system fonts, but not the LaTeX fonts
1355         if (outputModule->xetexCB->isChecked()) {
1356                 fontModule->fontsRomanCO->addItem(qt_("Default"));
1357                 fontModule->fontsSansCO->addItem(qt_("Default"));
1358                 fontModule->fontsTypewriterCO->addItem(qt_("Default"));
1359         
1360                 QFontDatabase fontdb;
1361                 QStringList families(fontdb.families());
1362                 for (QStringList::Iterator it = families.begin(); it != families.end(); ++it) {
1363                         fontModule->fontsRomanCO->addItem(*it);
1364                         fontModule->fontsSansCO->addItem(*it);
1365                         fontModule->fontsTypewriterCO->addItem(*it);
1366                 }
1367                 return;
1368         }
1369
1370         for (int n = 0; tex_fonts_roman[n][0]; ++n) {
1371                 QString font = qt_(tex_fonts_roman_gui[n]);
1372                 if (!isFontAvailable(tex_fonts_roman[n]))
1373                         font += qt_(" (not installed)");
1374                 fontModule->fontsRomanCO->addItem(font);
1375         }
1376         for (int n = 0; tex_fonts_sans[n][0]; ++n) {
1377                 QString font = qt_(tex_fonts_sans_gui[n]);
1378                 if (!isFontAvailable(tex_fonts_sans[n]))
1379                         font += qt_(" (not installed)");
1380                 fontModule->fontsSansCO->addItem(font);
1381         }
1382         for (int n = 0; tex_fonts_monospaced[n][0]; ++n) {
1383                 QString font = qt_(tex_fonts_monospaced_gui[n]);
1384                 if (!isFontAvailable(tex_fonts_monospaced[n]))
1385                         font += qt_(" (not installed)");
1386                 fontModule->fontsTypewriterCO->addItem(font);
1387         }
1388 }
1389
1390
1391 void GuiDocument::romanChanged(int item)
1392 {
1393         if (outputModule->xetexCB->isChecked())
1394                 return;
1395         string const font = tex_fonts_roman[item];
1396         fontModule->fontScCB->setEnabled(providesSC(font));
1397         fontModule->fontOsfCB->setEnabled(providesOSF(font));
1398 }
1399
1400
1401 void GuiDocument::sansChanged(int item)
1402 {
1403         if (outputModule->xetexCB->isChecked())
1404                 return;
1405         string const font = tex_fonts_sans[item];
1406         bool scaleable = providesScale(font);
1407         fontModule->scaleSansSB->setEnabled(scaleable);
1408         fontModule->scaleSansLA->setEnabled(scaleable);
1409 }
1410
1411
1412 void GuiDocument::ttChanged(int item)
1413 {
1414         if (outputModule->xetexCB->isChecked())
1415                 return;
1416         string const font = tex_fonts_monospaced[item];
1417         bool scaleable = providesScale(font);
1418         fontModule->scaleTypewriterSB->setEnabled(scaleable);
1419         fontModule->scaleTypewriterLA->setEnabled(scaleable);
1420 }
1421
1422
1423 void GuiDocument::updatePagestyle(string const & items, string const & sel)
1424 {
1425         pagestyles.clear();
1426         pageLayoutModule->pagestyleCO->clear();
1427         pageLayoutModule->pagestyleCO->addItem(qt_("Default"));
1428
1429         for (int n = 0; !token(items, '|', n).empty(); ++n) {
1430                 string style = token(items, '|', n);
1431                 QString style_gui = qt_(style);
1432                 pagestyles.push_back(pair<string, QString>(style, style_gui));
1433                 pageLayoutModule->pagestyleCO->addItem(style_gui);
1434         }
1435
1436         if (sel == "default") {
1437                 pageLayoutModule->pagestyleCO->setCurrentIndex(0);
1438                 return;
1439         }
1440
1441         int nn = 0;
1442
1443         for (size_t i = 0; i < pagestyles.size(); ++i)
1444                 if (pagestyles[i].first == sel)
1445                         nn = pageLayoutModule->pagestyleCO->findText(pagestyles[i].second);
1446
1447         if (nn > 0)
1448                 pageLayoutModule->pagestyleCO->setCurrentIndex(nn);
1449 }
1450
1451
1452 void GuiDocument::browseLayout()
1453 {
1454         QString const label1 = qt_("Layouts|#o#O");
1455         QString const dir1 = toqstr(lyxrc.document_path);
1456         QStringList const filter(qt_("LyX Layout (*.layout)"));
1457         QString file = browseRelFile(QString(), bufferFilepath(),
1458                 qt_("Local layout file"), filter, false,
1459                 label1, dir1);
1460
1461         if (!file.endsWith(".layout"))
1462                 return;
1463
1464         FileName layoutFile = support::makeAbsPath(fromqstr(file),
1465                 fromqstr(bufferFilepath()));
1466         
1467         int const ret = Alert::prompt(_("Local layout file"),
1468                 _("The layout file you have selected is a local layout\n"
1469                   "file, not one in the system or user directory. Your\n"
1470                   "document may not work with this layout if you do not\n"
1471                   "keep the layout file in the document directory."),
1472                   1, 1, _("&Set Layout"), _("&Cancel"));
1473         if (ret == 1)
1474                 return;
1475
1476         // load the layout file
1477         LayoutFileList & bcl = LayoutFileList::get();
1478         string classname = layoutFile.onlyFileName();
1479         // this will update an existing layout if that layout has been loaded before.
1480         LayoutFileIndex name = bcl.addLocalLayout(
1481                 classname.substr(0, classname.size() - 7),
1482                 layoutFile.onlyPath().absFilename());
1483
1484         if (name.empty()) {
1485                 Alert::error(_("Error"),
1486                         _("Unable to read local layout file."));                
1487                 return;
1488         }
1489
1490         // do not trigger classChanged if there is no change.
1491         if (latexModule->classCO->currentText() == toqstr(name))
1492                 return;
1493                 
1494         // add to combo box
1495         int idx = latexModule->classCO->findText(toqstr(name));
1496         if (idx == -1) {
1497                 classes_model_.insertRow(0, toqstr(name), name);
1498                 latexModule->classCO->setCurrentIndex(0);
1499         } else
1500                 latexModule->classCO->setCurrentIndex(idx);
1501         
1502         classChanged();
1503 }
1504
1505
1506 void GuiDocument::browseMaster()
1507 {
1508         QString const title = qt_("Select master document");
1509         QString const dir1 = toqstr(lyxrc.document_path);
1510         QString const old = latexModule->childDocLE->text();
1511         QString const docpath = toqstr(support::onlyPath(buffer().absFileName()));
1512         QStringList const filter(qt_("LyX Files (*.lyx)"));
1513         QString file = browseRelFile(old, docpath, title, filter, false,
1514                 qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
1515
1516         latexModule->childDocLE->setText(file);
1517 }
1518
1519
1520 void GuiDocument::classChanged()
1521 {
1522         int idx = latexModule->classCO->currentIndex();
1523         if (idx < 0) 
1524                 return;
1525         string const classname = classes_model_.getIDString(idx);
1526
1527         // check whether the selected modules have changed.
1528         bool modules_changed = false;
1529         unsigned int const srows = selectedModel()->rowCount();
1530         if (srows != bp_.getModules().size())
1531                 modules_changed = true;
1532         else {
1533                 list<string>::const_iterator mit = bp_.getModules().begin();
1534                 list<string>::const_iterator men = bp_.getModules().end();
1535                 for (unsigned int i = 0; i < srows && mit != men; ++i, ++mit)
1536                         if (selectedModel()->getIDString(i) != *mit) {
1537                                 modules_changed = true;
1538                                 break;
1539                         }
1540         }
1541
1542         if (modules_changed || lyxrc.auto_reset_options) {
1543                 if (applyPB->isEnabled()) {
1544                         int const ret = Alert::prompt(_("Unapplied changes"),
1545                                         _("Some changes in the dialog were not yet applied.\n"
1546                                         "If you do not apply now, they will be lost after this action."),
1547                                         1, 1, _("&Apply"), _("&Dismiss"));
1548                         if (ret == 0)
1549                                 applyView();
1550                 }
1551         }
1552
1553         // We load the TextClass as soon as it is selected. This is
1554         // necessary so that other options in the dialog can be updated
1555         // according to the new class. Note, however, that, if you use 
1556         // the scroll wheel when sitting on the combo box, we'll load a 
1557         // lot of TextClass objects very quickly....
1558         if (!bp_.setBaseClass(classname)) {
1559                 Alert::error(_("Error"), _("Unable to set document class."));
1560                 return;
1561         }
1562         if (lyxrc.auto_reset_options)
1563                 bp_.useClassDefaults();
1564
1565         // With the introduction of modules came a distinction between the base 
1566         // class and the document class. The former corresponds to the main layout 
1567         // file; the latter is that plus the modules (or the document-specific layout,
1568         // or  whatever else there could be). Our parameters come from the document 
1569         // class. So when we set the base class, we also need to recreate the document 
1570         // class. Otherwise, we still have the old one.
1571         bp_.makeDocumentClass();
1572         paramsToDialog();
1573 }
1574
1575
1576 void GuiDocument::bibtexChanged(int n)
1577 {
1578         biblioModule->bibtexOptionsED->setEnabled(n != 0);
1579         changed();
1580 }
1581
1582
1583 namespace {
1584         // This is an insanely complicated attempt to make this sort of thing
1585         // work with RTL languages.
1586         docstring formatStrVec(vector<string> const & v, docstring const & s) 
1587         {
1588                 //this mess formats the list as "v[0], v[1], ..., [s] v[n]"
1589                 if (v.size() == 0)
1590                         return docstring();
1591                 if (v.size() == 1) 
1592                         return from_utf8(v[0]);
1593                 if (v.size() == 2) {
1594                         docstring retval = _("%1$s and %2$s");
1595                         retval = subst(retval, _("and"), s);
1596                         return bformat(retval, from_utf8(v[0]), from_utf8(v[1]));
1597                 }
1598                 // The idea here is to format all but the last two items...
1599                 int const vSize = v.size();
1600                 docstring t2 = _("%1$s, %2$s");
1601                 docstring retval = from_utf8(v[0]);
1602                 for (int i = 1; i < vSize - 2; ++i)
1603                         retval = bformat(t2, retval, from_utf8(v[i])); 
1604                 //...and then to  plug them, and the last two, into this schema
1605                 docstring t = _("%1$s, %2$s, and %3$s");
1606                 t = subst(t, _("and"), s);
1607                 return bformat(t, retval, from_utf8(v[vSize - 2]), from_utf8(v[vSize - 1]));
1608         }
1609         
1610         vector<string> idsToNames(vector<string> const & idList)
1611         {
1612                 vector<string> retval;
1613                 vector<string>::const_iterator it  = idList.begin();
1614                 vector<string>::const_iterator end = idList.end();
1615                 for (; it != end; ++it) {
1616                         LyXModule const * const mod = theModuleList[*it];
1617                         if (!mod)
1618                                 retval.push_back(*it + " (Unavailable)");
1619                         else
1620                                 retval.push_back(mod->getName());
1621                 }
1622                 return retval;
1623         }
1624 }
1625
1626
1627 void GuiDocument::modulesToParams(BufferParams & bp)
1628 {
1629         // update list of loaded modules
1630         bp.clearLayoutModules();
1631         int const srows = modules_sel_model_.rowCount();
1632         for (int i = 0; i < srows; ++i)
1633                 bp.addLayoutModule(modules_sel_model_.getIDString(i));
1634
1635         // update the list of removed modules
1636         bp.clearRemovedModules();
1637         LayoutModuleList const & reqmods = bp.baseClass()->defaultModules();
1638         list<string>::const_iterator rit = reqmods.begin();
1639         list<string>::const_iterator ren = reqmods.end();
1640
1641         // check each of the default modules
1642         for (; rit != ren; rit++) {
1643                 list<string>::const_iterator mit = bp.getModules().begin();
1644                 list<string>::const_iterator men = bp.getModules().end();
1645                 bool found = false;
1646                 for (; mit != men; mit++) {
1647                         if (*rit == *mit) {
1648                                 found = true;
1649                                 break;
1650                         }
1651                 }
1652                 if (!found) {
1653                         // the module isn't present so must have been removed by the user
1654                         bp.addRemovedModule(*rit);
1655                 }
1656         }
1657 }
1658
1659 void GuiDocument::modulesChanged()
1660 {
1661         modulesToParams(bp_);
1662         bp_.makeDocumentClass();
1663         paramsToDialog();
1664 }
1665
1666
1667 void GuiDocument::updateModuleInfo()
1668 {
1669         selectionManager->update();
1670         
1671         //Module description
1672         bool const focus_on_selected = selectionManager->selectedFocused();
1673         QAbstractItemView * lv;
1674         if (focus_on_selected)
1675                 lv = modulesModule->selectedLV;
1676         else
1677                 lv= modulesModule->availableLV;
1678         if (lv->selectionModel()->selectedIndexes().isEmpty()) {
1679                 modulesModule->infoML->document()->clear();
1680                 return;
1681         }
1682         QModelIndex const & idx = lv->selectionModel()->currentIndex();
1683         GuiIdListModel const & id_model = 
1684                         focus_on_selected  ? modules_sel_model_ : modules_av_model_;
1685         string const modName = id_model.getIDString(idx.row());
1686         docstring desc = getModuleDescription(modName);
1687
1688         LayoutModuleList const & provmods = bp_.baseClass()->providedModules();
1689         if (std::find(provmods.begin(), provmods.end(), modName) != provmods.end()) {
1690                 if (!desc.empty())
1691                         desc += "\n";
1692                 desc += _("Module provided by document class.");
1693         }
1694
1695         vector<string> pkglist = getPackageList(modName);
1696         docstring pkgdesc = formatStrVec(pkglist, _("and"));
1697         if (!pkgdesc.empty()) {
1698                 if (!desc.empty())
1699                         desc += "\n";
1700                 desc += bformat(_("Package(s) required: %1$s."), pkgdesc);
1701         }
1702
1703         pkglist = getRequiredList(modName);
1704         if (!pkglist.empty()) {
1705                 vector<string> const reqdescs = idsToNames(pkglist);
1706                 pkgdesc = formatStrVec(reqdescs, _("or"));
1707                 if (!desc.empty())
1708                         desc += "\n";
1709                 desc += bformat(_("Module required: %1$s."), pkgdesc);
1710         }
1711
1712         pkglist = getExcludedList(modName);
1713         if (!pkglist.empty()) {
1714                 vector<string> const reqdescs = idsToNames(pkglist);
1715                 pkgdesc = formatStrVec(reqdescs, _( "and"));
1716                 if (!desc.empty())
1717                         desc += "\n";
1718                 desc += bformat(_("Modules excluded: %1$s."), pkgdesc);
1719         }
1720
1721         if (!isModuleAvailable(modName)) {
1722                 if (!desc.empty())
1723                         desc += "\n";
1724                 desc += _("WARNING: Some required packages are unavailable!");
1725         }
1726
1727         modulesModule->infoML->document()->setPlainText(toqstr(desc));
1728 }
1729
1730
1731 void GuiDocument::updateNumbering()
1732 {
1733         DocumentClass const & tclass = documentClass();
1734
1735         numberingModule->tocTW->setUpdatesEnabled(false);
1736         numberingModule->tocTW->clear();
1737
1738         int const depth = numberingModule->depthSL->value();
1739         int const toc = numberingModule->tocSL->value();
1740         QString const no = qt_("No");
1741         QString const yes = qt_("Yes");
1742         QTreeWidgetItem * item = 0;
1743
1744         DocumentClass::const_iterator lit = tclass.begin();
1745         DocumentClass::const_iterator len = tclass.end();
1746         for (; lit != len; ++lit) {
1747                 int const toclevel = lit->toclevel;
1748                 if (toclevel != Layout::NOT_IN_TOC && lit->labeltype == LABEL_COUNTER) {
1749                         item = new QTreeWidgetItem(numberingModule->tocTW);
1750                         item->setText(0, toqstr(translateIfPossible(lit->name())));
1751                         item->setText(1, (toclevel <= depth) ? yes : no);
1752                         item->setText(2, (toclevel <= toc) ? yes : no);
1753                 }
1754         }
1755
1756         numberingModule->tocTW->setUpdatesEnabled(true);
1757         numberingModule->tocTW->update();
1758 }
1759
1760
1761 void GuiDocument::updateDefaultFormat()
1762 {
1763         // make a copy in order to consider unapplied changes
1764         Buffer * tmpbuf = const_cast<Buffer *>(&buffer());
1765         tmpbuf->params().useXetex = outputModule->xetexCB->isChecked();
1766         int idx = latexModule->classCO->currentIndex();
1767         if (idx >= 0) {
1768                 string const classname = classes_model_.getIDString(idx);
1769                 tmpbuf->params().setBaseClass(classname);
1770                 tmpbuf->params().makeDocumentClass();
1771         }
1772         outputModule->defaultFormatCO->blockSignals(true);
1773         outputModule->defaultFormatCO->clear();
1774         outputModule->defaultFormatCO->addItem(qt_("Default"),
1775                                 QVariant(QString("default")));
1776         typedef vector<Format const *> Formats;
1777         Formats formats = tmpbuf->exportableFormats(true);
1778         Formats::const_iterator cit = formats.begin();
1779         Formats::const_iterator end = formats.end();
1780         for (; cit != end; ++cit)
1781                 outputModule->defaultFormatCO->addItem(qt_((*cit)->prettyname()),
1782                                 QVariant(toqstr((*cit)->name())));
1783         outputModule->defaultFormatCO->blockSignals(false);
1784 }
1785
1786
1787 void GuiDocument::applyView()
1788 {
1789         // preamble
1790         preambleModule->apply(bp_);
1791
1792         // date
1793         bp_.suppress_date = latexModule->suppressDateCB->isChecked();
1794
1795         // biblio
1796         bp_.setCiteEngine(ENGINE_BASIC);
1797
1798         if (biblioModule->citeNatbibRB->isChecked()) {
1799                 bool const use_numerical_citations =
1800                         biblioModule->citeStyleCO->currentIndex();
1801                 if (use_numerical_citations)
1802                         bp_.setCiteEngine(ENGINE_NATBIB_NUMERICAL);
1803                 else
1804                         bp_.setCiteEngine(ENGINE_NATBIB_AUTHORYEAR);
1805
1806         } else if (biblioModule->citeJurabibRB->isChecked())
1807                 bp_.setCiteEngine(ENGINE_JURABIB);
1808
1809         bp_.use_bibtopic =
1810                 biblioModule->bibtopicCB->isChecked();
1811
1812         string const bibtex_command =
1813                 fromqstr(biblioModule->bibtexCO->itemData(
1814                         biblioModule->bibtexCO->currentIndex()).toString());
1815         string const bibtex_options =
1816                 fromqstr(biblioModule->bibtexOptionsED->text());
1817         if (bibtex_command == "default" || bibtex_options.empty())
1818                 bp_.bibtex_command = bibtex_command;
1819         else
1820                 bp_.bibtex_command = bibtex_command + " " + bibtex_options;
1821
1822         // Indices
1823         indicesModule->apply(bp_);
1824
1825         // language & quotes
1826         if (langModule->defaultencodingRB->isChecked()) {
1827                 bp_.inputenc = "auto";
1828         } else {
1829                 int i = langModule->encodingCO->currentIndex();
1830                 if (i == 0)
1831                         bp_.inputenc = "default";
1832                 else {
1833                         QString const enc_gui =
1834                                 langModule->encodingCO->currentText();
1835                         Encodings::const_iterator it = encodings.begin();
1836                         Encodings::const_iterator const end = encodings.end();
1837                         bool found = false;
1838                         for (; it != end; ++it) {
1839                                 if (qt_(it->guiName()) == enc_gui) {
1840                                         bp_.inputenc = it->latexName();
1841                                         found = true;
1842                                         break;
1843                                 }
1844                         }
1845                         if (!found) {
1846                                 // should not happen
1847                                 lyxerr << "GuiDocument::apply: Unknown encoding! Resetting to default" << endl;
1848                                 bp_.inputenc = "default";
1849                         }
1850                 }
1851         }
1852
1853         InsetQuotes::QuoteLanguage lga = InsetQuotes::EnglishQuotes;
1854         switch (langModule->quoteStyleCO->currentIndex()) {
1855         case 0:
1856                 lga = InsetQuotes::EnglishQuotes;
1857                 break;
1858         case 1:
1859                 lga = InsetQuotes::SwedishQuotes;
1860                 break;
1861         case 2:
1862                 lga = InsetQuotes::GermanQuotes;
1863                 break;
1864         case 3:
1865                 lga = InsetQuotes::PolishQuotes;
1866                 break;
1867         case 4:
1868                 lga = InsetQuotes::FrenchQuotes;
1869                 break;
1870         case 5:
1871                 lga = InsetQuotes::DanishQuotes;
1872                 break;
1873         }
1874         bp_.quotes_language = lga;
1875
1876         QString const lang = langModule->languageCO->itemData(
1877                 langModule->languageCO->currentIndex()).toString();
1878         bp_.language = lyx::languages.getLanguage(fromqstr(lang));
1879
1880         // numbering
1881         if (bp_.documentClass().hasTocLevels()) {
1882                 bp_.tocdepth = numberingModule->tocSL->value();
1883                 bp_.secnumdepth = numberingModule->depthSL->value();
1884         }
1885
1886         // bullets
1887         bp_.user_defined_bullet(0) = bulletsModule->bullet(0);
1888         bp_.user_defined_bullet(1) = bulletsModule->bullet(1);
1889         bp_.user_defined_bullet(2) = bulletsModule->bullet(2);
1890         bp_.user_defined_bullet(3) = bulletsModule->bullet(3);
1891
1892         // packages
1893         bp_.graphicsDriver =
1894                 tex_graphics[latexModule->psdriverCO->currentIndex()];
1895         
1896         // text layout
1897         int idx = latexModule->classCO->currentIndex();
1898         if (idx >= 0) {
1899                 string const classname = classes_model_.getIDString(idx);
1900                 bp_.setBaseClass(classname);
1901         }
1902
1903         // Modules
1904         modulesToParams(bp_);
1905
1906         // Math
1907         if (mathsModule->amsautoCB->isChecked()) {
1908                 bp_.use_amsmath = BufferParams::package_auto;
1909         } else {
1910                 if (mathsModule->amsCB->isChecked())
1911                         bp_.use_amsmath = BufferParams::package_on;
1912                 else
1913                         bp_.use_amsmath = BufferParams::package_off;
1914         }
1915         if (mathsModule->esintautoCB->isChecked())
1916                 bp_.use_esint = BufferParams::package_auto;
1917         else {
1918                 if (mathsModule->esintCB->isChecked())
1919                         bp_.use_esint = BufferParams::package_on;
1920                 else
1921                         bp_.use_esint = BufferParams::package_off;
1922         }
1923         if (mathsModule->mhchemautoCB->isChecked())
1924                 bp_.use_mhchem = BufferParams::package_auto;
1925         else {
1926                 if (mathsModule->mhchemCB->isChecked())
1927                         bp_.use_mhchem = BufferParams::package_on;
1928                 else
1929                         bp_.use_mhchem = BufferParams::package_off;
1930         }
1931
1932         // Page Layout
1933         if (pageLayoutModule->pagestyleCO->currentIndex() == 0)
1934                 bp_.pagestyle = "default";
1935         else {
1936                 QString style_gui = pageLayoutModule->pagestyleCO->currentText();
1937                 for (size_t i = 0; i != pagestyles.size(); ++i)
1938                         if (pagestyles[i].second == style_gui)
1939                                 bp_.pagestyle = pagestyles[i].first;
1940         }
1941
1942         // Text Layout
1943         switch (textLayoutModule->lspacingCO->currentIndex()) {
1944         case 0:
1945                 bp_.spacing().set(Spacing::Single);
1946                 break;
1947         case 1:
1948                 bp_.spacing().set(Spacing::Onehalf);
1949                 break;
1950         case 2:
1951                 bp_.spacing().set(Spacing::Double);
1952                 break;
1953         case 3:
1954                 bp_.spacing().set(Spacing::Other,
1955                         widgetToDoubleStr(textLayoutModule->lspacingLE));
1956                 break;
1957         }
1958
1959         if (textLayoutModule->twoColumnCB->isChecked())
1960                 bp_.columns = 2;
1961         else
1962                 bp_.columns = 1;
1963
1964         if (textLayoutModule->indentRB->isChecked()) {
1965                 // if paragraphs are separated by an indentation
1966                 bp_.paragraph_separation = BufferParams::ParagraphIndentSeparation;
1967                 switch (textLayoutModule->indentCO->currentIndex()) {
1968                 case 0:
1969                         bp_.setIndentation(HSpace(HSpace::DEFAULT));
1970                         break;
1971                 case 1: {
1972                         HSpace indent = HSpace(
1973                                 widgetsToLength(textLayoutModule->indentLE,
1974                                 textLayoutModule->indentLengthCO)
1975                                 );
1976                         bp_.setIndentation(indent);
1977                         break;
1978                         }
1979                 default:
1980                         // this should never happen
1981                         bp_.setIndentation(HSpace(HSpace::DEFAULT));
1982                         break;
1983                 }
1984         } else {
1985                 // if paragraphs are separated by a skip
1986                 bp_.paragraph_separation = BufferParams::ParagraphSkipSeparation;
1987                 switch (textLayoutModule->skipCO->currentIndex()) {
1988                 case 0:
1989                         bp_.setDefSkip(VSpace(VSpace::SMALLSKIP));
1990                         break;
1991                 case 1:
1992                         bp_.setDefSkip(VSpace(VSpace::MEDSKIP));
1993                         break;
1994                 case 2:
1995                         bp_.setDefSkip(VSpace(VSpace::BIGSKIP));
1996                         break;
1997                 case 3:
1998                         {
1999                         VSpace vs = VSpace(
2000                                 widgetsToLength(textLayoutModule->skipLE,
2001                                 textLayoutModule->skipLengthCO)
2002                                 );
2003                         bp_.setDefSkip(vs);
2004                         break;
2005                         }
2006                 default:
2007                         // this should never happen
2008                         bp_.setDefSkip(VSpace(VSpace::MEDSKIP));
2009                         break;
2010                 }
2011         }
2012
2013         bp_.options =
2014                 fromqstr(latexModule->optionsLE->text());
2015
2016         bp_.use_default_options =
2017                 latexModule->defaultOptionsCB->isChecked();
2018
2019         if (latexModule->childDocGB->isChecked())
2020                 bp_.master =
2021                         fromqstr(latexModule->childDocLE->text());
2022         else
2023                 bp_.master = string();
2024
2025         // Float Placement
2026         bp_.float_placement = floatModule->get();
2027
2028         // Listings
2029         // text should have passed validation
2030         bp_.listings_params =
2031                 InsetListingsParams(fromqstr(listingsModule->listingsED->toPlainText())).params();
2032
2033         // output
2034         bp_.defaultOutputFormat = fromqstr(outputModule->defaultFormatCO->itemData(
2035                 outputModule->defaultFormatCO->currentIndex()).toString());
2036
2037         bool const xetex = outputModule->xetexCB->isChecked();
2038         bp_.useXetex = xetex;
2039
2040         // fonts
2041         if (xetex) {
2042                 if (fontModule->fontsRomanCO->currentIndex() == 0)
2043                         bp_.fontsRoman = "default";
2044                 else
2045                         bp_.fontsRoman =
2046                                 fromqstr(fontModule->fontsRomanCO->currentText());
2047         
2048                 if (fontModule->fontsSansCO->currentIndex() == 0)
2049                         bp_.fontsSans = "default";
2050                 else
2051                         bp_.fontsSans =
2052                                 fromqstr(fontModule->fontsSansCO->currentText());
2053         
2054                 if (fontModule->fontsTypewriterCO->currentIndex() == 0)
2055                         bp_.fontsTypewriter = "default";
2056                 else
2057                         bp_.fontsTypewriter =
2058                                 fromqstr(fontModule->fontsTypewriterCO->currentText());
2059         } else {
2060                 bp_.fontsRoman =
2061                         tex_fonts_roman[fontModule->fontsRomanCO->currentIndex()];
2062         
2063                 bp_.fontsSans =
2064                         tex_fonts_sans[fontModule->fontsSansCO->currentIndex()];
2065         
2066                 bp_.fontsTypewriter =
2067                         tex_fonts_monospaced[fontModule->fontsTypewriterCO->currentIndex()];
2068         }
2069
2070         bp_.fontsCJK =
2071                 fromqstr(fontModule->cjkFontLE->text());
2072
2073         bp_.fontsSansScale = fontModule->scaleSansSB->value();
2074
2075         bp_.fontsTypewriterScale = fontModule->scaleTypewriterSB->value();
2076
2077         bp_.fontsSC = fontModule->fontScCB->isChecked();
2078
2079         bp_.fontsOSF = fontModule->fontOsfCB->isChecked();
2080
2081         if (xetex)
2082                 bp_.fontsDefaultFamily = "default";
2083         else
2084                 bp_.fontsDefaultFamily = GuiDocument::fontfamilies[
2085                         fontModule->fontsDefaultCO->currentIndex()];
2086
2087         if (fontModule->fontsizeCO->currentIndex() == 0)
2088                 bp_.fontsize = "default";
2089         else
2090                 bp_.fontsize =
2091                         fromqstr(fontModule->fontsizeCO->currentText());
2092
2093         // paper
2094         bp_.papersize = PAPER_SIZE(
2095                 pageLayoutModule->papersizeCO->currentIndex());
2096
2097         // custom, A3, B3 and B4 paper sizes need geometry
2098         int psize = pageLayoutModule->papersizeCO->currentIndex();
2099         bool geom_papersize = (psize == 1 || psize == 5 || psize == 8 || psize == 9);
2100
2101         bp_.paperwidth = widgetsToLength(pageLayoutModule->paperwidthLE,
2102                 pageLayoutModule->paperwidthUnitCO);
2103
2104         bp_.paperheight = widgetsToLength(pageLayoutModule->paperheightLE,
2105                 pageLayoutModule->paperheightUnitCO);
2106
2107         if (pageLayoutModule->facingPagesCB->isChecked())
2108                 bp_.sides = TwoSides;
2109         else
2110                 bp_.sides = OneSide;
2111
2112         if (pageLayoutModule->landscapeRB->isChecked())
2113                 bp_.orientation = ORIENTATION_LANDSCAPE;
2114         else
2115                 bp_.orientation = ORIENTATION_PORTRAIT;
2116
2117         bp_.backgroundcolor = set_backgroundcolor;
2118
2119         // margins
2120         bp_.use_geometry = !marginsModule->marginCB->isChecked()
2121                 || geom_papersize;
2122
2123         Ui::MarginsUi const * m = marginsModule;
2124
2125         bp_.leftmargin = widgetsToLength(m->innerLE, m->innerUnit);
2126         bp_.topmargin = widgetsToLength(m->topLE, m->topUnit);
2127         bp_.rightmargin = widgetsToLength(m->outerLE, m->outerUnit);
2128         bp_.bottommargin = widgetsToLength(m->bottomLE, m->bottomUnit);
2129         bp_.headheight = widgetsToLength(m->headheightLE, m->headheightUnit);
2130         bp_.headsep = widgetsToLength(m->headsepLE, m->headsepUnit);
2131         bp_.footskip = widgetsToLength(m->footskipLE, m->footskipUnit);
2132         bp_.columnsep = widgetsToLength(m->columnsepLE, m->columnsepUnit);
2133
2134         // branches
2135         branchesModule->apply(bp_);
2136
2137         // PDF support
2138         PDFOptions & pdf = bp_.pdfoptions();
2139         pdf.use_hyperref = pdfSupportModule->use_hyperrefGB->isChecked();
2140         pdf.title = fromqstr(pdfSupportModule->titleLE->text());
2141         pdf.author = fromqstr(pdfSupportModule->authorLE->text());
2142         pdf.subject = fromqstr(pdfSupportModule->subjectLE->text());
2143         pdf.keywords = fromqstr(pdfSupportModule->keywordsLE->text());
2144
2145         pdf.bookmarks = pdfSupportModule->bookmarksGB->isChecked();
2146         pdf.bookmarksnumbered = pdfSupportModule->bookmarksnumberedCB->isChecked();
2147         pdf.bookmarksopen = pdfSupportModule->bookmarksopenGB->isChecked();
2148         pdf.bookmarksopenlevel = pdfSupportModule->bookmarksopenlevelSB->value();
2149
2150         pdf.breaklinks = pdfSupportModule->breaklinksCB->isChecked();
2151         pdf.pdfborder = pdfSupportModule->pdfborderCB->isChecked();
2152         pdf.pdfusetitle = pdfSupportModule->pdfusetitleCB->isChecked();
2153         pdf.colorlinks = pdfSupportModule->colorlinksCB->isChecked();
2154         pdf.backref =
2155                 backref_opts[pdfSupportModule->backrefCO->currentIndex()];
2156         if (pdfSupportModule->fullscreenCB->isChecked())
2157                 pdf.pagemode = pdf.pagemode_fullscreen;
2158         else
2159                 pdf.pagemode.clear();
2160         pdf.quoted_options = pdf.quoted_options_check(
2161                                 fromqstr(pdfSupportModule->optionsLE->text()));
2162 }
2163
2164
2165 void GuiDocument::paramsToDialog()
2166 {
2167         // set the default unit
2168         Length::UNIT const defaultUnit = Length::defaultUnit();
2169
2170         // preamble
2171         preambleModule->update(bp_, id());
2172
2173         // date
2174         latexModule->suppressDateCB->setChecked(bp_.suppress_date);
2175
2176         // biblio
2177         biblioModule->citeDefaultRB->setChecked(
2178                 bp_.citeEngine() == ENGINE_BASIC);
2179
2180         biblioModule->citeNatbibRB->setChecked(
2181                 bp_.citeEngine() == ENGINE_NATBIB_NUMERICAL ||
2182                 bp_.citeEngine() == ENGINE_NATBIB_AUTHORYEAR);
2183
2184         biblioModule->citeStyleCO->setCurrentIndex(
2185                 bp_.citeEngine() == ENGINE_NATBIB_NUMERICAL);
2186
2187         biblioModule->citeJurabibRB->setChecked(
2188                 bp_.citeEngine() == ENGINE_JURABIB);
2189
2190         biblioModule->bibtopicCB->setChecked(
2191                 bp_.use_bibtopic);
2192
2193         string command;
2194         string options =
2195                 split(bp_.bibtex_command, command, ' ');
2196
2197         int const bpos = biblioModule->bibtexCO->findData(toqstr(command));
2198         if (bpos != -1) {
2199                 biblioModule->bibtexCO->setCurrentIndex(bpos);
2200                 biblioModule->bibtexOptionsED->setText(toqstr(options).trimmed());
2201         } else {
2202                 biblioModule->bibtexCO->setCurrentIndex(0);
2203                 biblioModule->bibtexOptionsED->clear();
2204         }
2205         biblioModule->bibtexOptionsED->setEnabled(
2206                 biblioModule->bibtexCO->currentIndex() != 0);
2207
2208         // indices
2209         indicesModule->update(bp_);
2210
2211         // language & quotes
2212         int const pos = langModule->languageCO->findData(toqstr(
2213                 bp_.language->lang()));
2214         langModule->languageCO->setCurrentIndex(pos);
2215
2216         langModule->quoteStyleCO->setCurrentIndex(
2217                 bp_.quotes_language);
2218
2219         bool default_enc = true;
2220         if (bp_.inputenc != "auto") {
2221                 default_enc = false;
2222                 if (bp_.inputenc == "default") {
2223                         langModule->encodingCO->setCurrentIndex(0);
2224                 } else {
2225                         string enc_gui;
2226                         Encodings::const_iterator it = encodings.begin();
2227                         Encodings::const_iterator const end = encodings.end();
2228                         for (; it != end; ++it) {
2229                                 if (it->latexName() == bp_.inputenc) {
2230                                         enc_gui = it->guiName();
2231                                         break;
2232                                 }
2233                         }
2234                         int const i = langModule->encodingCO->findText(
2235                                         qt_(enc_gui));
2236                         if (i >= 0)
2237                                 langModule->encodingCO->setCurrentIndex(i);
2238                         else
2239                                 // unknown encoding. Set to default.
2240                                 default_enc = true;
2241                 }
2242         }
2243         langModule->defaultencodingRB->setChecked(default_enc);
2244         langModule->otherencodingRB->setChecked(!default_enc);
2245
2246         // numbering
2247         int const min_toclevel = documentClass().min_toclevel();
2248         int const max_toclevel = documentClass().max_toclevel();
2249         if (documentClass().hasTocLevels()) {
2250                 numberingModule->setEnabled(true);
2251                 numberingModule->depthSL->setMinimum(min_toclevel - 1);
2252                 numberingModule->depthSL->setMaximum(max_toclevel);
2253                 numberingModule->depthSL->setValue(bp_.secnumdepth);
2254                 numberingModule->tocSL->setMaximum(min_toclevel - 1);
2255                 numberingModule->tocSL->setMaximum(max_toclevel);
2256                 numberingModule->tocSL->setValue(bp_.tocdepth);
2257                 updateNumbering();
2258         } else {
2259                 numberingModule->setEnabled(false);
2260                 numberingModule->tocTW->clear();
2261         }
2262
2263         // bullets
2264         bulletsModule->setBullet(0, bp_.user_defined_bullet(0));
2265         bulletsModule->setBullet(1, bp_.user_defined_bullet(1));
2266         bulletsModule->setBullet(2, bp_.user_defined_bullet(2));
2267         bulletsModule->setBullet(3, bp_.user_defined_bullet(3));
2268         bulletsModule->init();
2269
2270         // packages
2271         int nitem = findToken(tex_graphics, bp_.graphicsDriver);
2272         if (nitem >= 0)
2273                 latexModule->psdriverCO->setCurrentIndex(nitem);
2274         updateModuleInfo();
2275         
2276         mathsModule->amsCB->setChecked(
2277                 bp_.use_amsmath == BufferParams::package_on);
2278         mathsModule->amsautoCB->setChecked(
2279                 bp_.use_amsmath == BufferParams::package_auto);
2280
2281         mathsModule->esintCB->setChecked(
2282                 bp_.use_esint == BufferParams::package_on);
2283         mathsModule->esintautoCB->setChecked(
2284                 bp_.use_esint == BufferParams::package_auto);
2285
2286         mathsModule->mhchemCB->setChecked(
2287                 bp_.use_mhchem == BufferParams::package_on);
2288         mathsModule->mhchemautoCB->setChecked(
2289                 bp_.use_mhchem == BufferParams::package_auto);
2290
2291         switch (bp_.spacing().getSpace()) {
2292                 case Spacing::Other: nitem = 3; break;
2293                 case Spacing::Double: nitem = 2; break;
2294                 case Spacing::Onehalf: nitem = 1; break;
2295                 case Spacing::Default: case Spacing::Single: nitem = 0; break;
2296         }
2297
2298         // text layout
2299         string const & layoutID = bp_.baseClassID();
2300         setLayoutComboByIDString(layoutID);
2301
2302         updatePagestyle(documentClass().opt_pagestyle(),
2303                                  bp_.pagestyle);
2304
2305         textLayoutModule->lspacingCO->setCurrentIndex(nitem);
2306         if (bp_.spacing().getSpace() == Spacing::Other) {
2307                 doubleToWidget(textLayoutModule->lspacingLE,
2308                         bp_.spacing().getValueAsString());
2309         }
2310         setLSpacing(nitem);
2311
2312         if (bp_.paragraph_separation == BufferParams::ParagraphIndentSeparation) {
2313                 textLayoutModule->indentRB->setChecked(true);
2314                 string indentation = bp_.getIndentation().asLyXCommand();
2315                 int indent = 0;
2316                 if (indentation != "default") {
2317                         lengthToWidgets(textLayoutModule->indentLE,
2318                         textLayoutModule->indentLengthCO,
2319                         indentation, defaultUnit);
2320                         indent = 1;
2321                 }
2322                 textLayoutModule->indentCO->setCurrentIndex(indent);
2323                 setIndent(indent);
2324         } else {
2325                 textLayoutModule->skipRB->setChecked(true);
2326                 int skip = 0;
2327                 switch (bp_.getDefSkip().kind()) {
2328                 case VSpace::SMALLSKIP:
2329                         skip = 0;
2330                         break;
2331                 case VSpace::MEDSKIP:
2332                         skip = 1;
2333                         break;
2334                 case VSpace::BIGSKIP:
2335                         skip = 2;
2336                         break;
2337                 case VSpace::LENGTH:
2338                         {
2339                         skip = 3;
2340                         string const length = bp_.getDefSkip().asLyXCommand();
2341                         lengthToWidgets(textLayoutModule->skipLE,
2342                                 textLayoutModule->skipLengthCO,
2343                                 length, defaultUnit);
2344                         break;
2345                         }
2346                 default:
2347                         skip = 0;
2348                         break;
2349                 }
2350                 textLayoutModule->skipCO->setCurrentIndex(skip);
2351                 setSkip(skip);
2352         }
2353
2354         textLayoutModule->twoColumnCB->setChecked(
2355                 bp_.columns == 2);
2356
2357         if (!bp_.options.empty()) {
2358                 latexModule->optionsLE->setText(
2359                         toqstr(bp_.options));
2360         } else {
2361                 latexModule->optionsLE->setText(QString());
2362         }
2363
2364         // latex
2365         latexModule->defaultOptionsCB->setChecked(
2366                         bp_.use_default_options);
2367         updateSelectedModules();
2368         selectionManager->updateProvidedModules(
2369                         bp_.baseClass()->providedModules());
2370         selectionManager->updateExcludedModules(
2371                         bp_.baseClass()->excludedModules());
2372
2373         if (!documentClass().options().empty()) {
2374                 latexModule->defaultOptionsLE->setText(
2375                         toqstr(documentClass().options()));
2376         } else {
2377                 latexModule->defaultOptionsLE->setText(
2378                         toqstr(_("[No options predefined]")));
2379         }
2380
2381         latexModule->defaultOptionsLE->setEnabled(
2382                 bp_.use_default_options
2383                 && !documentClass().options().empty());
2384
2385         latexModule->defaultOptionsCB->setEnabled(
2386                 !documentClass().options().empty());
2387
2388         if (!bp_.master.empty()) {
2389                 latexModule->childDocGB->setChecked(true);
2390                 latexModule->childDocLE->setText(
2391                         toqstr(bp_.master));
2392         } else {
2393                 latexModule->childDocLE->setText(QString());
2394                 latexModule->childDocGB->setChecked(false);
2395         }
2396
2397         // Float Settings
2398         floatModule->set(bp_.float_placement);
2399
2400         // ListingsSettings
2401         // break listings_params to multiple lines
2402         string lstparams =
2403                 InsetListingsParams(bp_.listings_params).separatedParams();
2404         listingsModule->listingsED->setPlainText(toqstr(lstparams));
2405
2406         // Output
2407         // update combobox with formats
2408         updateDefaultFormat();
2409         int index = outputModule->defaultFormatCO->findData(toqstr(
2410                 bp_.defaultOutputFormat));
2411         // set to default if format is not found 
2412         if (index == -1)
2413                 index = 0;
2414         outputModule->defaultFormatCO->setCurrentIndex(index);
2415         outputModule->xetexCB->setEnabled(bp_.baseClass()->outputType() == lyx::LATEX);
2416         outputModule->xetexCB->setChecked(
2417                 bp_.baseClass()->outputType() == lyx::LATEX && bp_.useXetex);
2418
2419         // Fonts
2420         updateFontsize(documentClass().opt_fontsize(),
2421                         bp_.fontsize);
2422
2423         if (bp_.useXetex) {
2424                 for (int i = 0; i < fontModule->fontsRomanCO->count(); ++i) {
2425                         if (fontModule->fontsRomanCO->itemText(i) == toqstr(bp_.fontsRoman)) {
2426                                 fontModule->fontsRomanCO->setCurrentIndex(i);
2427                                 return;
2428                         }
2429                 }
2430                 
2431                 for (int i = 0; i < fontModule->fontsSansCO->count(); ++i) {
2432                         if (fontModule->fontsSansCO->itemText(i) == toqstr(bp_.fontsSans)) {
2433                                 fontModule->fontsSansCO->setCurrentIndex(i);
2434                                 return;
2435                         }
2436                 }
2437                 for (int i = 0; i < fontModule->fontsTypewriterCO->count(); ++i) {
2438                         if (fontModule->fontsTypewriterCO->itemText(i) == 
2439                                 toqstr(bp_.fontsTypewriter)) {
2440                                 fontModule->fontsTypewriterCO->setCurrentIndex(i);
2441                                 return;
2442                         }
2443                 }
2444         } else {
2445                 int n = findToken(tex_fonts_roman, bp_.fontsRoman);
2446                 if (n >= 0) {
2447                         fontModule->fontsRomanCO->setCurrentIndex(n);
2448                         romanChanged(n);
2449                 }
2450         
2451                 n = findToken(tex_fonts_sans, bp_.fontsSans);
2452                 if (n >= 0) {
2453                         fontModule->fontsSansCO->setCurrentIndex(n);
2454                         sansChanged(n);
2455                 }
2456         
2457                 n = findToken(tex_fonts_monospaced, bp_.fontsTypewriter);
2458                 if (n >= 0) {
2459                         fontModule->fontsTypewriterCO->setCurrentIndex(n);
2460                         ttChanged(n);
2461                 }
2462         }
2463
2464         if (!bp_.fontsCJK.empty())
2465                 fontModule->cjkFontLE->setText(
2466                         toqstr(bp_.fontsCJK));
2467         else
2468                 fontModule->cjkFontLE->setText(QString());
2469
2470         fontModule->fontScCB->setChecked(bp_.fontsSC);
2471         fontModule->fontOsfCB->setChecked(bp_.fontsOSF);
2472         fontModule->scaleSansSB->setValue(bp_.fontsSansScale);
2473         fontModule->scaleTypewriterSB->setValue(bp_.fontsTypewriterScale);
2474
2475         int nn = findToken(GuiDocument::fontfamilies, bp_.fontsDefaultFamily);
2476         if (nn >= 0)
2477                 fontModule->fontsDefaultCO->setCurrentIndex(nn);
2478
2479         // paper
2480         bool const extern_geometry =
2481                 documentClass().provides("geometry");
2482         int const psize = bp_.papersize;
2483         pageLayoutModule->papersizeCO->setCurrentIndex(psize);
2484         setCustomPapersize(!extern_geometry && psize == 1);
2485         pageLayoutModule->papersizeCO->setEnabled(!extern_geometry);
2486
2487         bool const landscape =
2488                 bp_.orientation == ORIENTATION_LANDSCAPE;
2489         pageLayoutModule->landscapeRB->setChecked(landscape);
2490         pageLayoutModule->portraitRB->setChecked(!landscape);
2491         pageLayoutModule->landscapeRB->setEnabled(!extern_geometry);
2492         pageLayoutModule->portraitRB->setEnabled(!extern_geometry);
2493
2494         pageLayoutModule->facingPagesCB->setChecked(
2495                 bp_.sides == TwoSides);
2496
2497         pageLayoutModule->backgroundPB->setStyleSheet(
2498                 colorButtonStyleSheet(rgb2qcolor(bp_.backgroundcolor)));
2499         set_backgroundcolor = bp_.backgroundcolor;
2500
2501         lengthToWidgets(pageLayoutModule->paperwidthLE,
2502                 pageLayoutModule->paperwidthUnitCO, bp_.paperwidth, defaultUnit);
2503         lengthToWidgets(pageLayoutModule->paperheightLE,
2504                 pageLayoutModule->paperheightUnitCO, bp_.paperheight, defaultUnit);
2505
2506         // margins
2507         Ui::MarginsUi * m = marginsModule;
2508
2509         setMargins(!bp_.use_geometry);
2510
2511         lengthToWidgets(m->topLE, m->topUnit,
2512                 bp_.topmargin, defaultUnit);
2513
2514         lengthToWidgets(m->bottomLE, m->bottomUnit,
2515                 bp_.bottommargin, defaultUnit);
2516
2517         lengthToWidgets(m->innerLE, m->innerUnit,
2518                 bp_.leftmargin, defaultUnit);
2519
2520         lengthToWidgets(m->outerLE, m->outerUnit,
2521                 bp_.rightmargin, defaultUnit);
2522
2523         lengthToWidgets(m->headheightLE, m->headheightUnit,
2524                 bp_.headheight, defaultUnit);
2525
2526         lengthToWidgets(m->headsepLE, m->headsepUnit,
2527                 bp_.headsep, defaultUnit);
2528
2529         lengthToWidgets(m->footskipLE, m->footskipUnit,
2530                 bp_.footskip, defaultUnit);
2531
2532         lengthToWidgets(m->columnsepLE, m->columnsepUnit,
2533                 bp_.columnsep, defaultUnit);
2534
2535         // branches
2536         updateUnknownBranches();
2537         branchesModule->update(bp_);
2538
2539         // PDF support
2540         PDFOptions const & pdf = bp_.pdfoptions();
2541         pdfSupportModule->use_hyperrefGB->setChecked(pdf.use_hyperref);
2542         pdfSupportModule->titleLE->setText(toqstr(pdf.title));
2543         pdfSupportModule->authorLE->setText(toqstr(pdf.author));
2544         pdfSupportModule->subjectLE->setText(toqstr(pdf.subject));
2545         pdfSupportModule->keywordsLE->setText(toqstr(pdf.keywords));
2546
2547         pdfSupportModule->bookmarksGB->setChecked(pdf.bookmarks);
2548         pdfSupportModule->bookmarksnumberedCB->setChecked(pdf.bookmarksnumbered);
2549         pdfSupportModule->bookmarksopenGB->setChecked(pdf.bookmarksopen);
2550
2551         pdfSupportModule->bookmarksopenlevelSB->setValue(pdf.bookmarksopenlevel);
2552
2553         pdfSupportModule->breaklinksCB->setChecked(pdf.breaklinks);
2554         pdfSupportModule->pdfborderCB->setChecked(pdf.pdfborder);
2555         pdfSupportModule->pdfusetitleCB->setChecked(pdf.pdfusetitle);
2556         pdfSupportModule->colorlinksCB->setChecked(pdf.colorlinks);
2557
2558         nn = findToken(backref_opts, pdf.backref);
2559         if (nn >= 0)
2560                 pdfSupportModule->backrefCO->setCurrentIndex(nn);
2561
2562         pdfSupportModule->fullscreenCB->setChecked
2563                 (pdf.pagemode == pdf.pagemode_fullscreen);
2564
2565         pdfSupportModule->optionsLE->setText(
2566                 toqstr(pdf.quoted_options));
2567
2568         // Make sure that the bc is in the INITIAL state
2569         if (bc().policy().buttonStatus(ButtonPolicy::RESTORE))
2570                 bc().restore();
2571
2572         // clear changed branches cache
2573         changedBranches_.clear();
2574 }
2575
2576
2577 void GuiDocument::saveDocDefault()
2578 {
2579         // we have to apply the params first
2580         applyView();
2581         saveAsDefault();
2582 }
2583
2584
2585 void GuiDocument::updateAvailableModules() 
2586 {
2587         modules_av_model_.clear();
2588         list<modInfoStruct> const & modInfoList = getModuleInfo();
2589         list<modInfoStruct>::const_iterator mit = modInfoList.begin();
2590         list<modInfoStruct>::const_iterator men = modInfoList.end();
2591         for (int i = 0; mit != men; ++mit, ++i)
2592                 modules_av_model_.insertRow(i, mit->name, mit->id, 
2593                                 mit->description);
2594 }
2595
2596
2597 void GuiDocument::updateSelectedModules() 
2598 {
2599         modules_sel_model_.clear();
2600         list<modInfoStruct> const selModList = getSelectedModules();
2601         list<modInfoStruct>::const_iterator mit = selModList.begin();
2602         list<modInfoStruct>::const_iterator men = selModList.end();
2603         for (int i = 0; mit != men; ++mit, ++i)
2604                 modules_sel_model_.insertRow(i, mit->name, mit->id, 
2605                                 mit->description);
2606 }
2607
2608
2609 void GuiDocument::updateContents()
2610 {
2611         // Nothing to do here as the document settings is not cursor dependant.
2612         return;
2613 }
2614
2615
2616 void GuiDocument::useClassDefaults()
2617 {
2618         if (applyPB->isEnabled()) {
2619                 int const ret = Alert::prompt(_("Unapplied changes"),
2620                                 _("Some changes in the dialog were not yet applied.\n"
2621                                   "If you do not apply now, they will be lost after this action."),
2622                                 1, 1, _("&Apply"), _("&Dismiss"));
2623                 if (ret == 0)
2624                         applyView();
2625         }
2626
2627         int idx = latexModule->classCO->currentIndex();
2628         string const classname = classes_model_.getIDString(idx);
2629         if (!bp_.setBaseClass(classname)) {
2630                 Alert::error(_("Error"), _("Unable to set document class."));
2631                 return;
2632         }
2633         bp_.useClassDefaults();
2634         paramsToDialog();
2635 }
2636
2637
2638 void GuiDocument::setLayoutComboByIDString(string const & idString)
2639 {
2640         int idx = classes_model_.findIDString(idString);
2641         if (idx < 0)
2642                 Alert::warning(_("Can't set layout!"), 
2643                         bformat(_("Unable to set layout for ID: %1$s"), from_utf8(idString)));
2644         else 
2645                 latexModule->classCO->setCurrentIndex(idx);
2646 }
2647
2648
2649 bool GuiDocument::isValid()
2650 {
2651         return validateListingsParameters().isEmpty()
2652                 && (textLayoutModule->skipCO->currentIndex() != 3
2653                         || !textLayoutModule->skipLE->text().isEmpty()
2654                         || textLayoutModule->indentRB->isChecked())
2655                 && (textLayoutModule->indentCO->currentIndex() != 1
2656                         || !textLayoutModule->indentLE->text().isEmpty()
2657                         || textLayoutModule->skipRB->isChecked());
2658 }
2659
2660
2661 char const * const GuiDocument::fontfamilies[5] = {
2662         "default", "rmdefault", "sfdefault", "ttdefault", ""
2663 };
2664
2665
2666 char const * GuiDocument::fontfamilies_gui[5] = {
2667         N_("Default"), N_("Roman"), N_("Sans Serif"), N_("Typewriter"), ""
2668 };
2669
2670
2671 bool GuiDocument::initialiseParams(string const &)
2672 {
2673         BufferView const * view = bufferview();
2674         if (!view) {
2675                 bp_ = BufferParams();
2676                 paramsToDialog();
2677                 return true;
2678         }
2679         bp_ = view->buffer().params();
2680         loadModuleInfo();
2681         updateAvailableModules();
2682         //FIXME It'd be nice to make sure here that the selected
2683         //modules are consistent: That required modules are actually
2684         //selected, and that we don't have conflicts. If so, we could
2685         //at least pop up a warning.
2686         paramsToDialog();
2687         return true;
2688 }
2689
2690
2691 void GuiDocument::clearParams()
2692 {
2693         bp_ = BufferParams();
2694 }
2695
2696
2697 BufferId GuiDocument::id() const
2698 {
2699         BufferView const * const view = bufferview();
2700         return view? &view->buffer() : 0;
2701 }
2702
2703
2704 list<GuiDocument::modInfoStruct> const & GuiDocument::getModuleInfo()
2705 {
2706         return moduleNames_;
2707 }
2708
2709
2710 list<GuiDocument::modInfoStruct> const 
2711                 GuiDocument::makeModuleInfo(LayoutModuleList const & mods)
2712 {
2713         LayoutModuleList::const_iterator it =  mods.begin();
2714         LayoutModuleList::const_iterator end = mods.end();
2715         list<modInfoStruct> mInfo;
2716         for (; it != end; ++it) {
2717                 modInfoStruct m;
2718                 m.id = *it;
2719                 LyXModule const * const mod = theModuleList[*it];
2720                 if (mod)
2721                         // FIXME Unicode
2722                         m.name = toqstr(translateIfPossible(from_utf8(mod->getName())));
2723                 else 
2724                         m.name = toqstr(*it) + toqstr(" (") + qt_("Not Found") + toqstr(")");
2725                 mInfo.push_back(m);
2726         }
2727         return mInfo;
2728 }
2729
2730
2731 list<GuiDocument::modInfoStruct> const GuiDocument::getSelectedModules()
2732 {
2733         return makeModuleInfo(params().getModules());
2734 }
2735
2736
2737 list<GuiDocument::modInfoStruct> const GuiDocument::getProvidedModules()
2738 {
2739         return makeModuleInfo(params().baseClass()->providedModules());
2740 }
2741
2742
2743 DocumentClass const & GuiDocument::documentClass() const
2744 {
2745         return bp_.documentClass();
2746 }
2747
2748
2749 static void dispatch_bufferparams(Dialog const & dialog,
2750         BufferParams const & bp, FuncCode lfun)
2751 {
2752         ostringstream ss;
2753         ss << "\\begin_header\n";
2754         bp.writeFile(ss);
2755         ss << "\\end_header\n";
2756         dialog.dispatch(FuncRequest(lfun, ss.str()));
2757 }
2758
2759
2760 void GuiDocument::dispatchParams()
2761 {
2762         // This must come first so that a language change is correctly noticed
2763         setLanguage();
2764
2765         // Apply the BufferParams. Note that this will set the base class
2766         // and then update the buffer's layout.
2767         dispatch_bufferparams(*this, params(), LFUN_BUFFER_PARAMS_APPLY);
2768
2769         if (!params().master.empty()) {
2770                 FileName const master_file = support::makeAbsPath(params().master,
2771                            support::onlyPath(buffer().absFileName()));
2772                 if (isLyXFilename(master_file.absFilename())) {
2773                         Buffer * master = checkAndLoadLyXFile(master_file);
2774                         if (master) {
2775                                 if (master->isChild(const_cast<Buffer *>(&buffer())))
2776                                         const_cast<Buffer &>(buffer()).setParent(master);
2777                                 else
2778                                         Alert::warning(_("Assigned master does not include this file"), 
2779                                                 bformat(_("You must include this file in the document\n"
2780                                                           "'%1$s' in order to use the master document\n"
2781                                                           "feature."), from_utf8(params().master)));
2782                         } else
2783                                 Alert::warning(_("Could not load master"), 
2784                                                 bformat(_("The master document '%1$s'\n"
2785                                                            "could not be loaded."),
2786                                                            from_utf8(params().master)));
2787                 }
2788         }
2789
2790         // Generate the colours requested by each new branch.
2791         BranchList & branchlist = params().branchlist();
2792         if (!branchlist.empty()) {
2793                 BranchList::const_iterator it = branchlist.begin();
2794                 BranchList::const_iterator const end = branchlist.end();
2795                 for (; it != end; ++it) {
2796                         docstring const & current_branch = it->branch();
2797                         Branch const * branch = branchlist.find(current_branch);
2798                         string const x11hexname = X11hexname(branch->color());
2799                         // display the new color
2800                         docstring const str = current_branch + ' ' + from_ascii(x11hexname);
2801                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
2802                 }
2803
2804                 // Open insets of selected branches, close deselected ones
2805                 dispatch(FuncRequest(LFUN_ALL_INSETS_TOGGLE,
2806                         "assign branch"));
2807         }
2808         // rename branches in the document
2809         executeBranchRenaming();
2810         // and clear changed branches cache
2811         changedBranches_.clear();
2812         
2813         // Generate the colours requested by indices.
2814         IndicesList & indiceslist = params().indiceslist();
2815         if (!indiceslist.empty()) {
2816                 IndicesList::const_iterator it = indiceslist.begin();
2817                 IndicesList::const_iterator const end = indiceslist.end();
2818                 for (; it != end; ++it) {
2819                         docstring const & current_index = it->shortcut();
2820                         Index const * index = indiceslist.findShortcut(current_index);
2821                         string const x11hexname = X11hexname(index->color());
2822                         // display the new color
2823                         docstring const str = current_index + ' ' + from_ascii(x11hexname);
2824                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
2825                 }
2826         }
2827         // FIXME: If we used an LFUN, we would not need those two lines:
2828         BufferView * bv = const_cast<BufferView *>(bufferview());
2829         bv->processUpdateFlags(Update::Force | Update::FitCursor);
2830 }
2831
2832
2833 void GuiDocument::setLanguage() const
2834 {
2835         Language const * const newL = bp_.language;
2836         if (buffer().params().language == newL)
2837                 return;
2838
2839         string const & lang_name = newL->lang();
2840         dispatch(FuncRequest(LFUN_BUFFER_LANGUAGE, lang_name));
2841 }
2842
2843
2844 void GuiDocument::saveAsDefault() const
2845 {
2846         dispatch_bufferparams(*this, params(), LFUN_BUFFER_SAVE_AS_DEFAULT);
2847 }
2848
2849
2850 bool GuiDocument::isFontAvailable(string const & font) const
2851 {
2852         if (font == "default" || font == "cmr"
2853             || font == "cmss" || font == "cmtt")
2854                 // these are standard
2855                 return true;
2856         if (font == "lmodern" || font == "lmss" || font == "lmtt")
2857                 return LaTeXFeatures::isAvailable("lmodern");
2858         if (font == "times" || font == "palatino"
2859                  || font == "helvet" || font == "courier")
2860                 return LaTeXFeatures::isAvailable("psnfss");
2861         if (font == "cmbr" || font == "cmtl")
2862                 return LaTeXFeatures::isAvailable("cmbright");
2863         if (font == "utopia")
2864                 return LaTeXFeatures::isAvailable("utopia")
2865                         || LaTeXFeatures::isAvailable("fourier");
2866         if (font == "beraserif" || font == "berasans"
2867                 || font == "beramono")
2868                 return LaTeXFeatures::isAvailable("bera");
2869         return LaTeXFeatures::isAvailable(font);
2870 }
2871
2872
2873 bool GuiDocument::providesOSF(string const & font) const
2874 {
2875         if (outputModule->xetexCB->isChecked())
2876                 // FIXME: we should check if the fonts really
2877                 // have OSF support. But how?
2878                 return true;
2879         if (font == "cmr")
2880                 return isFontAvailable("eco");
2881         if (font == "palatino")
2882                 return isFontAvailable("mathpazo");
2883         return false;
2884 }
2885
2886
2887 bool GuiDocument::providesSC(string const & font) const
2888 {
2889         if (outputModule->xetexCB->isChecked())
2890                 return false;
2891         if (font == "palatino")
2892                 return isFontAvailable("mathpazo");
2893         if (font == "utopia")
2894                 return isFontAvailable("fourier");
2895         return false;
2896 }
2897
2898
2899 bool GuiDocument::providesScale(string const & font) const
2900 {
2901         if (outputModule->xetexCB->isChecked())
2902                 return true;
2903         return font == "helvet" || font == "luximono"
2904                 || font == "berasans"  || font == "beramono";
2905 }
2906
2907
2908 void GuiDocument::loadModuleInfo()
2909 {
2910         moduleNames_.clear();
2911         LyXModuleList::const_iterator it  = theModuleList.begin();
2912         LyXModuleList::const_iterator end = theModuleList.end();
2913         for (; it != end; ++it) {
2914                 modInfoStruct m;
2915                 m.id = it->getID();
2916                 // FIXME Unicode
2917                 m.name = toqstr(translateIfPossible(from_utf8(it->getName())));
2918                 // this is supposed to give us the first sentence of the description
2919                 // FIXME Unicode
2920                 QString desc =
2921                         toqstr(translateIfPossible(from_utf8(it->getDescription())));
2922                 int const pos = desc.indexOf(".");
2923                 if (pos > 0)
2924                         desc.truncate(pos + 1);
2925                 m.description = desc;
2926                 moduleNames_.push_back(m);
2927         }
2928 }
2929
2930
2931 void GuiDocument::updateUnknownBranches()
2932 {
2933         list<docstring> used_branches;
2934         buffer().getUsedBranches(used_branches);
2935         list<docstring>::const_iterator it = used_branches.begin();
2936         QStringList unknown_branches;
2937         for (; it != used_branches.end() ; ++it) {
2938                 if (!buffer().params().branchlist().find(*it))
2939                         unknown_branches.append(toqstr(*it));
2940         }
2941         branchesModule->setUnknownBranches(unknown_branches);
2942 }
2943
2944
2945 void GuiDocument::branchesRename(docstring const & oldname, docstring const & newname)
2946 {
2947         map<docstring, docstring>::iterator it = changedBranches_.begin();
2948         for (; it != changedBranches_.end() ; ++it) {
2949                 if (it->second == oldname) {
2950                         // branch has already been renamed
2951                         it->second = newname;
2952                         return;
2953                 }
2954         }
2955         // store new name
2956         changedBranches_[oldname] = newname;
2957 }
2958
2959
2960 void GuiDocument::executeBranchRenaming() const
2961 {
2962         map<docstring, docstring>::const_iterator it = changedBranches_.begin();
2963         for (; it != changedBranches_.end() ; ++it) {
2964                 docstring const arg = '"' + it->first + '"' + " " + '"' + it->second + '"';
2965                 dispatch(FuncRequest(LFUN_BRANCHES_RENAME, arg));
2966         }
2967 }
2968
2969
2970 Dialog * createGuiDocument(GuiView & lv) { return new GuiDocument(lv); }
2971
2972
2973 } // namespace frontend
2974 } // namespace lyx
2975
2976 #include "moc_GuiDocument.cpp"