]> git.lyx.org Git - features.git/blob - src/frontends/qt4/GuiDocument.cpp
GuiDocument: some polishing of the list of modules.
[features.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 "CategorizedCombo.h"
17 #include "GuiApplication.h"
18 #include "GuiBranches.h"
19 #include "GuiIndices.h"
20 #include "GuiSelectionManager.h"
21 #include "LaTeXHighlighter.h"
22 #include "LengthCombo.h"
23 #include "PanelStack.h"
24 #include "Validator.h"
25
26 #include "LayoutFile.h"
27 #include "BranchList.h"
28 #include "buffer_funcs.h"
29 #include "Buffer.h"
30 #include "BufferParams.h"
31 #include "BufferView.h"
32 #include "Color.h"
33 #include "ColorCache.h"
34 #include "Cursor.h"
35 #include "Encoding.h"
36 #include "FloatPlacement.h"
37 #include "Format.h"
38 #include "FuncRequest.h"
39 #include "HSpace.h"
40 #include "IndicesList.h"
41 #include "Language.h"
42 #include "LaTeXFeatures.h"
43 #include "LaTeXFonts.h"
44 #include "Layout.h"
45 #include "LayoutEnums.h"
46 #include "LayoutModuleList.h"
47 #include "LyXRC.h"
48 #include "ModuleList.h"
49 #include "OutputParams.h"
50 #include "PDFOptions.h"
51 #include "qt_helpers.h"
52 #include "Spacing.h"
53 #include "TextClass.h"
54 #include "Undo.h"
55 #include "VSpace.h"
56
57 #include "insets/InsetListingsParams.h"
58
59 #include "support/debug.h"
60 #include "support/FileName.h"
61 #include "support/filetools.h"
62 #include "support/gettext.h"
63 #include "support/lassert.h"
64 #include "support/lstrings.h"
65
66 #include "frontends/alert.h"
67
68 #include <QAbstractItemModel>
69 #include <QHeaderView>
70 #include <QColor>
71 #include <QColorDialog>
72 #include <QCloseEvent>
73 #include <QFontDatabase>
74 #include <QScrollBar>
75 #include <QTextBoundaryFinder>
76 #include <QTextCursor>
77
78 #include <sstream>
79 #include <vector>
80
81 #ifdef IN
82 #undef IN
83 #endif
84
85
86 // a style sheet for buttons
87 // this is for example used for the background color setting button
88 static inline QString colorButtonStyleSheet(QColor const & bgColor)
89 {
90         if (bgColor.isValid()) {
91                 QString rc = QLatin1String("background-color:");
92                 rc += bgColor.name();
93                 return rc;
94         }
95         return QString();
96 }
97
98
99 using namespace std;
100 using namespace lyx::support;
101
102
103 namespace {
104
105 char const * const tex_graphics[] =
106 {
107         "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
108         "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
109         "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
110         "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
111         "xetex", "none", ""
112 };
113
114
115 char const * const tex_graphics_gui[] =
116 {
117         N_("Default"), "dvialw", "DviLaser", "dvipdf", "DVIPDFM", "DVIPDFMx",
118         "Dvips", "DVIPSONE", "DVItoPS", "DVIWIN", "DVIWindo", "dvi2ps", "EmTeX",
119         "LN", "OzTeX", "pctexhp", "pctexps", "pctexwin", "PCTeX32", "pdfTeX",
120         "psprint", "pubps", "tcidvi", "Textures", "TrueTeX", "VTeX", "xdvi",
121         "XeTeX", N_("None"), ""
122 };
123
124
125 char const * backref_opts[] =
126 {
127         "false", "section", "slide", "page", ""
128 };
129
130
131 char const * backref_opts_gui[] =
132 {
133         N_("Off"), N_("Section"), N_("Slide"), N_("Page"), ""
134 };
135
136
137 vector<string> engine_types_;
138 vector<pair<string, QString> > pagestyles;
139
140 QMap<QString, QString> rmfonts_;
141 QMap<QString, QString> sffonts_;
142 QMap<QString, QString> ttfonts_;
143 QMap<QString, QString> mathfonts_;
144
145
146 } // anonymous namespace
147
148 namespace lyx {
149
150 RGBColor set_backgroundcolor;
151 bool is_backgroundcolor;
152 RGBColor set_fontcolor;
153 bool is_fontcolor;
154 RGBColor set_notefontcolor;
155 RGBColor set_boxbgcolor;
156 bool forced_fontspec_activation;
157
158 namespace {
159 // used when sorting the textclass list.
160 class less_textclass_avail_desc
161         : public binary_function<string, string, int>
162 {
163 public:
164         bool operator()(string const & lhs, string const & rhs) const
165         {
166                 // Ordering criteria:
167                 //   1. Availability of text class
168                 //   2. Description (lexicographic)
169                 LayoutFile const & tc1 = LayoutFileList::get()[lhs];
170                 LayoutFile const & tc2 = LayoutFileList::get()[rhs];
171                 int const order = compare_no_case(
172                         translateIfPossible(from_utf8(tc1.description())),
173                         translateIfPossible(from_utf8(tc2.description())));
174                 return (tc1.isTeXClassAvailable() && !tc2.isTeXClassAvailable()) ||
175                         (tc1.isTeXClassAvailable() == tc2.isTeXClassAvailable() && order < 0);
176         }
177 };
178
179 }
180
181 namespace frontend {
182 namespace {
183
184 vector<string> getRequiredList(string const & modName)
185 {
186         LyXModule const * const mod = theModuleList[modName];
187         if (!mod)
188                 return vector<string>(); //empty such thing
189         return mod->getRequiredModules();
190 }
191
192
193 vector<string> getExcludedList(string const & modName)
194 {
195         LyXModule const * const mod = theModuleList[modName];
196         if (!mod)
197                 return vector<string>(); //empty such thing
198         return mod->getExcludedModules();
199 }
200
201
202 docstring getModuleCategory(string const & modName)
203 {
204         LyXModule const * const mod = theModuleList[modName];
205         if (!mod)
206                 return docstring();
207         return from_utf8(mod->category());
208 }
209
210
211 docstring getModuleDescription(string const & modName)
212 {
213         LyXModule const * const mod = theModuleList[modName];
214         if (!mod)
215                 return _("Module not found!");
216         // FIXME Unicode
217         return translateIfPossible(from_utf8(mod->getDescription()));
218 }
219
220
221 vector<string> getPackageList(string const & modName)
222 {
223         LyXModule const * const mod = theModuleList[modName];
224         if (!mod)
225                 return vector<string>(); //empty such thing
226         return mod->getPackageList();
227 }
228
229
230 bool isModuleAvailable(string const & modName)
231 {
232         LyXModule const * const mod = theModuleList[modName];
233         if (!mod)
234                 return false;
235         return mod->isAvailable();
236 }
237
238 } // anonymous namespace
239
240
241 /////////////////////////////////////////////////////////////////////
242 //
243 // ModuleSelectionManager
244 //
245 /////////////////////////////////////////////////////////////////////
246
247 /// SelectionManager for use with modules
248 class ModuleSelectionManager : public GuiSelectionManager
249 {
250 public:
251         ///
252         ModuleSelectionManager(
253                 QTreeView * availableLV,
254                 QListView * selectedLV,
255                 QPushButton * addPB,
256                 QPushButton * delPB,
257                 QPushButton * upPB,
258                 QPushButton * downPB,
259                 GuiIdListModel * availableModel,
260                 GuiIdListModel * selectedModel,
261                 GuiDocument const * container)
262         : GuiSelectionManager(availableLV, selectedLV, addPB, delPB,
263                                 upPB, downPB, availableModel, selectedModel), container_(container)
264                 {}
265         ///
266         void updateProvidedModules(LayoutModuleList const & pm)
267                         { provided_modules_ = pm.list(); }
268         ///
269         void updateExcludedModules(LayoutModuleList const & em)
270                         { excluded_modules_ = em.list(); }
271 private:
272         ///
273         virtual void updateAddPB();
274         ///
275         virtual void updateUpPB();
276         ///
277         virtual void updateDownPB();
278         ///
279         virtual void updateDelPB();
280         /// returns availableModel as a GuiIdListModel
281         GuiIdListModel * getAvailableModel()
282         {
283                 return dynamic_cast<GuiIdListModel *>(availableModel);
284         }
285         /// returns selectedModel as a GuiIdListModel
286         GuiIdListModel * getSelectedModel()
287         {
288                 return dynamic_cast<GuiIdListModel *>(selectedModel);
289         }
290         /// keeps a list of the modules the text class provides
291         list<string> provided_modules_;
292         /// similarly...
293         list<string> excluded_modules_;
294         ///
295         GuiDocument const * container_;
296 };
297
298 void ModuleSelectionManager::updateAddPB()
299 {
300         int const arows = availableModel->rowCount();
301         QModelIndexList const avail_sels =
302                         availableLV->selectionModel()->selectedIndexes();
303
304         // disable if there aren't any modules (?), if none of them is chosen
305         // in the dialog, or if the chosen one is already selected for use.
306         if (arows == 0 || avail_sels.isEmpty() || isSelected(avail_sels.first())) {
307                 addPB->setEnabled(false);
308                 return;
309         }
310
311         QModelIndex const & idx = availableLV->selectionModel()->currentIndex();
312         string const modname = getAvailableModel()->getIDString(idx.row());
313
314         bool const enable =
315                 container_->params().layoutModuleCanBeAdded(modname);
316         addPB->setEnabled(enable);
317 }
318
319
320 void ModuleSelectionManager::updateDownPB()
321 {
322         int const srows = selectedModel->rowCount();
323         if (srows == 0) {
324                 downPB->setEnabled(false);
325                 return;
326         }
327         QModelIndex const & curidx = selectedLV->selectionModel()->currentIndex();
328         int const curRow = curidx.row();
329         if (curRow < 0 || curRow >= srows - 1) { // invalid or last item
330                 downPB->setEnabled(false);
331                 return;
332         }
333
334         // determine whether immediately succeding element requires this one
335         string const curmodname = getSelectedModel()->getIDString(curRow);
336         string const nextmodname = getSelectedModel()->getIDString(curRow + 1);
337
338         vector<string> reqs = getRequiredList(nextmodname);
339
340         // if it doesn't require anything....
341         if (reqs.empty()) {
342                 downPB->setEnabled(true);
343                 return;
344         }
345
346         // Enable it if this module isn't required.
347         // FIXME This should perhaps be more flexible and check whether, even
348         // if the next one is required, there is also an earlier one that will do.
349         downPB->setEnabled(
350                         find(reqs.begin(), reqs.end(), curmodname) == reqs.end());
351 }
352
353 void ModuleSelectionManager::updateUpPB()
354 {
355         int const srows = selectedModel->rowCount();
356         if (srows == 0) {
357                 upPB->setEnabled(false);
358                 return;
359         }
360
361         QModelIndex const & curIdx = selectedLV->selectionModel()->currentIndex();
362         int curRow = curIdx.row();
363         if (curRow <= 0 || curRow > srows - 1) { // first item or invalid
364                 upPB->setEnabled(false);
365                 return;
366         }
367         string const curmodname = getSelectedModel()->getIDString(curRow);
368
369         // determine whether immediately preceding element is required by this one
370         vector<string> reqs = getRequiredList(curmodname);
371
372         // if this one doesn't require anything....
373         if (reqs.empty()) {
374                 upPB->setEnabled(true);
375                 return;
376         }
377
378
379         // Enable it if the preceding module isn't required.
380         // NOTE This is less flexible than it might be. We could check whether, even
381         // if the previous one is required, there is an earlier one that would do.
382         string const premod = getSelectedModel()->getIDString(curRow - 1);
383         upPB->setEnabled(find(reqs.begin(), reqs.end(), premod) == reqs.end());
384 }
385
386 void ModuleSelectionManager::updateDelPB()
387 {
388         int const srows = selectedModel->rowCount();
389         if (srows == 0) {
390                 deletePB->setEnabled(false);
391                 return;
392         }
393
394         QModelIndex const & curidx =
395                 selectedLV->selectionModel()->currentIndex();
396         int const curRow = curidx.row();
397         if (curRow < 0 || curRow >= srows) { // invalid index?
398                 deletePB->setEnabled(false);
399                 return;
400         }
401
402         string const curmodname = getSelectedModel()->getIDString(curRow);
403
404         // We're looking here for a reason NOT to enable the button. If we
405         // find one, we disable it and return. If we don't, we'll end up at
406         // the end of the function, and then we enable it.
407         for (int i = curRow + 1; i < srows; ++i) {
408                 string const thisMod = getSelectedModel()->getIDString(i);
409                 vector<string> reqs = getRequiredList(thisMod);
410                 //does this one require us?
411                 if (find(reqs.begin(), reqs.end(), curmodname) == reqs.end())
412                         //no...
413                         continue;
414
415                 // OK, so this module requires us
416                 // is there an EARLIER module that also satisfies the require?
417                 // NOTE We demand that it be earlier to keep the list of modules
418                 // consistent with the rule that a module must be proceeded by a
419                 // required module. There would be more flexible ways to proceed,
420                 // but that would be a lot more complicated, and the logic here is
421                 // already complicated. (That's why I've left the debugging code.)
422                 // lyxerr << "Testing " << thisMod << endl;
423                 bool foundone = false;
424                 for (int j = 0; j < curRow; ++j) {
425                         string const mod = getSelectedModel()->getIDString(j);
426                         // lyxerr << "In loop: Testing " << mod << endl;
427                         // do we satisfy the require?
428                         if (find(reqs.begin(), reqs.end(), mod) != reqs.end()) {
429                                 // lyxerr << mod << " does the trick." << endl;
430                                 foundone = true;
431                                 break;
432                         }
433                 }
434                 // did we find a module to satisfy the require?
435                 if (!foundone) {
436                         // lyxerr << "No matching module found." << endl;
437                         deletePB->setEnabled(false);
438                         return;
439                 }
440         }
441         // lyxerr << "All's well that ends well." << endl;
442         deletePB->setEnabled(true);
443 }
444
445
446 /////////////////////////////////////////////////////////////////////
447 //
448 // PreambleModule
449 //
450 /////////////////////////////////////////////////////////////////////
451
452 PreambleModule::PreambleModule() : current_id_(0)
453 {
454         // This is not a memory leak. The object will be destroyed
455         // with this.
456         (void) new LaTeXHighlighter(preambleTE->document());
457         preambleTE->setFont(guiApp->typewriterSystemFont());
458         preambleTE->setWordWrapMode(QTextOption::NoWrap);
459         setFocusProxy(preambleTE);
460         connect(preambleTE, SIGNAL(textChanged()), this, SIGNAL(changed()));
461 }
462
463
464 void PreambleModule::update(BufferParams const & params, BufferId id)
465 {
466         QString preamble = toqstr(params.preamble);
467         // Nothing to do if the params and preamble are unchanged.
468         if (id == current_id_
469                 && preamble == preambleTE->document()->toPlainText())
470                 return;
471
472         QTextCursor cur = preambleTE->textCursor();
473         // Save the coords before switching to the new one.
474         preamble_coords_[current_id_] =
475                 make_pair(cur.position(), preambleTE->verticalScrollBar()->value());
476
477         // Save the params address for further use.
478         current_id_ = id;
479         preambleTE->document()->setPlainText(preamble);
480         Coords::const_iterator it = preamble_coords_.find(current_id_);
481         if (it == preamble_coords_.end())
482                 // First time we open this one.
483                 preamble_coords_[current_id_] = make_pair(0, 0);
484         else {
485                 // Restore saved coords.
486                 QTextCursor cur = preambleTE->textCursor();
487                 cur.setPosition(it->second.first);
488                 preambleTE->setTextCursor(cur);
489                 preambleTE->verticalScrollBar()->setValue(it->second.second);
490         }
491 }
492
493
494 void PreambleModule::apply(BufferParams & params)
495 {
496         params.preamble = fromqstr(preambleTE->document()->toPlainText());
497 }
498
499
500 void PreambleModule::closeEvent(QCloseEvent * e)
501 {
502         // Save the coords before closing.
503         QTextCursor cur = preambleTE->textCursor();
504         preamble_coords_[current_id_] =
505                 make_pair(cur.position(), preambleTE->verticalScrollBar()->value());
506         e->accept();
507 }
508
509
510 /////////////////////////////////////////////////////////////////////
511 //
512 // LocalLayout
513 //
514 /////////////////////////////////////////////////////////////////////
515
516
517 LocalLayout::LocalLayout() : current_id_(0), validated_(false)
518 {
519         connect(locallayoutTE, SIGNAL(textChanged()), this, SLOT(textChanged()));
520         connect(validatePB, SIGNAL(clicked()), this, SLOT(validatePressed()));
521         connect(convertPB, SIGNAL(clicked()), this, SLOT(convertPressed()));
522 }
523
524
525 void LocalLayout::update(BufferParams const & params, BufferId id)
526 {
527         QString layout = toqstr(params.getLocalLayout(false));
528         // Nothing to do if the params and preamble are unchanged.
529         if (id == current_id_
530                 && layout == locallayoutTE->document()->toPlainText())
531                 return;
532
533         // Save the params address for further use.
534         current_id_ = id;
535         locallayoutTE->document()->setPlainText(layout);
536         validate();
537 }
538
539
540 void LocalLayout::apply(BufferParams & params)
541 {
542         string const layout = fromqstr(locallayoutTE->document()->toPlainText());
543         params.setLocalLayout(layout, false);
544 }
545
546
547 void LocalLayout::textChanged()
548 {
549         static const QString message =
550                 qt_("Press button to check validity...");
551         string const layout =
552                 fromqstr(locallayoutTE->document()->toPlainText().trimmed());
553
554         if (layout.empty()) {
555                 validated_ = true;
556                 validatePB->setEnabled(false);
557                 validLB->setText("");
558                 convertPB->hide();
559                 convertLB->hide();
560                 changed();
561         } else if (!validatePB->isEnabled()) {
562                 // if that's already enabled, we shouldn't need to do anything.
563                 validated_ = false;
564                 validLB->setText(message);
565                 validatePB->setEnabled(true);
566                 convertPB->setEnabled(false);
567                 changed();
568         }
569 }
570
571
572 void LocalLayout::convert() {
573         string const layout =
574                 fromqstr(locallayoutTE->document()->toPlainText().trimmed());
575         string const newlayout = TextClass::convert(layout);
576         LYXERR0(newlayout);
577         if (newlayout.empty()) {
578                 Alert::error(_("Conversion Failed!"),
579                       _("Failed to convert local layout to current format."));
580         } else {
581                 locallayoutTE->setPlainText(toqstr(newlayout));
582         }
583         validate();
584 }
585
586
587 void LocalLayout::convertPressed() {
588         convert();
589         changed();
590 }
591
592
593 void LocalLayout::validate() {
594         static const QString valid = qt_("Layout is valid!");
595         static const QString vtext =
596                 toqstr("<p style=\"font-weight: bold; \">")
597                   + valid + toqstr("</p>");
598         static const QString invalid = qt_("Layout is invalid!");
599         static const QString ivtext =
600                 toqstr("<p style=\"color: #c00000; font-weight: bold; \">")
601                   + invalid + toqstr("</p>");
602
603         string const layout =
604                 fromqstr(locallayoutTE->document()->toPlainText().trimmed());
605         if (!layout.empty()) {
606                 TextClass::ReturnValues const ret = TextClass::validate(layout);
607                 validated_ = (ret == TextClass::OK) || (ret == TextClass::OK_OLDFORMAT);
608                 validatePB->setEnabled(false);
609                 validLB->setText(validated_ ? vtext : ivtext);
610                 if (ret == TextClass::OK_OLDFORMAT) {
611                         convertPB->show();
612                         convertPB->setEnabled(true);
613                         convertLB->setText(qt_("Convert to current format"));
614                         convertLB->show();
615                 } else {
616                         convertPB->hide();
617                         convertLB->hide();
618                 }
619         }
620 }
621
622
623 void LocalLayout::validatePressed() {
624         validate();
625         changed();
626 }
627
628
629 /////////////////////////////////////////////////////////////////////
630 //
631 // DocumentDialog
632 //
633 /////////////////////////////////////////////////////////////////////
634
635
636 GuiDocument::GuiDocument(GuiView & lv)
637         : GuiDialog(lv, "document", qt_("Document Settings")),
638           biblioChanged_(false), nonModuleChanged_(false)
639 {
640         setupUi(this);
641
642         connect(okPB, SIGNAL(clicked()), this, SLOT(slotOK()));
643         connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
644         connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
645         connect(restorePB, SIGNAL(clicked()), this, SLOT(slotRestore()));
646
647         connect(savePB, SIGNAL(clicked()), this, SLOT(saveDefaultClicked()));
648         connect(defaultPB, SIGNAL(clicked()), this, SLOT(useDefaultsClicked()));
649
650         // Manage the restore, ok, apply, restore and cancel/close buttons
651         bc().setPolicy(ButtonPolicy::NoRepeatedApplyReadOnlyPolicy);
652         bc().setOK(okPB);
653         bc().setApply(applyPB);
654         bc().setCancel(closePB);
655         bc().setRestore(restorePB);
656
657
658         // text layout
659         textLayoutModule = new UiWidget<Ui::TextLayoutUi>;
660         connect(textLayoutModule->lspacingCO, SIGNAL(activated(int)),
661                 this, SLOT(change_adaptor()));
662         connect(textLayoutModule->lspacingCO, SIGNAL(activated(int)),
663                 this, SLOT(setLSpacing(int)));
664         connect(textLayoutModule->lspacingLE, SIGNAL(textChanged(const QString &)),
665                 this, SLOT(change_adaptor()));
666
667         connect(textLayoutModule->indentRB, SIGNAL(clicked()),
668                 this, SLOT(change_adaptor()));
669         connect(textLayoutModule->indentRB, SIGNAL(toggled(bool)),
670                 textLayoutModule->indentCO, SLOT(setEnabled(bool)));
671         connect(textLayoutModule->indentCO, SIGNAL(activated(int)),
672                 this, SLOT(change_adaptor()));
673         connect(textLayoutModule->indentCO, SIGNAL(activated(int)),
674                 this, SLOT(setIndent(int)));
675         connect(textLayoutModule->indentLE, SIGNAL(textChanged(const QString &)),
676                 this, SLOT(change_adaptor()));
677         connect(textLayoutModule->indentLengthCO, SIGNAL(activated(int)),
678                 this, SLOT(change_adaptor()));
679
680         connect(textLayoutModule->skipRB, SIGNAL(clicked()),
681                 this, SLOT(change_adaptor()));
682         connect(textLayoutModule->skipRB, SIGNAL(toggled(bool)),
683                 textLayoutModule->skipCO, SLOT(setEnabled(bool)));
684         connect(textLayoutModule->skipCO, SIGNAL(activated(int)),
685                 this, SLOT(change_adaptor()));
686         connect(textLayoutModule->skipCO, SIGNAL(activated(int)),
687                 this, SLOT(setSkip(int)));
688         connect(textLayoutModule->skipLE, SIGNAL(textChanged(const QString &)),
689                 this, SLOT(change_adaptor()));
690         connect(textLayoutModule->skipLengthCO, SIGNAL(activated(int)),
691                 this, SLOT(change_adaptor()));
692
693         connect(textLayoutModule->indentRB, SIGNAL(toggled(bool)),
694                 this, SLOT(enableIndent(bool)));
695         connect(textLayoutModule->skipRB, SIGNAL(toggled(bool)),
696                 this, SLOT(enableSkip(bool)));
697
698         connect(textLayoutModule->twoColumnCB, SIGNAL(clicked()),
699                 this, SLOT(change_adaptor()));
700         connect(textLayoutModule->twoColumnCB, SIGNAL(clicked()),
701                 this, SLOT(setColSep()));
702         connect(textLayoutModule->justCB, SIGNAL(clicked()),
703                 this, SLOT(change_adaptor()));
704
705         textLayoutModule->lspacingLE->setValidator(new QDoubleValidator(
706                 textLayoutModule->lspacingLE));
707         textLayoutModule->indentLE->setValidator(new LengthValidator(
708                 textLayoutModule->indentLE));
709         textLayoutModule->skipLE->setValidator(new LengthValidator(
710                 textLayoutModule->skipLE));
711
712         textLayoutModule->indentCO->addItem(qt_("Default"));
713         textLayoutModule->indentCO->addItem(qt_("Custom"));
714         textLayoutModule->skipCO->addItem(qt_("SmallSkip"));
715         textLayoutModule->skipCO->addItem(qt_("MedSkip"));
716         textLayoutModule->skipCO->addItem(qt_("BigSkip"));
717         textLayoutModule->skipCO->addItem(qt_("Custom"));
718         textLayoutModule->lspacingCO->insertItem(
719                 Spacing::Single, qt_("Single"));
720         textLayoutModule->lspacingCO->insertItem(
721                 Spacing::Onehalf, qt_("OneHalf"));
722         textLayoutModule->lspacingCO->insertItem(
723                 Spacing::Double, qt_("Double"));
724         textLayoutModule->lspacingCO->insertItem(
725                 Spacing::Other, qt_("Custom"));
726         // initialize the length validator
727         bc().addCheckedLineEdit(textLayoutModule->indentLE);
728         bc().addCheckedLineEdit(textLayoutModule->skipLE);
729
730
731         // master/child handling
732         masterChildModule = new UiWidget<Ui::MasterChildUi>;
733
734         connect(masterChildModule->childrenTW, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)),
735                 this, SLOT(includeonlyClicked(QTreeWidgetItem *, int)));
736         connect(masterChildModule->includeonlyRB, SIGNAL(toggled(bool)),
737                 masterChildModule->childrenTW, SLOT(setEnabled(bool)));
738         connect(masterChildModule->includeonlyRB, SIGNAL(toggled(bool)),
739                 masterChildModule->maintainAuxCB, SLOT(setEnabled(bool)));
740         connect(masterChildModule->includeallRB, SIGNAL(clicked()),
741                 this, SLOT(change_adaptor()));
742         connect(masterChildModule->includeonlyRB, SIGNAL(clicked()),
743                 this, SLOT(change_adaptor()));
744         connect(masterChildModule->maintainAuxCB, SIGNAL(clicked()),
745                 this, SLOT(change_adaptor()));
746         masterChildModule->childrenTW->setColumnCount(2);
747         masterChildModule->childrenTW->headerItem()->setText(0, qt_("Child Document"));
748         masterChildModule->childrenTW->headerItem()->setText(1, qt_("Include to Output"));
749         masterChildModule->childrenTW->resizeColumnToContents(1);
750         masterChildModule->childrenTW->resizeColumnToContents(2);
751
752
753         // output
754         outputModule = new UiWidget<Ui::OutputUi>;
755
756         connect(outputModule->defaultFormatCO, SIGNAL(activated(int)),
757                 this, SLOT(change_adaptor()));
758         connect(outputModule->mathimgSB, SIGNAL(valueChanged(double)),
759                 this, SLOT(change_adaptor()));
760         connect(outputModule->strictCB, SIGNAL(stateChanged(int)),
761                 this, SLOT(change_adaptor()));
762         connect(outputModule->cssCB, SIGNAL(stateChanged(int)),
763                 this, SLOT(change_adaptor()));
764         connect(outputModule->mathoutCB, SIGNAL(currentIndexChanged(int)),
765                 this, SLOT(change_adaptor()));
766
767         connect(outputModule->outputsyncCB, SIGNAL(clicked()),
768                 this, SLOT(change_adaptor()));
769         connect(outputModule->synccustomCB, SIGNAL(editTextChanged(QString)),
770                 this, SLOT(change_adaptor()));
771         outputModule->synccustomCB->addItem("");
772         outputModule->synccustomCB->addItem("\\synctex=1");
773         outputModule->synccustomCB->addItem("\\synctex=-1");
774         outputModule->synccustomCB->addItem("\\usepackage[active]{srcltx}");
775
776         outputModule->synccustomCB->setValidator(new NoNewLineValidator(
777                 outputModule->synccustomCB));
778
779         // fonts
780         fontModule = new FontModule;
781         connect(fontModule->osFontsCB, SIGNAL(clicked()),
782                 this, SLOT(change_adaptor()));
783         connect(fontModule->osFontsCB, SIGNAL(toggled(bool)),
784                 this, SLOT(osFontsChanged(bool)));
785         connect(fontModule->fontsRomanCO, SIGNAL(activated(int)),
786                 this, SLOT(change_adaptor()));
787         connect(fontModule->fontsRomanCO, SIGNAL(activated(int)),
788                 this, SLOT(romanChanged(int)));
789         connect(fontModule->fontsSansCO, SIGNAL(activated(int)),
790                 this, SLOT(change_adaptor()));
791         connect(fontModule->fontsSansCO, SIGNAL(activated(int)),
792                 this, SLOT(sansChanged(int)));
793         connect(fontModule->fontsTypewriterCO, SIGNAL(activated(int)),
794                 this, SLOT(change_adaptor()));
795         connect(fontModule->fontsTypewriterCO, SIGNAL(activated(int)),
796                 this, SLOT(ttChanged(int)));
797         connect(fontModule->fontsMathCO, SIGNAL(activated(int)),
798                 this, SLOT(change_adaptor()));
799         connect(fontModule->fontsMathCO, SIGNAL(activated(int)),
800                 this, SLOT(mathFontChanged(int)));
801         connect(fontModule->fontsDefaultCO, SIGNAL(activated(int)),
802                 this, SLOT(change_adaptor()));
803         connect(fontModule->fontencCO, SIGNAL(activated(int)),
804                 this, SLOT(change_adaptor()));
805         connect(fontModule->fontencCO, SIGNAL(activated(int)),
806                 this, SLOT(fontencChanged(int)));
807         connect(fontModule->fontencLE, SIGNAL(textChanged(const QString &)),
808                 this, SLOT(change_adaptor()));
809         connect(fontModule->fontsizeCO, SIGNAL(activated(int)),
810                 this, SLOT(change_adaptor()));
811         connect(fontModule->cjkFontLE, SIGNAL(textChanged(const QString &)),
812                 this, SLOT(change_adaptor()));
813         connect(fontModule->microtypeCB, SIGNAL(clicked()),
814                 this, SLOT(change_adaptor()));
815         connect(fontModule->scaleSansSB, SIGNAL(valueChanged(int)),
816                 this, SLOT(change_adaptor()));
817         connect(fontModule->scaleTypewriterSB, SIGNAL(valueChanged(int)),
818                 this, SLOT(change_adaptor()));
819         connect(fontModule->fontScCB, SIGNAL(clicked()),
820                 this, SLOT(change_adaptor()));
821         connect(fontModule->fontScCB, SIGNAL(toggled(bool)),
822                 this, SLOT(fontScToggled(bool)));
823         connect(fontModule->fontOsfCB, SIGNAL(clicked()),
824                 this, SLOT(change_adaptor()));
825         connect(fontModule->fontOsfCB, SIGNAL(toggled(bool)),
826                 this, SLOT(fontOsfToggled(bool)));
827
828         fontModule->fontencLE->setValidator(new NoNewLineValidator(
829                 fontModule->fontencLE));
830         fontModule->cjkFontLE->setValidator(new NoNewLineValidator(
831                 fontModule->cjkFontLE));
832
833         updateFontlist();
834
835         fontModule->fontsizeCO->addItem(qt_("Default"));
836         fontModule->fontsizeCO->addItem(qt_("10"));
837         fontModule->fontsizeCO->addItem(qt_("11"));
838         fontModule->fontsizeCO->addItem(qt_("12"));
839
840         fontModule->fontencCO->addItem(qt_("Default"), QString("global"));
841         fontModule->fontencCO->addItem(qt_("Custom"), QString("custom"));
842         fontModule->fontencCO->addItem(qt_("None (no fontenc)"), QString("default"));
843
844         for (int n = 0; GuiDocument::fontfamilies_gui[n][0]; ++n)
845                 fontModule->fontsDefaultCO->addItem(
846                         qt_(GuiDocument::fontfamilies_gui[n]));
847
848         if (!LaTeXFeatures::isAvailable("fontspec"))
849                 fontModule->osFontsCB->setToolTip(
850                         qt_("Use OpenType and TrueType fonts directly (requires XeTeX or LuaTeX)\n"
851                             "You need to install the package \"fontspec\" to use this feature"));
852
853
854         // page layout
855         pageLayoutModule = new UiWidget<Ui::PageLayoutUi>;
856         connect(pageLayoutModule->papersizeCO, SIGNAL(activated(int)),
857                 this, SLOT(papersizeChanged(int)));
858         connect(pageLayoutModule->papersizeCO, SIGNAL(activated(int)),
859                 this, SLOT(papersizeChanged(int)));
860         connect(pageLayoutModule->portraitRB, SIGNAL(clicked()),
861                 this, SLOT(change_adaptor()));
862         connect(pageLayoutModule->papersizeCO, SIGNAL(activated(int)),
863                 this, SLOT(change_adaptor()));
864         connect(pageLayoutModule->paperheightLE, SIGNAL(textChanged(const QString &)),
865                 this, SLOT(change_adaptor()));
866         connect(pageLayoutModule->paperwidthLE, SIGNAL(textChanged(const QString &)),
867                 this, SLOT(change_adaptor()));
868         connect(pageLayoutModule->paperwidthUnitCO, SIGNAL(activated(int)),
869                 this, SLOT(change_adaptor()));
870         connect(pageLayoutModule->paperheightUnitCO, SIGNAL(activated(int)),
871                 this, SLOT(change_adaptor()));
872         connect(pageLayoutModule->portraitRB, SIGNAL(clicked()),
873                 this, SLOT(change_adaptor()));
874         connect(pageLayoutModule->landscapeRB, SIGNAL(clicked()),
875                 this, SLOT(change_adaptor()));
876         connect(pageLayoutModule->facingPagesCB, SIGNAL(clicked()),
877                 this, SLOT(change_adaptor()));
878         connect(pageLayoutModule->pagestyleCO, SIGNAL(activated(int)),
879                 this, SLOT(change_adaptor()));
880
881         pageLayoutModule->pagestyleCO->addItem(qt_("Default"));
882         pageLayoutModule->pagestyleCO->addItem(qt_("empty"));
883         pageLayoutModule->pagestyleCO->addItem(qt_("plain"));
884         pageLayoutModule->pagestyleCO->addItem(qt_("headings"));
885         pageLayoutModule->pagestyleCO->addItem(qt_("fancy"));
886         bc().addCheckedLineEdit(pageLayoutModule->paperheightLE,
887                 pageLayoutModule->paperheightL);
888         bc().addCheckedLineEdit(pageLayoutModule->paperwidthLE,
889                 pageLayoutModule->paperwidthL);
890
891         QComboBox * cb = pageLayoutModule->papersizeCO;
892         cb->addItem(qt_("Default"));
893         cb->addItem(qt_("Custom"));
894         cb->addItem(qt_("US letter"));
895         cb->addItem(qt_("US legal"));
896         cb->addItem(qt_("US executive"));
897         cb->addItem(qt_("A0"));
898         cb->addItem(qt_("A1"));
899         cb->addItem(qt_("A2"));
900         cb->addItem(qt_("A3"));
901         cb->addItem(qt_("A4"));
902         cb->addItem(qt_("A5"));
903         cb->addItem(qt_("A6"));
904         cb->addItem(qt_("B0"));
905         cb->addItem(qt_("B1"));
906         cb->addItem(qt_("B2"));
907         cb->addItem(qt_("B3"));
908         cb->addItem(qt_("B4"));
909         cb->addItem(qt_("B5"));
910         cb->addItem(qt_("B6"));
911         cb->addItem(qt_("C0"));
912         cb->addItem(qt_("C1"));
913         cb->addItem(qt_("C2"));
914         cb->addItem(qt_("C3"));
915         cb->addItem(qt_("C4"));
916         cb->addItem(qt_("C5"));
917         cb->addItem(qt_("C6"));
918         cb->addItem(qt_("JIS B0"));
919         cb->addItem(qt_("JIS B1"));
920         cb->addItem(qt_("JIS B2"));
921         cb->addItem(qt_("JIS B3"));
922         cb->addItem(qt_("JIS B4"));
923         cb->addItem(qt_("JIS B5"));
924         cb->addItem(qt_("JIS B6"));
925         // remove the %-items from the unit choice
926         pageLayoutModule->paperwidthUnitCO->noPercents();
927         pageLayoutModule->paperheightUnitCO->noPercents();
928         pageLayoutModule->paperheightLE->setValidator(unsignedLengthValidator(
929                 pageLayoutModule->paperheightLE));
930         pageLayoutModule->paperwidthLE->setValidator(unsignedLengthValidator(
931                 pageLayoutModule->paperwidthLE));
932
933
934         // margins
935         marginsModule = new UiWidget<Ui::MarginsUi>;
936         connect(marginsModule->marginCB, SIGNAL(toggled(bool)),
937                 this, SLOT(setCustomMargins(bool)));
938         connect(marginsModule->marginCB, SIGNAL(clicked()),
939                 this, SLOT(change_adaptor()));
940         connect(marginsModule->topLE, SIGNAL(textChanged(QString)),
941                 this, SLOT(change_adaptor()));
942         connect(marginsModule->topUnit, SIGNAL(activated(int)),
943                 this, SLOT(change_adaptor()));
944         connect(marginsModule->bottomLE, SIGNAL(textChanged(QString)),
945                 this, SLOT(change_adaptor()));
946         connect(marginsModule->bottomUnit, SIGNAL(activated(int)),
947                 this, SLOT(change_adaptor()));
948         connect(marginsModule->innerLE, SIGNAL(textChanged(QString)),
949                 this, SLOT(change_adaptor()));
950         connect(marginsModule->innerUnit, SIGNAL(activated(int)),
951                 this, SLOT(change_adaptor()));
952         connect(marginsModule->outerLE, SIGNAL(textChanged(QString)),
953                 this, SLOT(change_adaptor()));
954         connect(marginsModule->outerUnit, SIGNAL(activated(int)),
955                 this, SLOT(change_adaptor()));
956         connect(marginsModule->headheightLE, SIGNAL(textChanged(QString)),
957                 this, SLOT(change_adaptor()));
958         connect(marginsModule->headheightUnit, SIGNAL(activated(int)),
959                 this, SLOT(change_adaptor()));
960         connect(marginsModule->headsepLE, SIGNAL(textChanged(QString)),
961                 this, SLOT(change_adaptor()));
962         connect(marginsModule->headsepUnit, SIGNAL(activated(int)),
963                 this, SLOT(change_adaptor()));
964         connect(marginsModule->footskipLE, SIGNAL(textChanged(QString)),
965                 this, SLOT(change_adaptor()));
966         connect(marginsModule->footskipUnit, SIGNAL(activated(int)),
967                 this, SLOT(change_adaptor()));
968         connect(marginsModule->columnsepLE, SIGNAL(textChanged(QString)),
969                 this, SLOT(change_adaptor()));
970         connect(marginsModule->columnsepUnit, SIGNAL(activated(int)),
971                 this, SLOT(change_adaptor()));
972         marginsModule->topLE->setValidator(new LengthValidator(
973                 marginsModule->topLE));
974         marginsModule->bottomLE->setValidator(new LengthValidator(
975                 marginsModule->bottomLE));
976         marginsModule->innerLE->setValidator(new LengthValidator(
977                 marginsModule->innerLE));
978         marginsModule->outerLE->setValidator(new LengthValidator(
979                 marginsModule->outerLE));
980         marginsModule->headsepLE->setValidator(new LengthValidator(
981                 marginsModule->headsepLE));
982         marginsModule->headheightLE->setValidator(new LengthValidator(
983                 marginsModule->headheightLE));
984         marginsModule->footskipLE->setValidator(new LengthValidator(
985                 marginsModule->footskipLE));
986         marginsModule->columnsepLE->setValidator(new LengthValidator(
987                 marginsModule->columnsepLE));
988
989         bc().addCheckedLineEdit(marginsModule->topLE,
990                 marginsModule->topL);
991         bc().addCheckedLineEdit(marginsModule->bottomLE,
992                 marginsModule->bottomL);
993         bc().addCheckedLineEdit(marginsModule->innerLE,
994                 marginsModule->innerL);
995         bc().addCheckedLineEdit(marginsModule->outerLE,
996                 marginsModule->outerL);
997         bc().addCheckedLineEdit(marginsModule->headsepLE,
998                 marginsModule->headsepL);
999         bc().addCheckedLineEdit(marginsModule->headheightLE,
1000                 marginsModule->headheightL);
1001         bc().addCheckedLineEdit(marginsModule->footskipLE,
1002                 marginsModule->footskipL);
1003         bc().addCheckedLineEdit(marginsModule->columnsepLE,
1004                 marginsModule->columnsepL);
1005
1006
1007         // language & quote
1008         langModule = new UiWidget<Ui::LanguageUi>;
1009         connect(langModule->languageCO, SIGNAL(activated(int)),
1010                 this, SLOT(change_adaptor()));
1011         connect(langModule->languageCO, SIGNAL(activated(int)),
1012                 this, SLOT(languageChanged(int)));
1013         connect(langModule->defaultencodingRB, SIGNAL(clicked()),
1014                 this, SLOT(change_adaptor()));
1015         connect(langModule->otherencodingRB, SIGNAL(clicked()),
1016                 this, SLOT(change_adaptor()));
1017         connect(langModule->encodingCO, SIGNAL(activated(int)),
1018                 this, SLOT(change_adaptor()));
1019         connect(langModule->quoteStyleCO, SIGNAL(activated(int)),
1020                 this, SLOT(change_adaptor()));
1021         connect(langModule->languagePackageCO, SIGNAL(activated(int)),
1022                 this, SLOT(change_adaptor()));
1023         connect(langModule->languagePackageLE, SIGNAL(textChanged(QString)),
1024                 this, SLOT(change_adaptor()));
1025         connect(langModule->languagePackageCO, SIGNAL(currentIndexChanged(int)),
1026                 this, SLOT(languagePackageChanged(int)));
1027
1028         langModule->languagePackageLE->setValidator(new NoNewLineValidator(
1029                 langModule->languagePackageLE));
1030
1031         QAbstractItemModel * language_model = guiApp->languageModel();
1032         // FIXME: it would be nice if sorting was enabled/disabled via a checkbox.
1033         language_model->sort(0);
1034         langModule->languageCO->setModel(language_model);
1035         langModule->languageCO->setModelColumn(0);
1036
1037         // Always put the default encoding in the first position.
1038         langModule->encodingCO->addItem(qt_("Language Default (no inputenc)"));
1039         QStringList encodinglist;
1040         Encodings::const_iterator it = encodings.begin();
1041         Encodings::const_iterator const end = encodings.end();
1042         for (; it != end; ++it)
1043                 if (!it->unsafe())
1044                         encodinglist.append(qt_(it->guiName()));
1045         encodinglist.sort();
1046         langModule->encodingCO->addItems(encodinglist);
1047
1048         langModule->quoteStyleCO->addItem(
1049                 qt_("``text''"),InsetQuotes::EnglishQuotes);
1050         langModule->quoteStyleCO->addItem(
1051                 qt_("''text''"), InsetQuotes::SwedishQuotes);
1052         langModule->quoteStyleCO->addItem
1053                 (qt_(",,text``"), InsetQuotes::GermanQuotes);
1054         langModule->quoteStyleCO->addItem(
1055                 qt_(",,text''"), InsetQuotes::PolishQuotes);
1056         langModule->quoteStyleCO->addItem(
1057                 qt_("<<text>>"), InsetQuotes::FrenchQuotes);
1058         langModule->quoteStyleCO->addItem(
1059                 qt_(">>text<<"), InsetQuotes::DanishQuotes);
1060
1061         langModule->languagePackageCO->addItem(
1062                 qt_("Default"), toqstr("default"));
1063         langModule->languagePackageCO->addItem(
1064                 qt_("Automatic"), toqstr("auto"));
1065         langModule->languagePackageCO->addItem(
1066                 qt_("Always Babel"), toqstr("babel"));
1067         langModule->languagePackageCO->addItem(
1068                 qt_("Custom"), toqstr("custom"));
1069         langModule->languagePackageCO->addItem(
1070                 qt_("None[[language package]]"), toqstr("none"));
1071
1072
1073         // color
1074         colorModule = new UiWidget<Ui::ColorUi>;
1075         connect(colorModule->fontColorPB, SIGNAL(clicked()),
1076                 this, SLOT(changeFontColor()));
1077         connect(colorModule->delFontColorTB, SIGNAL(clicked()),
1078                 this, SLOT(deleteFontColor()));
1079         connect(colorModule->noteFontColorPB, SIGNAL(clicked()),
1080                 this, SLOT(changeNoteFontColor()));
1081         connect(colorModule->delNoteFontColorTB, SIGNAL(clicked()),
1082                 this, SLOT(deleteNoteFontColor()));
1083         connect(colorModule->backgroundPB, SIGNAL(clicked()),
1084                 this, SLOT(changeBackgroundColor()));
1085         connect(colorModule->delBackgroundTB, SIGNAL(clicked()),
1086                 this, SLOT(deleteBackgroundColor()));
1087         connect(colorModule->boxBackgroundPB, SIGNAL(clicked()),
1088                 this, SLOT(changeBoxBackgroundColor()));
1089         connect(colorModule->delBoxBackgroundTB, SIGNAL(clicked()),
1090                 this, SLOT(deleteBoxBackgroundColor()));
1091
1092
1093         // numbering
1094         numberingModule = new UiWidget<Ui::NumberingUi>;
1095         connect(numberingModule->depthSL, SIGNAL(valueChanged(int)),
1096                 this, SLOT(change_adaptor()));
1097         connect(numberingModule->tocSL, SIGNAL(valueChanged(int)),
1098                 this, SLOT(change_adaptor()));
1099         connect(numberingModule->depthSL, SIGNAL(valueChanged(int)),
1100                 this, SLOT(updateNumbering()));
1101         connect(numberingModule->tocSL, SIGNAL(valueChanged(int)),
1102                 this, SLOT(updateNumbering()));
1103         numberingModule->tocTW->setColumnCount(3);
1104         numberingModule->tocTW->headerItem()->setText(0, qt_("Example"));
1105         numberingModule->tocTW->headerItem()->setText(1, qt_("Numbered"));
1106         numberingModule->tocTW->headerItem()->setText(2, qt_("Appears in TOC"));
1107         setSectionResizeMode(numberingModule->tocTW->header(), QHeaderView::ResizeToContents);
1108
1109         // biblio
1110         biblioModule = new UiWidget<Ui::BiblioUi>;
1111         connect(biblioModule->citeDefaultRB, SIGNAL(toggled(bool)),
1112                 this, SLOT(setNumerical(bool)));
1113         connect(biblioModule->citeJurabibRB, SIGNAL(toggled(bool)),
1114                 this, SLOT(setAuthorYear(bool)));
1115         connect(biblioModule->citeNatbibRB, SIGNAL(toggled(bool)),
1116                 biblioModule->citationStyleL, SLOT(setEnabled(bool)));
1117         connect(biblioModule->citeNatbibRB, SIGNAL(toggled(bool)),
1118                 biblioModule->citeStyleCO, SLOT(setEnabled(bool)));
1119         connect(biblioModule->citeDefaultRB, SIGNAL(clicked()),
1120                 this, SLOT(biblioChanged()));
1121         connect(biblioModule->citeNatbibRB, SIGNAL(clicked()),
1122                 this, SLOT(biblioChanged()));
1123         connect(biblioModule->citeStyleCO, SIGNAL(activated(int)),
1124                 this, SLOT(biblioChanged()));
1125         connect(biblioModule->citeJurabibRB, SIGNAL(clicked()),
1126                 this, SLOT(biblioChanged()));
1127         connect(biblioModule->bibtopicCB, SIGNAL(clicked()),
1128                 this, SLOT(biblioChanged()));
1129         connect(biblioModule->bibtexCO, SIGNAL(activated(int)),
1130                 this, SLOT(bibtexChanged(int)));
1131         connect(biblioModule->bibtexOptionsLE, SIGNAL(textChanged(QString)),
1132                 this, SLOT(biblioChanged()));
1133         connect(biblioModule->bibtexStyleLE, SIGNAL(textChanged(QString)),
1134                 this, SLOT(biblioChanged()));
1135
1136         biblioModule->bibtexOptionsLE->setValidator(new NoNewLineValidator(
1137                 biblioModule->bibtexOptionsLE));
1138         biblioModule->bibtexStyleLE->setValidator(new NoNewLineValidator(
1139                 biblioModule->bibtexStyleLE));
1140
1141         biblioModule->citeStyleCO->addItem(qt_("Author-year"));
1142         biblioModule->citeStyleCO->addItem(qt_("Numerical"));
1143         biblioModule->citeStyleCO->setCurrentIndex(0);
1144
1145         // NOTE: we do not provide "custom" here for security reasons!
1146         biblioModule->bibtexCO->clear();
1147         biblioModule->bibtexCO->addItem(qt_("Default"), QString("default"));
1148         for (set<string>::const_iterator it = lyxrc.bibtex_alternatives.begin();
1149                              it != lyxrc.bibtex_alternatives.end(); ++it) {
1150                 QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
1151                 biblioModule->bibtexCO->addItem(command, command);
1152         }
1153
1154
1155         // indices
1156         indicesModule = new GuiIndices;
1157         connect(indicesModule, SIGNAL(changed()),
1158                 this, SLOT(change_adaptor()));
1159
1160
1161         // maths
1162         mathsModule = new UiWidget<Ui::MathsUi>;
1163         QStringList headers;
1164         headers << qt_("Package") << qt_("Load automatically")
1165                 << qt_("Load always") << qt_("Do not load");
1166         mathsModule->packagesTW->setHorizontalHeaderLabels(headers);
1167         setSectionResizeMode(mathsModule->packagesTW->horizontalHeader(), QHeaderView::Stretch);
1168         map<string, string> const & packages = BufferParams::auto_packages();
1169         mathsModule->packagesTW->setRowCount(packages.size());
1170         int i = 0;
1171         for (map<string, string>::const_iterator it = packages.begin();
1172              it != packages.end(); ++it) {
1173                 docstring const package = from_ascii(it->first);
1174                 QString autoTooltip = qt_(it->second);
1175                 QString alwaysTooltip;
1176                 if (package == "amsmath")
1177                         alwaysTooltip =
1178                                 qt_("The AMS LaTeX packages are always used");
1179                 else
1180                         alwaysTooltip = toqstr(bformat(
1181                                 _("The LaTeX package %1$s is always used"),
1182                                 package));
1183                 QString neverTooltip;
1184                 if (package == "amsmath")
1185                         neverTooltip =
1186                                 qt_("The AMS LaTeX packages are never used");
1187                 else
1188                         neverTooltip = toqstr(bformat(
1189                                 _("The LaTeX package %1$s is never used"),
1190                                 package));
1191                 QRadioButton * autoRB = new QRadioButton(mathsModule);
1192                 QRadioButton * alwaysRB = new QRadioButton(mathsModule);
1193                 QRadioButton * neverRB = new QRadioButton(mathsModule);
1194                 QButtonGroup * packageGroup = new QButtonGroup(mathsModule);
1195                 packageGroup->addButton(autoRB);
1196                 packageGroup->addButton(alwaysRB);
1197                 packageGroup->addButton(neverRB);
1198                 autoRB->setToolTip(autoTooltip);
1199                 alwaysRB->setToolTip(alwaysTooltip);
1200                 neverRB->setToolTip(neverTooltip);
1201                 QTableWidgetItem * pack = new QTableWidgetItem(toqstr(package));
1202                 mathsModule->packagesTW->setItem(i, 0, pack);
1203                 mathsModule->packagesTW->setCellWidget(i, 1, autoRB);
1204                 mathsModule->packagesTW->setCellWidget(i, 2, alwaysRB);
1205                 mathsModule->packagesTW->setCellWidget(i, 3, neverRB);
1206
1207                 connect(autoRB, SIGNAL(clicked()),
1208                         this, SLOT(change_adaptor()));
1209                 connect(alwaysRB, SIGNAL(clicked()),
1210                         this, SLOT(change_adaptor()));
1211                 connect(neverRB, SIGNAL(clicked()),
1212                         this, SLOT(change_adaptor()));
1213                 ++i;
1214         }
1215         connect(mathsModule->allPackagesAutoPB, SIGNAL(clicked()),
1216                 this, SLOT(allPackagesAuto()));
1217         connect(mathsModule->allPackagesAlwaysPB, SIGNAL(clicked()),
1218                 this, SLOT(allPackagesAlways()));
1219         connect(mathsModule->allPackagesNotPB, SIGNAL(clicked()),
1220                 this, SLOT(allPackagesNot()));
1221         connect(mathsModule->allPackagesAutoPB, SIGNAL(clicked()),
1222                 this, SLOT(change_adaptor()));
1223         connect(mathsModule->allPackagesAlwaysPB, SIGNAL(clicked()),
1224                 this, SLOT(change_adaptor()));
1225         connect(mathsModule->allPackagesNotPB, SIGNAL(clicked()),
1226                 this, SLOT(change_adaptor()));
1227
1228
1229         // latex class
1230         latexModule = new UiWidget<Ui::LaTeXUi>;
1231         connect(latexModule->optionsLE, SIGNAL(textChanged(QString)),
1232                 this, SLOT(change_adaptor()));
1233         connect(latexModule->defaultOptionsCB, SIGNAL(clicked()),
1234                 this, SLOT(change_adaptor()));
1235         connect(latexModule->psdriverCO, SIGNAL(activated(int)),
1236                 this, SLOT(change_adaptor()));
1237         connect(latexModule->classCO, SIGNAL(activated(int)),
1238                 this, SLOT(classChanged_adaptor()));
1239         connect(latexModule->classCO, SIGNAL(activated(int)),
1240                 this, SLOT(change_adaptor()));
1241         connect(latexModule->layoutPB, SIGNAL(clicked()),
1242                 this, SLOT(browseLayout()));
1243         connect(latexModule->layoutPB, SIGNAL(clicked()),
1244                 this, SLOT(change_adaptor()));
1245         connect(latexModule->childDocGB, SIGNAL(clicked()),
1246                 this, SLOT(change_adaptor()));
1247         connect(latexModule->childDocLE, SIGNAL(textChanged(QString)),
1248                 this, SLOT(change_adaptor()));
1249         connect(latexModule->childDocPB, SIGNAL(clicked()),
1250                 this, SLOT(browseMaster()));
1251         connect(latexModule->suppressDateCB, SIGNAL(clicked()),
1252                 this, SLOT(change_adaptor()));
1253         connect(latexModule->refstyleCB, SIGNAL(clicked()),
1254                 this, SLOT(change_adaptor()));
1255
1256         latexModule->optionsLE->setValidator(new NoNewLineValidator(
1257                 latexModule->optionsLE));
1258         latexModule->childDocLE->setValidator(new NoNewLineValidator(
1259                 latexModule->childDocLE));
1260
1261         // postscript drivers
1262         for (int n = 0; tex_graphics[n][0]; ++n) {
1263                 QString enc = qt_(tex_graphics_gui[n]);
1264                 latexModule->psdriverCO->addItem(enc);
1265         }
1266         // latex classes
1267         LayoutFileList const & bcl = LayoutFileList::get();
1268         vector<LayoutFileIndex> classList = bcl.classList();
1269         sort(classList.begin(), classList.end(), less_textclass_avail_desc());
1270
1271         vector<LayoutFileIndex>::const_iterator cit  = classList.begin();
1272         vector<LayoutFileIndex>::const_iterator cen = classList.end();
1273         for (int i = 0; cit != cen; ++cit, ++i) {
1274                 LayoutFile const & tc = bcl[*cit];
1275                 bool const available = tc.isTeXClassAvailable();
1276                 docstring const guiname = translateIfPossible(from_utf8(tc.description()));
1277                 // tooltip sensu "KOMA-Script Article [Class 'scrartcl']"
1278                 QString tooltip = toqstr(bformat(_("%1$s [Class '%2$s']"), guiname, from_utf8(tc.latexname())));
1279                 if (!available) {
1280                         docstring const output_type = (tc.outputType() == lyx::DOCBOOK) ? _("DocBook") : _("LaTeX");
1281                         tooltip += '\n' + toqstr(wrap(bformat(_("Class not found by LyX. "
1282                                                            "Please check if you have the matching %1$s class "
1283                                                            "and all required packages (%2$s) installed."),
1284                                                          output_type, from_utf8(tc.prerequisites(", ")))));
1285                 }
1286                 latexModule->classCO->addItemSort(toqstr(tc.name()),
1287                                                   toqstr(guiname),
1288                                                   toqstr(translateIfPossible(from_utf8(tc.category()))),
1289                                                   tooltip,
1290                                                   true, true, true, available);
1291         }
1292
1293
1294         // branches
1295         branchesModule = new GuiBranches;
1296         connect(branchesModule, SIGNAL(changed()),
1297                 this, SLOT(change_adaptor()));
1298         connect(branchesModule, SIGNAL(renameBranches(docstring const &, docstring const &)),
1299                 this, SLOT(branchesRename(docstring const &, docstring const &)));
1300         connect(branchesModule, SIGNAL(okPressed()), this, SLOT(slotOK()));
1301         updateUnknownBranches();
1302
1303
1304         // preamble
1305         preambleModule = new PreambleModule;
1306         connect(preambleModule, SIGNAL(changed()),
1307                 this, SLOT(change_adaptor()));
1308
1309         localLayout = new LocalLayout;
1310         connect(localLayout, SIGNAL(changed()),
1311                 this, SLOT(change_adaptor()));
1312
1313
1314         // bullets
1315         bulletsModule = new BulletsModule;
1316         connect(bulletsModule, SIGNAL(changed()),
1317                 this, SLOT(change_adaptor()));
1318
1319
1320         // Modules
1321         modulesModule = new UiWidget<Ui::ModulesUi>;
1322         modulesModule->availableLV->header()->setVisible(false);
1323         setSectionResizeMode(modulesModule->availableLV->header(), QHeaderView::ResizeToContents);
1324         modulesModule->availableLV->header()->setStretchLastSection(false);
1325         selectionManager =
1326                 new ModuleSelectionManager(modulesModule->availableLV,
1327                         modulesModule->selectedLV,
1328                         modulesModule->addPB, modulesModule->deletePB,
1329                         modulesModule->upPB, modulesModule->downPB,
1330                         availableModel(), selectedModel(), this);
1331         connect(selectionManager, SIGNAL(updateHook()),
1332                 this, SLOT(updateModuleInfo()));
1333         connect(selectionManager, SIGNAL(selectionChanged()),
1334                 this, SLOT(modulesChanged()));
1335
1336
1337         // PDF support
1338         pdfSupportModule = new UiWidget<Ui::PDFSupportUi>;
1339         connect(pdfSupportModule->use_hyperrefGB, SIGNAL(toggled(bool)),
1340                 this, SLOT(change_adaptor()));
1341         connect(pdfSupportModule->titleLE, SIGNAL(textChanged(QString)),
1342                 this, SLOT(change_adaptor()));
1343         connect(pdfSupportModule->authorLE, SIGNAL(textChanged(QString)),
1344                 this, SLOT(change_adaptor()));
1345         connect(pdfSupportModule->subjectLE, SIGNAL(textChanged(QString)),
1346                 this, SLOT(change_adaptor()));
1347         connect(pdfSupportModule->keywordsLE, SIGNAL(textChanged(QString)),
1348                 this, SLOT(change_adaptor()));
1349         connect(pdfSupportModule->bookmarksGB, SIGNAL(toggled(bool)),
1350                 this, SLOT(change_adaptor()));
1351         connect(pdfSupportModule->bookmarksnumberedCB, SIGNAL(toggled(bool)),
1352                 this, SLOT(change_adaptor()));
1353         connect(pdfSupportModule->bookmarksopenGB, SIGNAL(toggled(bool)),
1354                 this, SLOT(change_adaptor()));
1355         connect(pdfSupportModule->bookmarksopenlevelSB, SIGNAL(valueChanged(int)),
1356                 this, SLOT(change_adaptor()));
1357         connect(pdfSupportModule->breaklinksCB, SIGNAL(toggled(bool)),
1358                 this, SLOT(change_adaptor()));
1359         connect(pdfSupportModule->pdfborderCB, SIGNAL(toggled(bool)),
1360                 this, SLOT(change_adaptor()));
1361         connect(pdfSupportModule->colorlinksCB, SIGNAL(toggled(bool)),
1362                 this, SLOT(change_adaptor()));
1363         connect(pdfSupportModule->backrefCO, SIGNAL(activated(int)),
1364                 this, SLOT(change_adaptor()));
1365         connect(pdfSupportModule->pdfusetitleCB, SIGNAL(toggled(bool)),
1366                 this, SLOT(change_adaptor()));
1367         connect(pdfSupportModule->fullscreenCB, SIGNAL(toggled(bool)),
1368                 this, SLOT(change_adaptor()));
1369         connect(pdfSupportModule->optionsLE, SIGNAL(textChanged(QString)),
1370                 this, SLOT(change_adaptor()));
1371
1372         pdfSupportModule->titleLE->setValidator(new NoNewLineValidator(
1373                 pdfSupportModule->titleLE));
1374         pdfSupportModule->authorLE->setValidator(new NoNewLineValidator(
1375                 pdfSupportModule->authorLE));
1376         pdfSupportModule->subjectLE->setValidator(new NoNewLineValidator(
1377                 pdfSupportModule->subjectLE));
1378         pdfSupportModule->keywordsLE->setValidator(new NoNewLineValidator(
1379                 pdfSupportModule->keywordsLE));
1380         pdfSupportModule->optionsLE->setValidator(new NoNewLineValidator(
1381                 pdfSupportModule->optionsLE));
1382
1383         for (int i = 0; backref_opts[i][0]; ++i)
1384                 pdfSupportModule->backrefCO->addItem(qt_(backref_opts_gui[i]));
1385
1386
1387         // float
1388         floatModule = new FloatPlacement;
1389         connect(floatModule, SIGNAL(changed()),
1390                 this, SLOT(change_adaptor()));
1391
1392
1393         // listings
1394         listingsModule = new UiWidget<Ui::ListingsSettingsUi>;
1395         connect(listingsModule->listingsED, SIGNAL(textChanged()),
1396                 this, SLOT(change_adaptor()));
1397         connect(listingsModule->bypassCB, SIGNAL(clicked()),
1398                 this, SLOT(change_adaptor()));
1399         connect(listingsModule->bypassCB, SIGNAL(clicked()),
1400                 this, SLOT(setListingsMessage()));
1401         connect(listingsModule->listingsED, SIGNAL(textChanged()),
1402                 this, SLOT(setListingsMessage()));
1403         listingsModule->listingsTB->setPlainText(
1404                 qt_("Input listings parameters below. Enter ? for a list of parameters."));
1405
1406
1407         // add the panels
1408         docPS->addPanel(latexModule, N_("Document Class"));
1409         docPS->addPanel(masterChildModule, N_("Child Documents"));
1410         docPS->addPanel(modulesModule, N_("Modules"));
1411         docPS->addPanel(localLayout, N_("Local Layout"));
1412         docPS->addPanel(fontModule, N_("Fonts"));
1413         docPS->addPanel(textLayoutModule, N_("Text Layout"));
1414         docPS->addPanel(pageLayoutModule, N_("Page Layout"));
1415         docPS->addPanel(marginsModule, N_("Page Margins"));
1416         docPS->addPanel(langModule, N_("Language"));
1417         docPS->addPanel(colorModule, N_("Colors"));
1418         docPS->addPanel(numberingModule, N_("Numbering & TOC"));
1419         docPS->addPanel(biblioModule, N_("Bibliography"));
1420         docPS->addPanel(indicesModule, N_("Indexes"));
1421         docPS->addPanel(pdfSupportModule, N_("PDF Properties"));
1422         docPS->addPanel(mathsModule, N_("Math Options"));
1423         docPS->addPanel(floatModule, N_("Float Placement"));
1424         docPS->addPanel(listingsModule, N_("Listings[[inset]]"));
1425         docPS->addPanel(bulletsModule, N_("Bullets"));
1426         docPS->addPanel(branchesModule, N_("Branches"));
1427         docPS->addPanel(outputModule, N_("Output"));
1428         docPS->addPanel(preambleModule, N_("LaTeX Preamble"));
1429         docPS->setCurrentPanel("Document Class");
1430 // FIXME: hack to work around resizing bug in Qt >= 4.2
1431 // bug verified with Qt 4.2.{0-3} (JSpitzm)
1432 #if QT_VERSION >= 0x040200
1433         docPS->updateGeometry();
1434 #endif
1435 }
1436
1437
1438 void GuiDocument::saveDefaultClicked()
1439 {
1440         saveDocDefault();
1441 }
1442
1443
1444 void GuiDocument::useDefaultsClicked()
1445 {
1446         useClassDefaults();
1447 }
1448
1449
1450 void GuiDocument::change_adaptor()
1451 {
1452         nonModuleChanged_ = true;
1453         changed();
1454 }
1455
1456
1457 void GuiDocument::includeonlyClicked(QTreeWidgetItem * item, int)
1458 {
1459         if (item == 0)
1460                 return;
1461
1462         string child = fromqstr(item->text(0));
1463         if (child.empty())
1464                 return;
1465
1466         if (std::find(includeonlys_.begin(),
1467                       includeonlys_.end(), child) != includeonlys_.end())
1468                 includeonlys_.remove(child);
1469         else
1470                 includeonlys_.push_back(child);
1471
1472         updateIncludeonlys();
1473         change_adaptor();
1474 }
1475
1476
1477 QString GuiDocument::validateListingsParameters()
1478 {
1479         // use a cache here to avoid repeated validation
1480         // of the same parameters
1481         // FIXME THREAD
1482         static string param_cache;
1483         static QString msg_cache;
1484
1485         if (listingsModule->bypassCB->isChecked())
1486                 return QString();
1487
1488         string params = fromqstr(listingsModule->listingsED->toPlainText());
1489         if (params != param_cache) {
1490                 param_cache = params;
1491                 msg_cache = toqstr(InsetListingsParams(params).validate());
1492         }
1493         return msg_cache;
1494 }
1495
1496
1497 void GuiDocument::setListingsMessage()
1498 {
1499         // FIXME THREAD
1500         static bool isOK = true;
1501         QString msg = validateListingsParameters();
1502         if (msg.isEmpty()) {
1503                 if (isOK)
1504                         return;
1505                 isOK = true;
1506                 // listingsTB->setTextColor("black");
1507                 listingsModule->listingsTB->setPlainText(
1508                         qt_("Input listings parameters below. "
1509                             "Enter ? for a list of parameters."));
1510         } else {
1511                 isOK = false;
1512                 // listingsTB->setTextColor("red");
1513                 listingsModule->listingsTB->setPlainText(msg);
1514         }
1515 }
1516
1517
1518 void GuiDocument::setLSpacing(int item)
1519 {
1520         textLayoutModule->lspacingLE->setEnabled(item == 3);
1521 }
1522
1523
1524 void GuiDocument::setIndent(int item)
1525 {
1526         bool const enable = (item == 1);
1527         textLayoutModule->indentLE->setEnabled(enable);
1528         textLayoutModule->indentLengthCO->setEnabled(enable);
1529         textLayoutModule->skipLE->setEnabled(false);
1530         textLayoutModule->skipLengthCO->setEnabled(false);
1531         isValid();
1532 }
1533
1534
1535 void GuiDocument::enableIndent(bool indent)
1536 {
1537         textLayoutModule->skipLE->setEnabled(!indent);
1538         textLayoutModule->skipLengthCO->setEnabled(!indent);
1539         if (indent)
1540                 setIndent(textLayoutModule->indentCO->currentIndex());
1541 }
1542
1543
1544 void GuiDocument::setSkip(int item)
1545 {
1546         bool const enable = (item == 3);
1547         textLayoutModule->skipLE->setEnabled(enable);
1548         textLayoutModule->skipLengthCO->setEnabled(enable);
1549         isValid();
1550 }
1551
1552
1553 void GuiDocument::enableSkip(bool skip)
1554 {
1555         textLayoutModule->indentLE->setEnabled(!skip);
1556         textLayoutModule->indentLengthCO->setEnabled(!skip);
1557         if (skip)
1558                 setSkip(textLayoutModule->skipCO->currentIndex());
1559 }
1560
1561
1562 void GuiDocument::setMargins()
1563 {
1564         bool const extern_geometry =
1565                 documentClass().provides("geometry");
1566         marginsModule->marginCB->setEnabled(!extern_geometry);
1567         if (extern_geometry) {
1568                 marginsModule->marginCB->setChecked(false);
1569                 setCustomMargins(true);
1570         } else {
1571                 marginsModule->marginCB->setChecked(!bp_.use_geometry);
1572                 setCustomMargins(!bp_.use_geometry);
1573         }
1574 }
1575
1576
1577 void GuiDocument::papersizeChanged(int paper_size)
1578 {
1579         setCustomPapersize(paper_size == 1);
1580 }
1581
1582
1583 void GuiDocument::setCustomPapersize(bool custom)
1584 {
1585         pageLayoutModule->paperwidthL->setEnabled(custom);
1586         pageLayoutModule->paperwidthLE->setEnabled(custom);
1587         pageLayoutModule->paperwidthUnitCO->setEnabled(custom);
1588         pageLayoutModule->paperheightL->setEnabled(custom);
1589         pageLayoutModule->paperheightLE->setEnabled(custom);
1590         pageLayoutModule->paperheightLE->setFocus();
1591         pageLayoutModule->paperheightUnitCO->setEnabled(custom);
1592 }
1593
1594
1595 void GuiDocument::setColSep()
1596 {
1597         setCustomMargins(marginsModule->marginCB->checkState() == Qt::Checked);
1598 }
1599
1600
1601 void GuiDocument::setCustomMargins(bool custom)
1602 {
1603         marginsModule->topL->setEnabled(!custom);
1604         marginsModule->topLE->setEnabled(!custom);
1605         marginsModule->topUnit->setEnabled(!custom);
1606
1607         marginsModule->bottomL->setEnabled(!custom);
1608         marginsModule->bottomLE->setEnabled(!custom);
1609         marginsModule->bottomUnit->setEnabled(!custom);
1610
1611         marginsModule->innerL->setEnabled(!custom);
1612         marginsModule->innerLE->setEnabled(!custom);
1613         marginsModule->innerUnit->setEnabled(!custom);
1614
1615         marginsModule->outerL->setEnabled(!custom);
1616         marginsModule->outerLE->setEnabled(!custom);
1617         marginsModule->outerUnit->setEnabled(!custom);
1618
1619         marginsModule->headheightL->setEnabled(!custom);
1620         marginsModule->headheightLE->setEnabled(!custom);
1621         marginsModule->headheightUnit->setEnabled(!custom);
1622
1623         marginsModule->headsepL->setEnabled(!custom);
1624         marginsModule->headsepLE->setEnabled(!custom);
1625         marginsModule->headsepUnit->setEnabled(!custom);
1626
1627         marginsModule->footskipL->setEnabled(!custom);
1628         marginsModule->footskipLE->setEnabled(!custom);
1629         marginsModule->footskipUnit->setEnabled(!custom);
1630
1631         bool const enableColSep = !custom &&
1632                         textLayoutModule->twoColumnCB->checkState() == Qt::Checked;
1633         marginsModule->columnsepL->setEnabled(enableColSep);
1634         marginsModule->columnsepLE->setEnabled(enableColSep);
1635         marginsModule->columnsepUnit->setEnabled(enableColSep);
1636 }
1637
1638
1639 void GuiDocument::changeBackgroundColor()
1640 {
1641         QColor const & newColor = QColorDialog::getColor(
1642                 rgb2qcolor(set_backgroundcolor), asQWidget());
1643         if (!newColor.isValid())
1644                 return;
1645         // set the button color and text
1646         colorModule->backgroundPB->setStyleSheet(
1647                 colorButtonStyleSheet(newColor));
1648         colorModule->backgroundPB->setText(qt_("&Change..."));
1649         // save color
1650         set_backgroundcolor = rgbFromHexName(fromqstr(newColor.name()));
1651         is_backgroundcolor = true;
1652         change_adaptor();
1653 }
1654
1655
1656 void GuiDocument::deleteBackgroundColor()
1657 {
1658         // set the button color back to default by setting an empty StyleSheet
1659         colorModule->backgroundPB->setStyleSheet(QLatin1String(""));
1660         // change button text
1661         colorModule->backgroundPB->setText(qt_("&Default..."));
1662         // save default color (white)
1663         set_backgroundcolor = rgbFromHexName("#ffffff");
1664         is_backgroundcolor = false;
1665         change_adaptor();
1666 }
1667
1668
1669 void GuiDocument::changeFontColor()
1670 {
1671         QColor const & newColor = QColorDialog::getColor(
1672                 rgb2qcolor(set_fontcolor), asQWidget());
1673         if (!newColor.isValid())
1674                 return;
1675         // set the button color and text
1676         colorModule->fontColorPB->setStyleSheet(
1677                 colorButtonStyleSheet(newColor));
1678         colorModule->fontColorPB->setText(qt_("&Change..."));
1679         // save color
1680         set_fontcolor = rgbFromHexName(fromqstr(newColor.name()));
1681         is_fontcolor = true;
1682         change_adaptor();
1683 }
1684
1685
1686 void GuiDocument::deleteFontColor()
1687 {
1688         // set the button color back to default by setting an empty StyleSheet
1689         colorModule->fontColorPB->setStyleSheet(QLatin1String(""));
1690         // change button text
1691         colorModule->fontColorPB->setText(qt_("&Default..."));
1692         // save default color (black)
1693         set_fontcolor = rgbFromHexName("#000000");
1694         is_fontcolor = false;
1695         change_adaptor();
1696 }
1697
1698
1699 void GuiDocument::changeNoteFontColor()
1700 {
1701         QColor const & newColor = QColorDialog::getColor(
1702                 rgb2qcolor(set_notefontcolor), asQWidget());
1703         if (!newColor.isValid())
1704                 return;
1705         // set the button color
1706         colorModule->noteFontColorPB->setStyleSheet(
1707                 colorButtonStyleSheet(newColor));
1708         // save color
1709         set_notefontcolor = rgbFromHexName(fromqstr(newColor.name()));
1710         change_adaptor();
1711 }
1712
1713
1714 void GuiDocument::deleteNoteFontColor()
1715 {
1716         // set the button color back to pref
1717         theApp()->getRgbColor(Color_greyedouttext, set_notefontcolor);
1718         colorModule->noteFontColorPB->setStyleSheet(
1719                 colorButtonStyleSheet(rgb2qcolor(set_notefontcolor)));
1720         change_adaptor();
1721 }
1722
1723
1724 void GuiDocument::changeBoxBackgroundColor()
1725 {
1726         QColor const & newColor = QColorDialog::getColor(
1727                 rgb2qcolor(set_boxbgcolor), asQWidget());
1728         if (!newColor.isValid())
1729                 return;
1730         // set the button color
1731         colorModule->boxBackgroundPB->setStyleSheet(
1732                 colorButtonStyleSheet(newColor));
1733         // save color
1734         set_boxbgcolor = rgbFromHexName(fromqstr(newColor.name()));
1735         change_adaptor();
1736 }
1737
1738
1739 void GuiDocument::deleteBoxBackgroundColor()
1740 {
1741         // set the button color back to pref
1742         theApp()->getRgbColor(Color_shadedbg, set_boxbgcolor);
1743         colorModule->boxBackgroundPB->setStyleSheet(
1744                 colorButtonStyleSheet(rgb2qcolor(set_boxbgcolor)));
1745         change_adaptor();
1746 }
1747
1748
1749 void GuiDocument::languageChanged(int i)
1750 {
1751         // some languages only work with polyglossia/XeTeX
1752         Language const * lang = lyx::languages.getLanguage(
1753                 fromqstr(langModule->languageCO->itemData(i).toString()));
1754         if (lang->babel().empty() && !lang->polyglossia().empty()) {
1755                         // If we force to switch fontspec on, store
1756                         // current state (#8717)
1757                         if (fontModule->osFontsCB->isEnabled())
1758                                 forced_fontspec_activation =
1759                                         !fontModule->osFontsCB->isChecked();
1760                         fontModule->osFontsCB->setChecked(true);
1761                         fontModule->osFontsCB->setEnabled(false);
1762         }
1763         else {
1764                 fontModule->osFontsCB->setEnabled(true);
1765                 // If we have forced to switch fontspec on,
1766                 // restore previous state (#8717)
1767                 if (forced_fontspec_activation)
1768                         fontModule->osFontsCB->setChecked(false);
1769                 forced_fontspec_activation = false;
1770         }
1771
1772         // set appropriate quotation mark style
1773         if (!lang->quoteStyle().empty()) {
1774                 langModule->quoteStyleCO->setCurrentIndex(
1775                         bp_.getQuoteStyle(lang->quoteStyle()));
1776         }
1777 }
1778
1779
1780 void GuiDocument::osFontsChanged(bool nontexfonts)
1781 {
1782         bool const tex_fonts = !nontexfonts;
1783         // store current fonts
1784         QString const font_roman = fontModule->fontsRomanCO->itemData(
1785                         fontModule->fontsRomanCO->currentIndex()).toString();
1786         QString const font_sans = fontModule->fontsSansCO->itemData(
1787                         fontModule->fontsSansCO->currentIndex()).toString();
1788         QString const font_typewriter = fontModule->fontsTypewriterCO->itemData(
1789                         fontModule->fontsTypewriterCO->currentIndex()).toString();
1790         QString const font_math = fontModule->fontsMathCO->itemData(
1791                         fontModule->fontsMathCO->currentIndex()).toString();
1792         int const font_sf_scale = fontModule->scaleSansSB->value();
1793         int const font_tt_scale = fontModule->scaleTypewriterSB->value();
1794
1795         updateFontlist();
1796         // store default format
1797         QString const dformat = outputModule->defaultFormatCO->itemData(
1798                 outputModule->defaultFormatCO->currentIndex()).toString();
1799         updateDefaultFormat();
1800         // try to restore default format
1801         int index = outputModule->defaultFormatCO->findData(dformat);
1802         // set to default if format is not found
1803         if (index == -1)
1804                 index = 0;
1805         outputModule->defaultFormatCO->setCurrentIndex(index);
1806
1807         // try to restore fonts which were selected two toggles ago
1808         index = fontModule->fontsRomanCO->findData(fontModule->font_roman);
1809         if (index != -1)
1810                 fontModule->fontsRomanCO->setCurrentIndex(index);
1811         index = fontModule->fontsSansCO->findData(fontModule->font_sans);
1812         if (index != -1)
1813                 fontModule->fontsSansCO->setCurrentIndex(index);
1814         index = fontModule->fontsTypewriterCO->findData(fontModule->font_typewriter);
1815         if (index != -1)
1816                 fontModule->fontsTypewriterCO->setCurrentIndex(index);
1817         index = fontModule->fontsMathCO->findData(fontModule->font_math);
1818         if (index != -1)
1819                 fontModule->fontsMathCO->setCurrentIndex(index);
1820         // save fonts for next next toggle
1821         fontModule->font_roman = font_roman;
1822         fontModule->font_sans = font_sans;
1823         fontModule->font_typewriter = font_typewriter;
1824         fontModule->font_math = font_math;
1825         fontModule->font_sf_scale = font_sf_scale;
1826         fontModule->font_tt_scale = font_tt_scale;
1827
1828         langModule->encodingCO->setEnabled(tex_fonts &&
1829                 !langModule->defaultencodingRB->isChecked());
1830         langModule->defaultencodingRB->setEnabled(tex_fonts);
1831         langModule->otherencodingRB->setEnabled(tex_fonts);
1832
1833         fontModule->fontsDefaultCO->setEnabled(tex_fonts);
1834         fontModule->fontsDefaultLA->setEnabled(tex_fonts);
1835         fontModule->cjkFontLE->setEnabled(tex_fonts);
1836         fontModule->cjkFontLA->setEnabled(tex_fonts);
1837
1838         updateFontOptions();
1839
1840         fontModule->fontencLA->setEnabled(tex_fonts);
1841         fontModule->fontencCO->setEnabled(tex_fonts);
1842         if (!tex_fonts)
1843                 fontModule->fontencLE->setEnabled(false);
1844         else
1845                 fontencChanged(fontModule->fontencCO->currentIndex());
1846 }
1847
1848
1849 void GuiDocument::mathFontChanged(int)
1850 {
1851         updateFontOptions();
1852 }
1853
1854
1855 void GuiDocument::fontOsfToggled(bool state)
1856 {
1857         if (fontModule->osFontsCB->isChecked())
1858                 return;
1859         QString font = fontModule->fontsRomanCO->itemData(
1860                         fontModule->fontsRomanCO->currentIndex()).toString();
1861         if (hasMonolithicExpertSet(font))
1862                 fontModule->fontScCB->setChecked(state);
1863 }
1864
1865
1866 void GuiDocument::fontScToggled(bool state)
1867 {
1868         if (fontModule->osFontsCB->isChecked())
1869                 return;
1870         QString font = fontModule->fontsRomanCO->itemData(
1871                         fontModule->fontsRomanCO->currentIndex()).toString();
1872         if (hasMonolithicExpertSet(font))
1873                 fontModule->fontOsfCB->setChecked(state);
1874 }
1875
1876
1877 void GuiDocument::updateFontOptions()
1878 {
1879         bool const tex_fonts = !fontModule->osFontsCB->isChecked();
1880         QString font;
1881         if (tex_fonts)
1882                 font = fontModule->fontsSansCO->itemData(
1883                                 fontModule->fontsSansCO->currentIndex()).toString();
1884         bool scaleable = providesScale(font);
1885         fontModule->scaleSansSB->setEnabled(scaleable);
1886         fontModule->scaleSansLA->setEnabled(scaleable);
1887         if (tex_fonts)
1888                 font = fontModule->fontsTypewriterCO->itemData(
1889                                 fontModule->fontsTypewriterCO->currentIndex()).toString();
1890         scaleable = providesScale(font);
1891         fontModule->scaleTypewriterSB->setEnabled(scaleable);
1892         fontModule->scaleTypewriterLA->setEnabled(scaleable);
1893         if (tex_fonts)
1894                 font = fontModule->fontsRomanCO->itemData(
1895                                 fontModule->fontsRomanCO->currentIndex()).toString();
1896         fontModule->fontScCB->setEnabled(providesSC(font));
1897         fontModule->fontOsfCB->setEnabled(providesOSF(font));
1898         updateMathFonts(font);
1899 }
1900
1901
1902 void GuiDocument::updateFontsize(string const & items, string const & sel)
1903 {
1904         fontModule->fontsizeCO->clear();
1905         fontModule->fontsizeCO->addItem(qt_("Default"));
1906
1907         for (int n = 0; !token(items,'|',n).empty(); ++n)
1908                 fontModule->fontsizeCO->
1909                         addItem(toqstr(token(items,'|',n)));
1910
1911         for (int n = 0; n < fontModule->fontsizeCO->count(); ++n) {
1912                 if (fromqstr(fontModule->fontsizeCO->itemText(n)) == sel) {
1913                         fontModule->fontsizeCO->setCurrentIndex(n);
1914                         break;
1915                 }
1916         }
1917 }
1918
1919
1920 bool GuiDocument::ot1() const
1921 {
1922         QString const fontenc =
1923                 fontModule->fontencCO->itemData(fontModule->fontencCO->currentIndex()).toString();
1924         return (fontenc == "default"
1925                 || (fontenc == "global" && (lyxrc.fontenc == "default" || lyxrc.fontenc == "OT1"))
1926                 || (fontenc == "custom" && fontModule->fontencLE->text() == "OT1"));
1927 }
1928
1929
1930 bool GuiDocument::completeFontset() const
1931 {
1932         return (fontModule->fontsSansCO->itemData(
1933                         fontModule->fontsSansCO->currentIndex()).toString() == "default"
1934                 && fontModule->fontsSansCO->itemData(
1935                         fontModule->fontsTypewriterCO->currentIndex()).toString() == "default");
1936 }
1937
1938
1939 bool GuiDocument::noMathFont() const
1940 {
1941         return (fontModule->fontsMathCO->itemData(
1942                 fontModule->fontsMathCO->currentIndex()).toString() == "default");
1943 }
1944
1945
1946 void GuiDocument::updateTexFonts()
1947 {
1948         LaTeXFonts::TexFontMap texfontmap = theLaTeXFonts().getLaTeXFonts();
1949
1950         LaTeXFonts::TexFontMap::const_iterator it = texfontmap.begin();
1951         LaTeXFonts::TexFontMap::const_iterator end = texfontmap.end();
1952         for (; it != end; ++it) {
1953                 LaTeXFont lf = it->second;
1954                 if (lf.name().empty()) {
1955                         LYXERR0("Error: Unnamed font: " << it->first);
1956                         continue;
1957                 }
1958                 docstring const family = lf.family();
1959                 docstring guiname = translateIfPossible(lf.guiname());
1960                 if (!lf.available(ot1(), noMathFont()))
1961                         guiname += _(" (not installed)");
1962                 if (family == "rm")
1963                         rmfonts_.insert(toqstr(guiname), toqstr(it->first));
1964                 else if (family == "sf")
1965                         sffonts_.insert(toqstr(guiname), toqstr(it->first));
1966                 else if (family == "tt")
1967                         ttfonts_.insert(toqstr(guiname), toqstr(it->first));
1968                 else if (family == "math")
1969                         mathfonts_.insert(toqstr(guiname), toqstr(it->first));
1970         }
1971 }
1972
1973
1974 void GuiDocument::updateFontlist()
1975 {
1976         fontModule->fontsRomanCO->clear();
1977         fontModule->fontsSansCO->clear();
1978         fontModule->fontsTypewriterCO->clear();
1979         fontModule->fontsMathCO->clear();
1980
1981         // With fontspec (XeTeX, LuaTeX), we have access to all system fonts, but not the LaTeX fonts
1982         if (fontModule->osFontsCB->isChecked()) {
1983                 fontModule->fontsRomanCO->addItem(qt_("Default"), QString("default"));
1984                 fontModule->fontsSansCO->addItem(qt_("Default"), QString("default"));
1985                 fontModule->fontsTypewriterCO->addItem(qt_("Default"), QString("default"));
1986                 QString unimath = qt_("Non-TeX Fonts Default");
1987                 if (!LaTeXFeatures::isAvailable("unicode-math"))
1988                         unimath += qt_(" (not available)");
1989                 fontModule->fontsMathCO->addItem(qt_("Class Default (TeX Fonts)"), QString("auto"));
1990                 fontModule->fontsMathCO->addItem(unimath, QString("default"));
1991
1992                 QFontDatabase fontdb;
1993                 QStringList families(fontdb.families());
1994                 for (QStringList::Iterator it = families.begin(); it != families.end(); ++it) {
1995                         fontModule->fontsRomanCO->addItem(*it, *it);
1996                         fontModule->fontsSansCO->addItem(*it, *it);
1997                         fontModule->fontsTypewriterCO->addItem(*it, *it);
1998                 }
1999                 return;
2000         }
2001
2002         if (rmfonts_.empty())
2003                 updateTexFonts();
2004
2005         fontModule->fontsRomanCO->addItem(qt_("Default"), QString("default"));
2006         QMap<QString, QString>::const_iterator rmi = rmfonts_.constBegin();
2007         while (rmi != rmfonts_.constEnd()) {
2008                 fontModule->fontsRomanCO->addItem(rmi.key(), rmi.value());
2009                 ++rmi;
2010         }
2011
2012         fontModule->fontsSansCO->addItem(qt_("Default"), QString("default"));
2013         QMap<QString, QString>::const_iterator sfi = sffonts_.constBegin();
2014         while (sfi != sffonts_.constEnd()) {
2015                 fontModule->fontsSansCO->addItem(sfi.key(), sfi.value());
2016                 ++sfi;
2017         }
2018
2019         fontModule->fontsTypewriterCO->addItem(qt_("Default"), QString("default"));
2020         QMap<QString, QString>::const_iterator tti = ttfonts_.constBegin();
2021         while (tti != ttfonts_.constEnd()) {
2022                 fontModule->fontsTypewriterCO->addItem(tti.key(), tti.value());
2023                 ++tti;
2024         }
2025
2026         fontModule->fontsMathCO->addItem(qt_("Automatic"), QString("auto"));
2027         fontModule->fontsMathCO->addItem(qt_("Class Default"), QString("default"));
2028         QMap<QString, QString>::const_iterator mmi = mathfonts_.constBegin();
2029         while (mmi != mathfonts_.constEnd()) {
2030                 fontModule->fontsMathCO->addItem(mmi.key(), mmi.value());
2031                 ++mmi;
2032         }
2033 }
2034
2035
2036 void GuiDocument::fontencChanged(int item)
2037 {
2038         fontModule->fontencLE->setEnabled(
2039                 fontModule->fontencCO->itemData(item).toString() == "custom");
2040         // The availability of TeX fonts depends on the font encoding
2041         updateTexFonts();
2042         updateFontOptions();
2043 }
2044
2045
2046 void GuiDocument::updateMathFonts(QString const & rm)
2047 {
2048         if (fontModule->osFontsCB->isChecked())
2049                 return;
2050         QString const math =
2051                 fontModule->fontsMathCO->itemData(fontModule->fontsMathCO->currentIndex()).toString();
2052         int const i = fontModule->fontsMathCO->findData("default");
2053         if (providesNoMath(rm) && i == -1)
2054                 fontModule->fontsMathCO->insertItem(1, qt_("Class Default"), QString("default"));
2055         else if (!providesNoMath(rm) && i != -1) {
2056                 int const c = fontModule->fontsMathCO->currentIndex();
2057                 fontModule->fontsMathCO->removeItem(i);
2058                 if (c == i)
2059                         fontModule->fontsMathCO->setCurrentIndex(0);
2060         }
2061 }
2062
2063
2064 void GuiDocument::romanChanged(int item)
2065 {
2066         if (fontModule->osFontsCB->isChecked())
2067                 return;
2068         QString const font =
2069                 fontModule->fontsRomanCO->itemData(item).toString();
2070         fontModule->fontScCB->setEnabled(providesSC(font));
2071         fontModule->fontOsfCB->setEnabled(providesOSF(font));
2072         updateMathFonts(font);
2073 }
2074
2075
2076 void GuiDocument::sansChanged(int item)
2077 {
2078         if (fontModule->osFontsCB->isChecked())
2079                 return;
2080         QString const font =
2081                 fontModule->fontsSansCO->itemData(item).toString();
2082         bool scaleable = providesScale(font);
2083         fontModule->scaleSansSB->setEnabled(scaleable);
2084         fontModule->scaleSansLA->setEnabled(scaleable);
2085 }
2086
2087
2088 void GuiDocument::ttChanged(int item)
2089 {
2090         if (fontModule->osFontsCB->isChecked())
2091                 return;
2092         QString const font =
2093                 fontModule->fontsTypewriterCO->itemData(item).toString();
2094         bool scaleable = providesScale(font);
2095         fontModule->scaleTypewriterSB->setEnabled(scaleable);
2096         fontModule->scaleTypewriterLA->setEnabled(scaleable);
2097 }
2098
2099
2100 void GuiDocument::updatePagestyle(string const & items, string const & sel)
2101 {
2102         pagestyles.clear();
2103         pageLayoutModule->pagestyleCO->clear();
2104         pageLayoutModule->pagestyleCO->addItem(qt_("Default"));
2105
2106         for (int n = 0; !token(items, '|', n).empty(); ++n) {
2107                 string style = token(items, '|', n);
2108                 QString style_gui = qt_(style);
2109                 pagestyles.push_back(pair<string, QString>(style, style_gui));
2110                 pageLayoutModule->pagestyleCO->addItem(style_gui);
2111         }
2112
2113         if (sel == "default") {
2114                 pageLayoutModule->pagestyleCO->setCurrentIndex(0);
2115                 return;
2116         }
2117
2118         int nn = 0;
2119
2120         for (size_t i = 0; i < pagestyles.size(); ++i)
2121                 if (pagestyles[i].first == sel)
2122                         nn = pageLayoutModule->pagestyleCO->findText(pagestyles[i].second);
2123
2124         if (nn > 0)
2125                 pageLayoutModule->pagestyleCO->setCurrentIndex(nn);
2126 }
2127
2128
2129 void GuiDocument::browseLayout()
2130 {
2131         QString const label1 = qt_("Layouts|#o#O");
2132         QString const dir1 = toqstr(lyxrc.document_path);
2133         QStringList const filter(qt_("LyX Layout (*.layout)"));
2134         QString file = browseRelToParent(QString(), bufferFilePath(),
2135                 qt_("Local layout file"), filter, false,
2136                 label1, dir1);
2137
2138         if (!file.endsWith(".layout"))
2139                 return;
2140
2141         FileName layoutFile = support::makeAbsPath(fromqstr(file),
2142                 fromqstr(bufferFilePath()));
2143
2144         int const ret = Alert::prompt(_("Local layout file"),
2145                 _("The layout file you have selected is a local layout\n"
2146                   "file, not one in the system or user directory.\n"
2147                   "Your document will not work with this layout if you\n"
2148                   "move the layout file to a different directory."),
2149                   1, 1, _("&Set Layout"), _("&Cancel"));
2150         if (ret == 1)
2151                 return;
2152
2153         // load the layout file
2154         LayoutFileList & bcl = LayoutFileList::get();
2155         string classname = layoutFile.onlyFileName();
2156         // this will update an existing layout if that layout has been loaded before.
2157         LayoutFileIndex name = support::onlyFileName(bcl.addLocalLayout(
2158                 classname.substr(0, classname.size() - 7),
2159                 layoutFile.onlyPath().absFileName()));
2160
2161         if (name.empty()) {
2162                 Alert::error(_("Error"),
2163                         _("Unable to read local layout file."));
2164                 return;
2165         }
2166
2167         const_cast<Buffer &>(buffer()).setLayoutPos(layoutFile.onlyPath().absFileName());
2168
2169         // do not trigger classChanged if there is no change.
2170         if (latexModule->classCO->currentText() == toqstr(name))
2171                 return;
2172
2173         // add to combo box
2174         bool const avail = latexModule->classCO->set(toqstr(name));
2175         if (!avail) {
2176                 LayoutFile const & tc = bcl[name];
2177                 docstring const guiname = translateIfPossible(from_utf8(tc.description()));
2178                 // tooltip sensu "KOMA-Script Article [Class 'scrartcl']"
2179                 QString tooltip = toqstr(bformat(_("%1$s [Class '%2$s']"), guiname, from_utf8(tc.latexname())));
2180                 tooltip += '\n' + qt_("This is a local layout file.");
2181                 latexModule->classCO->addItemSort(toqstr(tc.name()), toqstr(guiname),
2182                                                   toqstr(translateIfPossible(from_utf8(tc.category()))),
2183                                                   tooltip,
2184                                                   true, true, true, true);
2185                 latexModule->classCO->set(toqstr(name));
2186         }
2187
2188         classChanged();
2189 }
2190
2191
2192 void GuiDocument::browseMaster()
2193 {
2194         QString const title = qt_("Select master document");
2195         QString const dir1 = toqstr(lyxrc.document_path);
2196         QString const old = latexModule->childDocLE->text();
2197         QString const docpath = toqstr(support::onlyPath(buffer().absFileName()));
2198         QStringList const filter(qt_("LyX Files (*.lyx)"));
2199         QString file = browseRelToSub(old, docpath, title, filter, false,
2200                 qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
2201
2202         if (!file.isEmpty())
2203                 latexModule->childDocLE->setText(file);
2204 }
2205
2206
2207 void GuiDocument::classChanged_adaptor()
2208 {
2209         const_cast<Buffer &>(buffer()).setLayoutPos(string());
2210         classChanged();
2211 }
2212
2213
2214 void GuiDocument::classChanged()
2215 {
2216         int idx = latexModule->classCO->currentIndex();
2217         if (idx < 0)
2218                 return;
2219         string const classname = fromqstr(latexModule->classCO->getData(idx));
2220
2221         if (applyPB->isEnabled()) {
2222                 int const ret = Alert::prompt(_("Unapplied changes"),
2223                                 _("Some changes in the dialog were not yet applied.\n"
2224                                 "If you do not apply now, they will be lost after this action."),
2225                                 1, 1, _("&Apply"), _("&Dismiss"));
2226                 if (ret == 0)
2227                         applyView();
2228         }
2229
2230         // We load the TextClass as soon as it is selected. This is
2231         // necessary so that other options in the dialog can be updated
2232         // according to the new class. Note, however, that, if you use
2233         // the scroll wheel when sitting on the combo box, we'll load a
2234         // lot of TextClass objects very quickly....
2235         if (!bp_.setBaseClass(classname)) {
2236                 Alert::error(_("Error"), _("Unable to set document class."));
2237                 return;
2238         }
2239         if (lyxrc.auto_reset_options)
2240                 bp_.useClassDefaults();
2241
2242         // With the introduction of modules came a distinction between the base
2243         // class and the document class. The former corresponds to the main layout
2244         // file; the latter is that plus the modules (or the document-specific layout,
2245         // or  whatever else there could be). Our parameters come from the document
2246         // class. So when we set the base class, we also need to recreate the document
2247         // class. Otherwise, we still have the old one.
2248         bp_.makeDocumentClass();
2249         paramsToDialog();
2250 }
2251
2252
2253 void GuiDocument::languagePackageChanged(int i)
2254 {
2255          langModule->languagePackageLE->setEnabled(
2256                 langModule->languagePackageCO->itemData(i).toString() == "custom");
2257 }
2258
2259
2260 void GuiDocument::biblioChanged()
2261 {
2262         biblioChanged_ = true;
2263         change_adaptor();
2264 }
2265
2266
2267 void GuiDocument::bibtexChanged(int n)
2268 {
2269         biblioModule->bibtexOptionsLE->setEnabled(
2270                 biblioModule->bibtexCO->itemData(n).toString() != "default");
2271         biblioChanged();
2272 }
2273
2274
2275 void GuiDocument::setAuthorYear(bool authoryear)
2276 {
2277         if (authoryear)
2278                 biblioModule->citeStyleCO->setCurrentIndex(0);
2279         biblioChanged();
2280 }
2281
2282
2283 void GuiDocument::setNumerical(bool numerical)
2284 {
2285         if (numerical)
2286                 biblioModule->citeStyleCO->setCurrentIndex(1);
2287         biblioChanged();
2288 }
2289
2290
2291 void GuiDocument::updateEngineType(string const & items, CiteEngineType const & sel)
2292 {
2293         engine_types_.clear();
2294
2295         int nn = 0;
2296
2297         for (int n = 0; !token(items, '|', n).empty(); ++n) {
2298                 nn += 1;
2299                 string style = token(items, '|', n);
2300                 engine_types_.push_back(style);
2301         }
2302
2303         switch (sel) {
2304                 case ENGINE_TYPE_AUTHORYEAR:
2305                         biblioModule->citeStyleCO->setCurrentIndex(0);
2306                         break;
2307                 case ENGINE_TYPE_NUMERICAL:
2308                 case ENGINE_TYPE_DEFAULT:
2309                         biblioModule->citeStyleCO->setCurrentIndex(1);
2310                         break;
2311         }
2312
2313         biblioModule->citationStyleL->setEnabled(nn > 1);
2314         biblioModule->citeStyleCO->setEnabled(nn > 1);
2315
2316         if (nn != 1)
2317                 return;
2318
2319         // If the textclass allows only one of authoryear or numerical,
2320         // we have no choice but to force that engine type.
2321         if (engine_types_[0] == "authoryear")
2322                 biblioModule->citeStyleCO->setCurrentIndex(0);
2323         else
2324                 biblioModule->citeStyleCO->setCurrentIndex(1);
2325 }
2326
2327
2328 namespace {
2329         // FIXME unicode
2330         // both of these should take a vector<docstring>
2331
2332         // This is an insanely complicated attempt to make this sort of thing
2333         // work with RTL languages.
2334         docstring formatStrVec(vector<string> const & v, docstring const & s)
2335         {
2336                 //this mess formats the list as "v[0], v[1], ..., [s] v[n]"
2337                 if (v.empty())
2338                         return docstring();
2339                 if (v.size() == 1)
2340                         return translateIfPossible(from_utf8(v[0]));
2341                 if (v.size() == 2) {
2342                         docstring retval = _("%1$s and %2$s");
2343                         retval = subst(retval, _("and"), s);
2344                         return bformat(retval, translateIfPossible(from_utf8(v[0])),
2345                                        translateIfPossible(from_utf8(v[1])));
2346                 }
2347                 // The idea here is to format all but the last two items...
2348                 int const vSize = v.size();
2349                 docstring t2 = _("%1$s, %2$s");
2350                 docstring retval = translateIfPossible(from_utf8(v[0]));
2351                 for (int i = 1; i < vSize - 2; ++i)
2352                         retval = bformat(t2, retval, translateIfPossible(from_utf8(v[i])));
2353                 //...and then to  plug them, and the last two, into this schema
2354                 docstring t = _("%1$s, %2$s, and %3$s");
2355                 t = subst(t, _("and"), s);
2356                 return bformat(t, retval, translateIfPossible(from_utf8(v[vSize - 2])),
2357                                translateIfPossible(from_utf8(v[vSize - 1])));
2358         }
2359
2360         vector<string> idsToNames(vector<string> const & idList)
2361         {
2362                 vector<string> retval;
2363                 vector<string>::const_iterator it  = idList.begin();
2364                 vector<string>::const_iterator end = idList.end();
2365                 for (; it != end; ++it) {
2366                         LyXModule const * const mod = theModuleList[*it];
2367                         if (!mod)
2368                                 retval.push_back(to_utf8(bformat(_("%1$s (unavailable)"),
2369                                                 translateIfPossible(from_utf8(*it)))));
2370                         else
2371                                 retval.push_back(mod->getName());
2372                 }
2373                 return retval;
2374         }
2375 } // end anonymous namespace
2376
2377
2378 void GuiDocument::modulesToParams(BufferParams & bp)
2379 {
2380         // update list of loaded modules
2381         bp.clearLayoutModules();
2382         int const srows = modules_sel_model_.rowCount();
2383         for (int i = 0; i < srows; ++i)
2384                 bp.addLayoutModule(modules_sel_model_.getIDString(i));
2385
2386         // update the list of removed modules
2387         bp.clearRemovedModules();
2388         LayoutModuleList const & reqmods = bp.baseClass()->defaultModules();
2389         list<string>::const_iterator rit = reqmods.begin();
2390         list<string>::const_iterator ren = reqmods.end();
2391
2392         // check each of the default modules
2393         for (; rit != ren; ++rit) {
2394                 list<string>::const_iterator mit = bp.getModules().begin();
2395                 list<string>::const_iterator men = bp.getModules().end();
2396                 bool found = false;
2397                 for (; mit != men; ++mit) {
2398                         if (*rit == *mit) {
2399                                 found = true;
2400                                 break;
2401                         }
2402                 }
2403                 if (!found) {
2404                         // the module isn't present so must have been removed by the user
2405                         bp.addRemovedModule(*rit);
2406                 }
2407         }
2408 }
2409
2410 void GuiDocument::modulesChanged()
2411 {
2412         modulesToParams(bp_);
2413
2414         if (applyPB->isEnabled() && nonModuleChanged_) {
2415                 int const ret = Alert::prompt(_("Unapplied changes"),
2416                                 _("Some changes in the dialog were not yet applied.\n"
2417                                 "If you do not apply now, they will be lost after this action."),
2418                                 1, 1, _("&Apply"), _("&Dismiss"));
2419                 if (ret == 0)
2420                         applyView();
2421         }
2422
2423         bp_.makeDocumentClass();
2424         paramsToDialog();
2425         changed();
2426 }
2427
2428
2429 void GuiDocument::updateModuleInfo()
2430 {
2431         selectionManager->update();
2432
2433         //Module description
2434         bool const focus_on_selected = selectionManager->selectedFocused();
2435         QAbstractItemView * lv;
2436         if (focus_on_selected)
2437                 lv = modulesModule->selectedLV;
2438         else
2439                 lv = modulesModule->availableLV;
2440         if (lv->selectionModel()->selectedIndexes().isEmpty()) {
2441                 modulesModule->infoML->document()->clear();
2442                 return;
2443         }
2444         QModelIndex const & idx = lv->selectionModel()->currentIndex();
2445         GuiIdListModel const & id_model =
2446                         focus_on_selected  ? modules_sel_model_ : modules_av_model_;
2447         string const modName = id_model.getIDString(idx.row());
2448         docstring desc = getModuleDescription(modName);
2449
2450         LayoutModuleList const & provmods = bp_.baseClass()->providedModules();
2451         if (std::find(provmods.begin(), provmods.end(), modName) != provmods.end()) {
2452                 if (!desc.empty())
2453                         desc += "\n";
2454                 desc += _("Module provided by document class.");
2455         }
2456
2457         docstring cat = getModuleCategory(modName);
2458         if (!cat.empty()) {
2459                 if (!desc.empty())
2460                         desc += "\n";
2461                 desc += bformat(_("Category: %1$s."), cat);
2462         }
2463
2464         vector<string> pkglist = getPackageList(modName);
2465         docstring pkgdesc = formatStrVec(pkglist, _("and"));
2466         if (!pkgdesc.empty()) {
2467                 if (!desc.empty())
2468                         desc += "\n";
2469                 desc += bformat(_("Package(s) required: %1$s."), pkgdesc);
2470         }
2471
2472         pkglist = getRequiredList(modName);
2473         if (!pkglist.empty()) {
2474                 vector<string> const reqdescs = idsToNames(pkglist);
2475                 pkgdesc = formatStrVec(reqdescs, _("or"));
2476                 if (!desc.empty())
2477                         desc += "\n";
2478                 desc += bformat(_("Modules required: %1$s."), pkgdesc);
2479         }
2480
2481         pkglist = getExcludedList(modName);
2482         if (!pkglist.empty()) {
2483                 vector<string> const reqdescs = idsToNames(pkglist);
2484                 pkgdesc = formatStrVec(reqdescs, _( "and"));
2485                 if (!desc.empty())
2486                         desc += "\n";
2487                 desc += bformat(_("Modules excluded: %1$s."), pkgdesc);
2488         }
2489
2490         if (!isModuleAvailable(modName)) {
2491                 if (!desc.empty())
2492                         desc += "\n";
2493                 desc += _("WARNING: Some required packages are unavailable!");
2494         }
2495
2496         modulesModule->infoML->document()->setPlainText(toqstr(desc));
2497 }
2498
2499
2500 void GuiDocument::updateNumbering()
2501 {
2502         DocumentClass const & tclass = documentClass();
2503
2504         numberingModule->tocTW->setUpdatesEnabled(false);
2505         numberingModule->tocTW->clear();
2506
2507         int const depth = numberingModule->depthSL->value();
2508         int const toc = numberingModule->tocSL->value();
2509         QString const no = qt_("No");
2510         QString const yes = qt_("Yes");
2511         QTreeWidgetItem * item = 0;
2512
2513         DocumentClass::const_iterator lit = tclass.begin();
2514         DocumentClass::const_iterator len = tclass.end();
2515         for (; lit != len; ++lit) {
2516                 int const toclevel = lit->toclevel;
2517                 if (toclevel != Layout::NOT_IN_TOC && !lit->counter.empty()) {
2518                         item = new QTreeWidgetItem(numberingModule->tocTW);
2519                         item->setText(0, toqstr(translateIfPossible(lit->name())));
2520                         item->setText(1, (toclevel <= depth) ? yes : no);
2521                         item->setText(2, (toclevel <= toc) ? yes : no);
2522                 }
2523         }
2524
2525         numberingModule->tocTW->setUpdatesEnabled(true);
2526         numberingModule->tocTW->update();
2527 }
2528
2529
2530 void GuiDocument::updateDefaultFormat()
2531 {
2532         if (!bufferview())
2533                 return;
2534         // make a copy in order to consider unapplied changes
2535         BufferParams param_copy = buffer().params();
2536         param_copy.useNonTeXFonts = fontModule->osFontsCB->isChecked();
2537         int const idx = latexModule->classCO->currentIndex();
2538         if (idx >= 0) {
2539                 string const classname = fromqstr(latexModule->classCO->getData(idx));
2540                 param_copy.setBaseClass(classname);
2541                 param_copy.makeDocumentClass(true);
2542         }
2543         outputModule->defaultFormatCO->blockSignals(true);
2544         outputModule->defaultFormatCO->clear();
2545         outputModule->defaultFormatCO->addItem(qt_("Default"),
2546                                 QVariant(QString("default")));
2547         typedef vector<Format const *> Formats;
2548         Formats formats = param_copy.exportableFormats(true);
2549         sort(formats.begin(), formats.end(), Format::formatSorter);
2550         Formats::const_iterator cit = formats.begin();
2551         Formats::const_iterator end = formats.end();
2552         for (; cit != end; ++cit)
2553                 outputModule->defaultFormatCO->addItem(qt_((*cit)->prettyname()),
2554                                 QVariant(toqstr((*cit)->name())));
2555         outputModule->defaultFormatCO->blockSignals(false);
2556 }
2557
2558
2559 bool GuiDocument::isChildIncluded(string const & child)
2560 {
2561         if (includeonlys_.empty())
2562                 return false;
2563         return (std::find(includeonlys_.begin(),
2564                           includeonlys_.end(), child) != includeonlys_.end());
2565 }
2566
2567
2568 void GuiDocument::applyView()
2569 {
2570         // preamble
2571         preambleModule->apply(bp_);
2572         localLayout->apply(bp_);
2573
2574         // date
2575         bp_.suppress_date = latexModule->suppressDateCB->isChecked();
2576         bp_.use_refstyle  = latexModule->refstyleCB->isChecked();
2577
2578         // biblio
2579         if (biblioModule->citeNatbibRB->isChecked())
2580                 bp_.setCiteEngine("natbib");
2581         else if (biblioModule->citeJurabibRB->isChecked())
2582                 bp_.setCiteEngine("jurabib");
2583         if (biblioModule->citeDefaultRB->isChecked()) {
2584                 bp_.setCiteEngine("basic");
2585                 bp_.setCiteEngineType(ENGINE_TYPE_DEFAULT);
2586         }
2587         else
2588         if (biblioModule->citeStyleCO->currentIndex())
2589                 bp_.setCiteEngineType(ENGINE_TYPE_NUMERICAL);
2590         else
2591                 bp_.setCiteEngineType(ENGINE_TYPE_AUTHORYEAR);
2592
2593         bp_.use_bibtopic =
2594                 biblioModule->bibtopicCB->isChecked();
2595
2596         bp_.biblio_style = fromqstr(biblioModule->bibtexStyleLE->text());
2597
2598         string const bibtex_command =
2599                 fromqstr(biblioModule->bibtexCO->itemData(
2600                         biblioModule->bibtexCO->currentIndex()).toString());
2601         string const bibtex_options =
2602                 fromqstr(biblioModule->bibtexOptionsLE->text());
2603         if (bibtex_command == "default" || bibtex_options.empty())
2604                 bp_.bibtex_command = bibtex_command;
2605         else
2606                 bp_.bibtex_command = bibtex_command + " " + bibtex_options;
2607
2608         if (biblioChanged_) {
2609                 buffer().invalidateBibinfoCache();
2610                 buffer().removeBiblioTempFiles();
2611         }
2612
2613         // Indices
2614         indicesModule->apply(bp_);
2615
2616         // language & quotes
2617         if (langModule->defaultencodingRB->isChecked()) {
2618                 bp_.inputenc = "auto";
2619         } else {
2620                 int i = langModule->encodingCO->currentIndex();
2621                 if (i == 0)
2622                         bp_.inputenc = "default";
2623                 else {
2624                         QString const enc_gui =
2625                                 langModule->encodingCO->currentText();
2626                         Encodings::const_iterator it = encodings.begin();
2627                         Encodings::const_iterator const end = encodings.end();
2628                         bool found = false;
2629                         for (; it != end; ++it) {
2630                                 if (qt_(it->guiName()) == enc_gui &&
2631                                     !it->unsafe()) {
2632                                         bp_.inputenc = it->name();
2633                                         found = true;
2634                                         break;
2635                                 }
2636                         }
2637                         if (!found) {
2638                                 // should not happen
2639                                 lyxerr << "GuiDocument::apply: Unknown encoding! Resetting to default" << endl;
2640                                 bp_.inputenc = "default";
2641                         }
2642                 }
2643         }
2644
2645         bp_.quotes_language = (InsetQuotes::QuoteLanguage) langModule->quoteStyleCO->itemData(
2646                 langModule->quoteStyleCO->currentIndex()).toInt();
2647
2648         QString const langname = langModule->languageCO->itemData(
2649                 langModule->languageCO->currentIndex()).toString();
2650         Language const * newlang = lyx::languages.getLanguage(fromqstr(langname));
2651         Cursor & cur = const_cast<BufferView *>(bufferview())->cursor();
2652         // If current cursor language was the document language, then update it too.
2653         if (cur.current_font.language() == bp_.language) {
2654                 cur.current_font.setLanguage(newlang);
2655                 cur.real_current_font.setLanguage(newlang);
2656         }
2657         bp_.language = newlang;
2658
2659         QString const pack = langModule->languagePackageCO->itemData(
2660                 langModule->languagePackageCO->currentIndex()).toString();
2661         if (pack == "custom")
2662                 bp_.lang_package =
2663                         fromqstr(langModule->languagePackageLE->text());
2664         else
2665                 bp_.lang_package = fromqstr(pack);
2666
2667         //color
2668         bp_.backgroundcolor = set_backgroundcolor;
2669         bp_.isbackgroundcolor = is_backgroundcolor;
2670         bp_.fontcolor = set_fontcolor;
2671         bp_.isfontcolor = is_fontcolor;
2672         bp_.notefontcolor = set_notefontcolor;
2673         bp_.boxbgcolor = set_boxbgcolor;
2674
2675         // numbering
2676         if (bp_.documentClass().hasTocLevels()) {
2677                 bp_.tocdepth = numberingModule->tocSL->value();
2678                 bp_.secnumdepth = numberingModule->depthSL->value();
2679         }
2680
2681         // bullets
2682         bp_.user_defined_bullet(0) = bulletsModule->bullet(0);
2683         bp_.user_defined_bullet(1) = bulletsModule->bullet(1);
2684         bp_.user_defined_bullet(2) = bulletsModule->bullet(2);
2685         bp_.user_defined_bullet(3) = bulletsModule->bullet(3);
2686
2687         // packages
2688         bp_.graphics_driver =
2689                 tex_graphics[latexModule->psdriverCO->currentIndex()];
2690
2691         // text layout
2692         int idx = latexModule->classCO->currentIndex();
2693         if (idx >= 0) {
2694                 string const classname = fromqstr(latexModule->classCO->getData(idx));
2695                 bp_.setBaseClass(classname);
2696         }
2697
2698         // Modules
2699         modulesToParams(bp_);
2700
2701         // Math
2702         map<string, string> const & packages = BufferParams::auto_packages();
2703         for (map<string, string>::const_iterator it = packages.begin();
2704              it != packages.end(); ++it) {
2705                 QTableWidgetItem * item = mathsModule->packagesTW->findItems(toqstr(it->first), Qt::MatchExactly)[0];
2706                 if (!item)
2707                         continue;
2708                 int row = mathsModule->packagesTW->row(item);
2709                 QRadioButton * rb = (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 1);
2710                 if (rb->isChecked()) {
2711                         bp_.use_package(it->first, BufferParams::package_auto);
2712                         continue;
2713                 }
2714                 rb = (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 2);
2715                 if (rb->isChecked()) {
2716                         bp_.use_package(it->first, BufferParams::package_on);
2717                         continue;
2718                 }
2719                 rb = (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 3);
2720                 if (rb->isChecked())
2721                         bp_.use_package(it->first, BufferParams::package_off);
2722         }
2723
2724         // Page Layout
2725         if (pageLayoutModule->pagestyleCO->currentIndex() == 0)
2726                 bp_.pagestyle = "default";
2727         else {
2728                 QString style_gui = pageLayoutModule->pagestyleCO->currentText();
2729                 for (size_t i = 0; i != pagestyles.size(); ++i)
2730                         if (pagestyles[i].second == style_gui)
2731                                 bp_.pagestyle = pagestyles[i].first;
2732         }
2733
2734         // Text Layout
2735         switch (textLayoutModule->lspacingCO->currentIndex()) {
2736         case 0:
2737                 bp_.spacing().set(Spacing::Single);
2738                 break;
2739         case 1:
2740                 bp_.spacing().set(Spacing::Onehalf);
2741                 break;
2742         case 2:
2743                 bp_.spacing().set(Spacing::Double);
2744                 break;
2745         case 3: {
2746                 string s = widgetToDoubleStr(textLayoutModule->lspacingLE);
2747                 if (s.empty())
2748                         bp_.spacing().set(Spacing::Single);
2749                 else
2750                         bp_.spacing().set(Spacing::Other, s);
2751                 break;
2752                 }
2753         }
2754
2755         if (textLayoutModule->twoColumnCB->isChecked())
2756                 bp_.columns = 2;
2757         else
2758                 bp_.columns = 1;
2759
2760         bp_.justification = textLayoutModule->justCB->isChecked();
2761
2762         if (textLayoutModule->indentRB->isChecked()) {
2763                 // if paragraphs are separated by an indentation
2764                 bp_.paragraph_separation = BufferParams::ParagraphIndentSeparation;
2765                 switch (textLayoutModule->indentCO->currentIndex()) {
2766                 case 0:
2767                         bp_.setIndentation(HSpace(HSpace::DEFAULT));
2768                         break;
2769                 case 1: {
2770                         HSpace indent = HSpace(
2771                                 widgetsToLength(textLayoutModule->indentLE,
2772                                 textLayoutModule->indentLengthCO)
2773                                 );
2774                         bp_.setIndentation(indent);
2775                         break;
2776                         }
2777                 default:
2778                         // this should never happen
2779                         bp_.setIndentation(HSpace(HSpace::DEFAULT));
2780                         break;
2781                 }
2782         } else {
2783                 // if paragraphs are separated by a skip
2784                 bp_.paragraph_separation = BufferParams::ParagraphSkipSeparation;
2785                 switch (textLayoutModule->skipCO->currentIndex()) {
2786                 case 0:
2787                         bp_.setDefSkip(VSpace(VSpace::SMALLSKIP));
2788                         break;
2789                 case 1:
2790                         bp_.setDefSkip(VSpace(VSpace::MEDSKIP));
2791                         break;
2792                 case 2:
2793                         bp_.setDefSkip(VSpace(VSpace::BIGSKIP));
2794                         break;
2795                 case 3:
2796                         {
2797                         VSpace vs = VSpace(
2798                                 widgetsToLength(textLayoutModule->skipLE,
2799                                 textLayoutModule->skipLengthCO)
2800                                 );
2801                         bp_.setDefSkip(vs);
2802                         break;
2803                         }
2804                 default:
2805                         // this should never happen
2806                         bp_.setDefSkip(VSpace(VSpace::MEDSKIP));
2807                         break;
2808                 }
2809         }
2810
2811         bp_.options =
2812                 fromqstr(latexModule->optionsLE->text());
2813
2814         bp_.use_default_options =
2815                 latexModule->defaultOptionsCB->isChecked();
2816
2817         if (latexModule->childDocGB->isChecked())
2818                 bp_.master =
2819                         fromqstr(latexModule->childDocLE->text());
2820         else
2821                 bp_.master = string();
2822
2823         // Master/Child
2824         bp_.clearIncludedChildren();
2825         if (masterChildModule->includeonlyRB->isChecked()) {
2826                 list<string>::const_iterator it = includeonlys_.begin();
2827                 for (; it != includeonlys_.end() ; ++it) {
2828                         bp_.addIncludedChildren(*it);
2829                 }
2830         }
2831         bp_.maintain_unincluded_children =
2832                 masterChildModule->maintainAuxCB->isChecked();
2833
2834         // Float Placement
2835         bp_.float_placement = floatModule->get();
2836
2837         // Listings
2838         // text should have passed validation
2839         bp_.listings_params =
2840                 InsetListingsParams(fromqstr(listingsModule->listingsED->toPlainText())).params();
2841
2842         // output
2843         bp_.default_output_format = fromqstr(outputModule->defaultFormatCO->itemData(
2844                 outputModule->defaultFormatCO->currentIndex()).toString());
2845
2846         bool const nontexfonts = fontModule->osFontsCB->isChecked();
2847         bp_.useNonTeXFonts = nontexfonts;
2848
2849         bp_.output_sync = outputModule->outputsyncCB->isChecked();
2850
2851         bp_.output_sync_macro = fromqstr(outputModule->synccustomCB->currentText());
2852
2853         int mathfmt = outputModule->mathoutCB->currentIndex();
2854         if (mathfmt == -1)
2855                 mathfmt = 0;
2856         BufferParams::MathOutput const mo =
2857                 static_cast<BufferParams::MathOutput>(mathfmt);
2858         bp_.html_math_output = mo;
2859         bp_.html_be_strict = outputModule->strictCB->isChecked();
2860         bp_.html_css_as_file = outputModule->cssCB->isChecked();
2861         bp_.html_math_img_scale = outputModule->mathimgSB->value();
2862         bp_.display_pixel_ratio = theGuiApp()->pixelRatio();
2863
2864         // fonts
2865         bp_.fonts_roman[nontexfonts] =
2866                 fromqstr(fontModule->fontsRomanCO->
2867                         itemData(fontModule->fontsRomanCO->currentIndex()).toString());
2868         bp_.fonts_roman[!nontexfonts] = fromqstr(fontModule->font_roman);
2869
2870         bp_.fonts_sans[nontexfonts] =
2871                 fromqstr(fontModule->fontsSansCO->
2872                         itemData(fontModule->fontsSansCO->currentIndex()).toString());
2873         bp_.fonts_sans[!nontexfonts] = fromqstr(fontModule->font_sans);
2874
2875         bp_.fonts_typewriter[nontexfonts] =
2876                 fromqstr(fontModule->fontsTypewriterCO->
2877                         itemData(fontModule->fontsTypewriterCO->currentIndex()).toString());
2878         bp_.fonts_typewriter[!nontexfonts] = fromqstr(fontModule->font_typewriter);
2879
2880         bp_.fonts_math[nontexfonts] =
2881                 fromqstr(fontModule->fontsMathCO->
2882                         itemData(fontModule->fontsMathCO->currentIndex()).toString());
2883         bp_.fonts_math[!nontexfonts] = fromqstr(fontModule->font_math);
2884
2885         QString const fontenc =
2886                 fontModule->fontencCO->itemData(fontModule->fontencCO->currentIndex()).toString();
2887         if (fontenc == "custom")
2888                 bp_.fontenc = fromqstr(fontModule->fontencLE->text());
2889         else
2890                 bp_.fontenc = fromqstr(fontenc);
2891
2892         bp_.fonts_cjk =
2893                 fromqstr(fontModule->cjkFontLE->text());
2894
2895         bp_.use_microtype = fontModule->microtypeCB->isChecked();
2896
2897         bp_.fonts_sans_scale[nontexfonts] = fontModule->scaleSansSB->value();
2898         bp_.fonts_sans_scale[!nontexfonts] = fontModule->font_sf_scale;
2899
2900         bp_.fonts_typewriter_scale[nontexfonts] = fontModule->scaleTypewriterSB->value();
2901         bp_.fonts_typewriter_scale[!nontexfonts] = fontModule->font_tt_scale;
2902
2903         bp_.fonts_expert_sc = fontModule->fontScCB->isChecked();
2904
2905         bp_.fonts_old_figures = fontModule->fontOsfCB->isChecked();
2906
2907         if (nontexfonts)
2908                 bp_.fonts_default_family = "default";
2909         else
2910                 bp_.fonts_default_family = GuiDocument::fontfamilies[
2911                         fontModule->fontsDefaultCO->currentIndex()];
2912
2913         if (fontModule->fontsizeCO->currentIndex() == 0)
2914                 bp_.fontsize = "default";
2915         else
2916                 bp_.fontsize =
2917                         fromqstr(fontModule->fontsizeCO->currentText());
2918
2919         // paper
2920         bp_.papersize = PAPER_SIZE(
2921                 pageLayoutModule->papersizeCO->currentIndex());
2922
2923         bp_.paperwidth = widgetsToLength(pageLayoutModule->paperwidthLE,
2924                 pageLayoutModule->paperwidthUnitCO);
2925
2926         bp_.paperheight = widgetsToLength(pageLayoutModule->paperheightLE,
2927                 pageLayoutModule->paperheightUnitCO);
2928
2929         if (pageLayoutModule->facingPagesCB->isChecked())
2930                 bp_.sides = TwoSides;
2931         else
2932                 bp_.sides = OneSide;
2933
2934         if (pageLayoutModule->landscapeRB->isChecked())
2935                 bp_.orientation = ORIENTATION_LANDSCAPE;
2936         else
2937                 bp_.orientation = ORIENTATION_PORTRAIT;
2938
2939         // margins
2940         bp_.use_geometry = !marginsModule->marginCB->isChecked();
2941
2942         Ui::MarginsUi const * m = marginsModule;
2943
2944         bp_.leftmargin = widgetsToLength(m->innerLE, m->innerUnit);
2945         bp_.topmargin = widgetsToLength(m->topLE, m->topUnit);
2946         bp_.rightmargin = widgetsToLength(m->outerLE, m->outerUnit);
2947         bp_.bottommargin = widgetsToLength(m->bottomLE, m->bottomUnit);
2948         bp_.headheight = widgetsToLength(m->headheightLE, m->headheightUnit);
2949         bp_.headsep = widgetsToLength(m->headsepLE, m->headsepUnit);
2950         bp_.footskip = widgetsToLength(m->footskipLE, m->footskipUnit);
2951         bp_.columnsep = widgetsToLength(m->columnsepLE, m->columnsepUnit);
2952
2953         // branches
2954         branchesModule->apply(bp_);
2955
2956         // PDF support
2957         PDFOptions & pdf = bp_.pdfoptions();
2958         pdf.use_hyperref = pdfSupportModule->use_hyperrefGB->isChecked();
2959         pdf.title = fromqstr(pdfSupportModule->titleLE->text());
2960         pdf.author = fromqstr(pdfSupportModule->authorLE->text());
2961         pdf.subject = fromqstr(pdfSupportModule->subjectLE->text());
2962         pdf.keywords = fromqstr(pdfSupportModule->keywordsLE->text());
2963
2964         pdf.bookmarks = pdfSupportModule->bookmarksGB->isChecked();
2965         pdf.bookmarksnumbered = pdfSupportModule->bookmarksnumberedCB->isChecked();
2966         pdf.bookmarksopen = pdfSupportModule->bookmarksopenGB->isChecked();
2967         pdf.bookmarksopenlevel = pdfSupportModule->bookmarksopenlevelSB->value();
2968
2969         pdf.breaklinks = pdfSupportModule->breaklinksCB->isChecked();
2970         pdf.pdfborder = pdfSupportModule->pdfborderCB->isChecked();
2971         pdf.pdfusetitle = pdfSupportModule->pdfusetitleCB->isChecked();
2972         pdf.colorlinks = pdfSupportModule->colorlinksCB->isChecked();
2973         pdf.backref =
2974                 backref_opts[pdfSupportModule->backrefCO->currentIndex()];
2975         if (pdfSupportModule->fullscreenCB->isChecked())
2976                 pdf.pagemode = pdf.pagemode_fullscreen;
2977         else
2978                 pdf.pagemode.clear();
2979         pdf.quoted_options = pdf.quoted_options_check(
2980                                 fromqstr(pdfSupportModule->optionsLE->text()));
2981
2982         // reset tracker
2983         nonModuleChanged_ = false;
2984 }
2985
2986
2987 void GuiDocument::paramsToDialog()
2988 {
2989         // set the default unit
2990         Length::UNIT const default_unit = Length::defaultUnit();
2991
2992         // preamble
2993         preambleModule->update(bp_, id());
2994         localLayout->update(bp_, id());
2995
2996         // date
2997         latexModule->suppressDateCB->setChecked(bp_.suppress_date);
2998         latexModule->refstyleCB->setChecked(bp_.use_refstyle);
2999
3000         // biblio
3001         string const cite_engine = bp_.citeEngine().list().front();
3002
3003         biblioModule->citeDefaultRB->setChecked(
3004                 cite_engine == "basic");
3005
3006         biblioModule->citeJurabibRB->setChecked(
3007                 cite_engine == "jurabib");
3008
3009         biblioModule->citeNatbibRB->setChecked(
3010                 cite_engine == "natbib");
3011
3012         biblioModule->citeStyleCO->setCurrentIndex(
3013                 bp_.citeEngineType() & ENGINE_TYPE_NUMERICAL);
3014
3015         updateEngineType(documentClass().opt_enginetype(),
3016                 bp_.citeEngineType());
3017
3018         biblioModule->bibtopicCB->setChecked(
3019                 bp_.use_bibtopic);
3020
3021         biblioModule->bibtexStyleLE->setText(toqstr(bp_.biblio_style));
3022
3023         string command;
3024         string options =
3025                 split(bp_.bibtex_command, command, ' ');
3026
3027         int const bpos = biblioModule->bibtexCO->findData(toqstr(command));
3028         if (bpos != -1) {
3029                 biblioModule->bibtexCO->setCurrentIndex(bpos);
3030                 biblioModule->bibtexOptionsLE->setText(toqstr(options).trimmed());
3031         } else {
3032                 // We reset to default if we do not know the specified compiler
3033                 // This is for security reasons
3034                 biblioModule->bibtexCO->setCurrentIndex(
3035                         biblioModule->bibtexCO->findData(toqstr("default")));
3036                 biblioModule->bibtexOptionsLE->clear();
3037         }
3038         biblioModule->bibtexOptionsLE->setEnabled(
3039                 biblioModule->bibtexCO->currentIndex() != 0);
3040
3041         biblioChanged_ = false;
3042
3043         // indices
3044         // We may be called when there is no Buffer, e.g., when 
3045         // the last view has just been closed.
3046         bool const isReadOnly = isBufferAvailable() ? buffer().isReadonly() : false;
3047         indicesModule->update(bp_, isReadOnly);
3048
3049         // language & quotes
3050         int const pos = langModule->languageCO->findData(toqstr(
3051                 bp_.language->lang()));
3052         langModule->languageCO->setCurrentIndex(pos);
3053
3054         langModule->quoteStyleCO->setCurrentIndex(
3055                 bp_.quotes_language);
3056
3057         bool default_enc = true;
3058         if (bp_.inputenc != "auto") {
3059                 default_enc = false;
3060                 if (bp_.inputenc == "default") {
3061                         langModule->encodingCO->setCurrentIndex(0);
3062                 } else {
3063                         string enc_gui;
3064                         Encodings::const_iterator it = encodings.begin();
3065                         Encodings::const_iterator const end = encodings.end();
3066                         for (; it != end; ++it) {
3067                                 if (it->name() == bp_.inputenc &&
3068                                     !it->unsafe()) {
3069                                         enc_gui = it->guiName();
3070                                         break;
3071                                 }
3072                         }
3073                         int const i = langModule->encodingCO->findText(
3074                                         qt_(enc_gui));
3075                         if (i >= 0)
3076                                 langModule->encodingCO->setCurrentIndex(i);
3077                         else
3078                                 // unknown encoding. Set to default.
3079                                 default_enc = true;
3080                 }
3081         }
3082         langModule->defaultencodingRB->setChecked(default_enc);
3083         langModule->otherencodingRB->setChecked(!default_enc);
3084
3085         int const p = langModule->languagePackageCO->findData(toqstr(bp_.lang_package));
3086         if (p == -1) {
3087                 langModule->languagePackageCO->setCurrentIndex(
3088                           langModule->languagePackageCO->findData("custom"));
3089                 langModule->languagePackageLE->setText(toqstr(bp_.lang_package));
3090         } else {
3091                 langModule->languagePackageCO->setCurrentIndex(p);
3092                 langModule->languagePackageLE->clear();
3093         }
3094
3095         //color
3096         if (bp_.isfontcolor) {
3097                 colorModule->fontColorPB->setStyleSheet(
3098                         colorButtonStyleSheet(rgb2qcolor(bp_.fontcolor)));
3099         }
3100         set_fontcolor = bp_.fontcolor;
3101         is_fontcolor = bp_.isfontcolor;
3102
3103         colorModule->noteFontColorPB->setStyleSheet(
3104                 colorButtonStyleSheet(rgb2qcolor(bp_.notefontcolor)));
3105         set_notefontcolor = bp_.notefontcolor;
3106
3107         if (bp_.isbackgroundcolor) {
3108                 colorModule->backgroundPB->setStyleSheet(
3109                         colorButtonStyleSheet(rgb2qcolor(bp_.backgroundcolor)));
3110         }
3111         set_backgroundcolor = bp_.backgroundcolor;
3112         is_backgroundcolor = bp_.isbackgroundcolor;
3113
3114         colorModule->boxBackgroundPB->setStyleSheet(
3115                 colorButtonStyleSheet(rgb2qcolor(bp_.boxbgcolor)));
3116         set_boxbgcolor = bp_.boxbgcolor;
3117
3118         // numbering
3119         int const min_toclevel = documentClass().min_toclevel();
3120         int const max_toclevel = documentClass().max_toclevel();
3121         if (documentClass().hasTocLevels()) {
3122                 numberingModule->setEnabled(true);
3123                 numberingModule->depthSL->setMinimum(min_toclevel - 1);
3124                 numberingModule->depthSL->setMaximum(max_toclevel);
3125                 numberingModule->depthSL->setValue(bp_.secnumdepth);
3126                 numberingModule->tocSL->setMaximum(min_toclevel - 1);
3127                 numberingModule->tocSL->setMaximum(max_toclevel);
3128                 numberingModule->tocSL->setValue(bp_.tocdepth);
3129                 updateNumbering();
3130         } else {
3131                 numberingModule->setEnabled(false);
3132                 numberingModule->tocTW->clear();
3133         }
3134
3135         // bullets
3136         bulletsModule->setBullet(0, bp_.user_defined_bullet(0));
3137         bulletsModule->setBullet(1, bp_.user_defined_bullet(1));
3138         bulletsModule->setBullet(2, bp_.user_defined_bullet(2));
3139         bulletsModule->setBullet(3, bp_.user_defined_bullet(3));
3140         bulletsModule->init();
3141
3142         // packages
3143         int nitem = findToken(tex_graphics, bp_.graphics_driver);
3144         if (nitem >= 0)
3145                 latexModule->psdriverCO->setCurrentIndex(nitem);
3146         updateModuleInfo();
3147
3148         map<string, string> const & packages = BufferParams::auto_packages();
3149         for (map<string, string>::const_iterator it = packages.begin();
3150              it != packages.end(); ++it) {
3151                 QTableWidgetItem * item = mathsModule->packagesTW->findItems(toqstr(it->first), Qt::MatchExactly)[0];
3152                 if (!item)
3153                         continue;
3154                 int row = mathsModule->packagesTW->row(item);
3155                 switch (bp_.use_package(it->first)) {
3156                         case BufferParams::package_off: {
3157                                 QRadioButton * rb = (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 3);
3158                                 rb->setChecked(true);
3159                                 break;
3160                         }
3161                         case BufferParams::package_on: {
3162                                 QRadioButton * rb = (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 2);
3163                                 rb->setChecked(true);
3164                                 break;
3165                         }
3166                         case BufferParams::package_auto: {
3167                                 QRadioButton * rb = (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 1);
3168                                 rb->setChecked(true);
3169                                 break;
3170                         }
3171                 }
3172         }
3173
3174         switch (bp_.spacing().getSpace()) {
3175                 case Spacing::Other: nitem = 3; break;
3176                 case Spacing::Double: nitem = 2; break;
3177                 case Spacing::Onehalf: nitem = 1; break;
3178                 case Spacing::Default: case Spacing::Single: nitem = 0; break;
3179         }
3180
3181         // text layout
3182         string const & layoutID = bp_.baseClassID();
3183         setLayoutComboByIDString(layoutID);
3184
3185         updatePagestyle(documentClass().opt_pagestyle(),
3186                                  bp_.pagestyle);
3187
3188         textLayoutModule->lspacingCO->setCurrentIndex(nitem);
3189         if (bp_.spacing().getSpace() == Spacing::Other) {
3190                 doubleToWidget(textLayoutModule->lspacingLE,
3191                         bp_.spacing().getValueAsString());
3192         }
3193         setLSpacing(nitem);
3194
3195         if (bp_.paragraph_separation == BufferParams::ParagraphIndentSeparation) {
3196                 textLayoutModule->indentRB->setChecked(true);
3197                 string indentation = bp_.getIndentation().asLyXCommand();
3198                 int indent = 0;
3199                 if (indentation != "default") {
3200                         lengthToWidgets(textLayoutModule->indentLE,
3201                         textLayoutModule->indentLengthCO,
3202                         indentation, default_unit);
3203                         indent = 1;
3204                 }
3205                 textLayoutModule->indentCO->setCurrentIndex(indent);
3206                 setIndent(indent);
3207         } else {
3208                 textLayoutModule->skipRB->setChecked(true);
3209                 int skip = 0;
3210                 switch (bp_.getDefSkip().kind()) {
3211                 case VSpace::SMALLSKIP:
3212                         skip = 0;
3213                         break;
3214                 case VSpace::MEDSKIP:
3215                         skip = 1;
3216                         break;
3217                 case VSpace::BIGSKIP:
3218                         skip = 2;
3219                         break;
3220                 case VSpace::LENGTH:
3221                         {
3222                         skip = 3;
3223                         string const length = bp_.getDefSkip().asLyXCommand();
3224                         lengthToWidgets(textLayoutModule->skipLE,
3225                                 textLayoutModule->skipLengthCO,
3226                                 length, default_unit);
3227                         break;
3228                         }
3229                 default:
3230                         skip = 0;
3231                         break;
3232                 }
3233                 textLayoutModule->skipCO->setCurrentIndex(skip);
3234                 setSkip(skip);
3235         }
3236
3237         textLayoutModule->twoColumnCB->setChecked(
3238                 bp_.columns == 2);
3239         textLayoutModule->justCB->setChecked(bp_.justification);
3240
3241         if (!bp_.options.empty()) {
3242                 latexModule->optionsLE->setText(
3243                         toqstr(bp_.options));
3244         } else {
3245                 latexModule->optionsLE->setText(QString());
3246         }
3247
3248         // latex
3249         latexModule->defaultOptionsCB->setChecked(
3250                         bp_.use_default_options);
3251         updateSelectedModules();
3252         selectionManager->updateProvidedModules(
3253                         bp_.baseClass()->providedModules());
3254         selectionManager->updateExcludedModules(
3255                         bp_.baseClass()->excludedModules());
3256
3257         if (!documentClass().options().empty()) {
3258                 latexModule->defaultOptionsLE->setText(
3259                         toqstr(documentClass().options()));
3260         } else {
3261                 latexModule->defaultOptionsLE->setText(
3262                         toqstr(_("[No options predefined]")));
3263         }
3264
3265         latexModule->defaultOptionsLE->setEnabled(
3266                 bp_.use_default_options
3267                 && !documentClass().options().empty());
3268
3269         latexModule->defaultOptionsCB->setEnabled(
3270                 !documentClass().options().empty());
3271
3272         if (!bp_.master.empty()) {
3273                 latexModule->childDocGB->setChecked(true);
3274                 latexModule->childDocLE->setText(
3275                         toqstr(bp_.master));
3276         } else {
3277                 latexModule->childDocLE->setText(QString());
3278                 latexModule->childDocGB->setChecked(false);
3279         }
3280
3281         // Master/Child
3282         if (!bufferview() || !buffer().hasChildren()) {
3283                 masterChildModule->childrenTW->clear();
3284                 includeonlys_.clear();
3285                 docPS->showPanel("Child Documents", false);
3286                 if (docPS->isCurrentPanel("Child Documents"))
3287                         docPS->setCurrentPanel("Document Class");
3288         } else {
3289                 docPS->showPanel("Child Documents", true);
3290                 masterChildModule->setEnabled(true);
3291                 includeonlys_ = bp_.getIncludedChildren();
3292                 updateIncludeonlys();
3293         }
3294         masterChildModule->maintainAuxCB->setChecked(
3295                 bp_.maintain_unincluded_children);
3296
3297         // Float Settings
3298         floatModule->set(bp_.float_placement);
3299
3300         // ListingsSettings
3301         // break listings_params to multiple lines
3302         string lstparams =
3303                 InsetListingsParams(bp_.listings_params).separatedParams();
3304         listingsModule->listingsED->setPlainText(toqstr(lstparams));
3305
3306         // Fonts
3307         // some languages only work with polyglossia/XeTeX
3308         Language const * lang = lyx::languages.getLanguage(
3309                 fromqstr(langModule->languageCO->itemData(
3310                         langModule->languageCO->currentIndex()).toString()));
3311         bool const need_fontspec =
3312                 lang->babel().empty() && !lang->polyglossia().empty();
3313         bool const os_fonts_available =
3314                 bp_.baseClass()->outputType() == lyx::LATEX
3315                 && LaTeXFeatures::isAvailable("fontspec");
3316         fontModule->osFontsCB->setEnabled(os_fonts_available && !need_fontspec);
3317         fontModule->osFontsCB->setChecked(
3318                 (os_fonts_available && bp_.useNonTeXFonts) || need_fontspec);
3319         updateFontsize(documentClass().opt_fontsize(),
3320                         bp_.fontsize);
3321
3322         QString font = toqstr(bp_.fontsRoman());
3323         int rpos = fontModule->fontsRomanCO->findData(font);
3324         if (rpos == -1) {
3325                 rpos = fontModule->fontsRomanCO->count();
3326                 fontModule->fontsRomanCO->addItem(font + qt_(" (not installed)"), font);
3327         }
3328         fontModule->fontsRomanCO->setCurrentIndex(rpos);
3329         fontModule->font_roman = toqstr(bp_.fonts_roman[!bp_.useNonTeXFonts]);
3330
3331         font = toqstr(bp_.fontsSans());
3332         int spos = fontModule->fontsSansCO->findData(font);
3333         if (spos == -1) {
3334                 spos = fontModule->fontsSansCO->count();
3335                 fontModule->fontsSansCO->addItem(font + qt_(" (not installed)"), font);
3336         }
3337         fontModule->fontsSansCO->setCurrentIndex(spos);
3338         fontModule->font_sans = toqstr(bp_.fonts_sans[!bp_.useNonTeXFonts]);
3339
3340         font = toqstr(bp_.fontsTypewriter());
3341         int tpos = fontModule->fontsTypewriterCO->findData(font);
3342         if (tpos == -1) {
3343                 tpos = fontModule->fontsTypewriterCO->count();
3344                 fontModule->fontsTypewriterCO->addItem(font + qt_(" (not installed)"), font);
3345         }
3346         fontModule->fontsTypewriterCO->setCurrentIndex(tpos);
3347         fontModule->font_typewriter = toqstr(bp_.fonts_typewriter[!bp_.useNonTeXFonts]);
3348
3349         font = toqstr(bp_.fontsMath());
3350         int mpos = fontModule->fontsMathCO->findData(font);
3351         if (mpos == -1) {
3352                 mpos = fontModule->fontsMathCO->count();
3353                 fontModule->fontsMathCO->addItem(font + qt_(" (not installed)"), font);
3354         }
3355         fontModule->fontsMathCO->setCurrentIndex(mpos);
3356         fontModule->font_math = toqstr(bp_.fonts_math[!bp_.useNonTeXFonts]);
3357
3358         if (bp_.useNonTeXFonts && os_fonts_available) {
3359                 fontModule->fontencLA->setEnabled(false);
3360                 fontModule->fontencCO->setEnabled(false);
3361                 fontModule->fontencLE->setEnabled(false);
3362         } else {
3363                 fontModule->fontencLA->setEnabled(true);
3364                 fontModule->fontencCO->setEnabled(true);
3365                 fontModule->fontencLE->setEnabled(true);
3366                 romanChanged(rpos);
3367                 sansChanged(spos);
3368                 ttChanged(tpos);
3369         }
3370
3371         if (!bp_.fonts_cjk.empty())
3372                 fontModule->cjkFontLE->setText(
3373                         toqstr(bp_.fonts_cjk));
3374         else
3375                 fontModule->cjkFontLE->setText(QString());
3376         
3377         fontModule->microtypeCB->setChecked(bp_.use_microtype);
3378
3379         fontModule->fontScCB->setChecked(bp_.fonts_expert_sc);
3380         fontModule->fontOsfCB->setChecked(bp_.fonts_old_figures);
3381         fontModule->scaleSansSB->setValue(bp_.fontsSansScale());
3382         fontModule->font_sf_scale = bp_.fonts_sans_scale[!bp_.useNonTeXFonts];
3383         fontModule->scaleTypewriterSB->setValue(bp_.fontsTypewriterScale());
3384         fontModule->font_tt_scale = bp_.fonts_typewriter_scale[!bp_.useNonTeXFonts];
3385
3386         int nn = findToken(GuiDocument::fontfamilies, bp_.fonts_default_family);
3387         if (nn >= 0)
3388                 fontModule->fontsDefaultCO->setCurrentIndex(nn);
3389
3390         if (bp_.fontenc == "global" || bp_.fontenc == "default") {
3391                 fontModule->fontencCO->setCurrentIndex(
3392                         fontModule->fontencCO->findData(toqstr(bp_.fontenc)));
3393                 fontModule->fontencLE->setEnabled(false);
3394         } else {
3395                 fontModule->fontencCO->setCurrentIndex(1);
3396                 fontModule->fontencLE->setText(toqstr(bp_.fontenc));
3397         }
3398
3399         // Output
3400         // This must be set _after_ fonts since updateDefaultFormat()
3401         // checks osFontsCB settings.
3402         // update combobox with formats
3403         updateDefaultFormat();
3404         int index = outputModule->defaultFormatCO->findData(toqstr(
3405                 bp_.default_output_format));
3406         // set to default if format is not found
3407         if (index == -1)
3408                 index = 0;
3409         outputModule->defaultFormatCO->setCurrentIndex(index);
3410
3411         outputModule->outputsyncCB->setChecked(bp_.output_sync);
3412         outputModule->synccustomCB->setEditText(toqstr(bp_.output_sync_macro));
3413
3414         outputModule->mathimgSB->setValue(bp_.html_math_img_scale);
3415         outputModule->mathoutCB->setCurrentIndex(bp_.html_math_output);
3416         outputModule->strictCB->setChecked(bp_.html_be_strict);
3417         outputModule->cssCB->setChecked(bp_.html_css_as_file);
3418
3419         // paper
3420         bool const extern_geometry =
3421                 documentClass().provides("geometry");
3422         int const psize = bp_.papersize;
3423         pageLayoutModule->papersizeCO->setCurrentIndex(psize);
3424         setCustomPapersize(!extern_geometry && psize == 1);
3425         pageLayoutModule->papersizeCO->setEnabled(!extern_geometry);
3426
3427         bool const landscape =
3428                 bp_.orientation == ORIENTATION_LANDSCAPE;
3429         pageLayoutModule->landscapeRB->setChecked(landscape);
3430         pageLayoutModule->portraitRB->setChecked(!landscape);
3431         pageLayoutModule->landscapeRB->setEnabled(!extern_geometry);
3432         pageLayoutModule->portraitRB->setEnabled(!extern_geometry);
3433
3434         pageLayoutModule->facingPagesCB->setChecked(
3435                 bp_.sides == TwoSides);
3436
3437         lengthToWidgets(pageLayoutModule->paperwidthLE,
3438                 pageLayoutModule->paperwidthUnitCO, bp_.paperwidth, default_unit);
3439         lengthToWidgets(pageLayoutModule->paperheightLE,
3440                 pageLayoutModule->paperheightUnitCO, bp_.paperheight, default_unit);
3441
3442         // margins
3443         Ui::MarginsUi * m = marginsModule;
3444
3445         setMargins();
3446
3447         lengthToWidgets(m->topLE, m->topUnit,
3448                 bp_.topmargin, default_unit);
3449
3450         lengthToWidgets(m->bottomLE, m->bottomUnit,
3451                 bp_.bottommargin, default_unit);
3452
3453         lengthToWidgets(m->innerLE, m->innerUnit,
3454                 bp_.leftmargin, default_unit);
3455
3456         lengthToWidgets(m->outerLE, m->outerUnit,
3457                 bp_.rightmargin, default_unit);
3458
3459         lengthToWidgets(m->headheightLE, m->headheightUnit,
3460                 bp_.headheight, default_unit);
3461
3462         lengthToWidgets(m->headsepLE, m->headsepUnit,
3463                 bp_.headsep, default_unit);
3464
3465         lengthToWidgets(m->footskipLE, m->footskipUnit,
3466                 bp_.footskip, default_unit);
3467
3468         lengthToWidgets(m->columnsepLE, m->columnsepUnit,
3469                 bp_.columnsep, default_unit);
3470
3471         // branches
3472         updateUnknownBranches();
3473         branchesModule->update(bp_);
3474
3475         // PDF support
3476         PDFOptions const & pdf = bp_.pdfoptions();
3477         pdfSupportModule->use_hyperrefGB->setChecked(pdf.use_hyperref);
3478         if (bp_.documentClass().provides("hyperref"))
3479                 pdfSupportModule->use_hyperrefGB->setTitle(qt_("C&ustomize Hyperref Options"));
3480         else
3481                 pdfSupportModule->use_hyperrefGB->setTitle(qt_("&Use Hyperref Support"));
3482         pdfSupportModule->titleLE->setText(toqstr(pdf.title));
3483         pdfSupportModule->authorLE->setText(toqstr(pdf.author));
3484         pdfSupportModule->subjectLE->setText(toqstr(pdf.subject));
3485         pdfSupportModule->keywordsLE->setText(toqstr(pdf.keywords));
3486
3487         pdfSupportModule->bookmarksGB->setChecked(pdf.bookmarks);
3488         pdfSupportModule->bookmarksnumberedCB->setChecked(pdf.bookmarksnumbered);
3489         pdfSupportModule->bookmarksopenGB->setChecked(pdf.bookmarksopen);
3490
3491         pdfSupportModule->bookmarksopenlevelSB->setValue(pdf.bookmarksopenlevel);
3492
3493         pdfSupportModule->breaklinksCB->setChecked(pdf.breaklinks);
3494         pdfSupportModule->pdfborderCB->setChecked(pdf.pdfborder);
3495         pdfSupportModule->pdfusetitleCB->setChecked(pdf.pdfusetitle);
3496         pdfSupportModule->colorlinksCB->setChecked(pdf.colorlinks);
3497
3498         nn = findToken(backref_opts, pdf.backref);
3499         if (nn >= 0)
3500                 pdfSupportModule->backrefCO->setCurrentIndex(nn);
3501
3502         pdfSupportModule->fullscreenCB->setChecked
3503                 (pdf.pagemode == pdf.pagemode_fullscreen);
3504
3505         pdfSupportModule->optionsLE->setText(
3506                 toqstr(pdf.quoted_options));
3507
3508         // Make sure that the bc is in the INITIAL state
3509         if (bc().policy().buttonStatus(ButtonPolicy::RESTORE))
3510                 bc().restore();
3511
3512         // clear changed branches cache
3513         changedBranches_.clear();
3514
3515         // reset tracker
3516         nonModuleChanged_ = false;
3517 }
3518
3519
3520 void GuiDocument::saveDocDefault()
3521 {
3522         // we have to apply the params first
3523         applyView();
3524         saveAsDefault();
3525 }
3526
3527
3528 void GuiDocument::updateAvailableModules()
3529 {
3530         modules_av_model_.clear();
3531         list<modInfoStruct> modInfoList = getModuleInfo();
3532         // Sort names according to the locale
3533         modInfoList.sort([](modInfoStruct const & a, modInfoStruct const & b) {
3534                         return 0 < b.name.localeAwareCompare(a.name);
3535                 });
3536         int i = 0;
3537         for (modInfoStruct const & m : modInfoList) {
3538                 modules_av_model_.insertRow(i, m.name, m.id, m.description);
3539                 ++i;
3540         }
3541 }
3542
3543
3544 void GuiDocument::updateSelectedModules()
3545 {
3546         modules_sel_model_.clear();
3547         list<modInfoStruct> const selModList = getSelectedModules();
3548         int i = 0;
3549         for (modInfoStruct const & m : selModList) {
3550                 modules_sel_model_.insertRow(i, m.name, m.id, m.description);
3551                 ++i;
3552         }
3553 }
3554
3555
3556 void GuiDocument::updateIncludeonlys()
3557 {
3558         masterChildModule->childrenTW->clear();
3559         QString const no = qt_("No");
3560         QString const yes = qt_("Yes");
3561
3562         if (includeonlys_.empty()) {
3563                 masterChildModule->includeallRB->setChecked(true);
3564                 masterChildModule->childrenTW->setEnabled(false);
3565                 masterChildModule->maintainAuxCB->setEnabled(false);
3566         } else {
3567                 masterChildModule->includeonlyRB->setChecked(true);
3568                 masterChildModule->childrenTW->setEnabled(true);
3569                 masterChildModule->maintainAuxCB->setEnabled(true);
3570         }
3571         ListOfBuffers children = buffer().getChildren();
3572         ListOfBuffers::const_iterator it  = children.begin();
3573         ListOfBuffers::const_iterator end = children.end();
3574         bool has_unincluded = false;
3575         bool all_unincluded = true;
3576         for (; it != end; ++it) {
3577                 QTreeWidgetItem * item = new QTreeWidgetItem(masterChildModule->childrenTW);
3578                 // FIXME Unicode
3579                 string const name =
3580                         to_utf8(makeRelPath(from_utf8((*it)->fileName().absFileName()),
3581                                                         from_utf8(buffer().filePath())));
3582                 item->setText(0, toqstr(name));
3583                 item->setText(1, isChildIncluded(name) ? yes : no);
3584                 if (!isChildIncluded(name))
3585                         has_unincluded = true;
3586                 else
3587                         all_unincluded = false;
3588         }
3589         // Both if all childs are included and if none is included
3590         // is equal to "include all" (i.e., ommit \includeonly).
3591         // Thus, reset the GUI.
3592         if (!has_unincluded || all_unincluded) {
3593                 masterChildModule->includeallRB->setChecked(true);
3594                 masterChildModule->childrenTW->setEnabled(false);
3595                 includeonlys_.clear();
3596         }
3597         // If all are included, we need to update again.
3598         if (!has_unincluded)
3599                 updateIncludeonlys();
3600 }
3601
3602
3603 void GuiDocument::updateContents()
3604 {
3605         // Nothing to do here as the document settings is not cursor dependant.
3606         return;
3607 }
3608
3609
3610 void GuiDocument::useClassDefaults()
3611 {
3612         if (applyPB->isEnabled()) {
3613                 int const ret = Alert::prompt(_("Unapplied changes"),
3614                                 _("Some changes in the dialog were not yet applied.\n"
3615                                   "If you do not apply now, they will be lost after this action."),
3616                                 1, 1, _("&Apply"), _("&Dismiss"));
3617                 if (ret == 0)
3618                         applyView();
3619         }
3620
3621         int idx = latexModule->classCO->currentIndex();
3622         string const classname = fromqstr(latexModule->classCO->getData(idx));
3623         if (!bp_.setBaseClass(classname)) {
3624                 Alert::error(_("Error"), _("Unable to set document class."));
3625                 return;
3626         }
3627         bp_.useClassDefaults();
3628         paramsToDialog();
3629 }
3630
3631
3632 void GuiDocument::setLayoutComboByIDString(string const & idString)
3633 {
3634         if (!latexModule->classCO->set(toqstr(idString)))
3635                 Alert::warning(_("Can't set layout!"),
3636                         bformat(_("Unable to set layout for ID: %1$s"), from_utf8(idString)));
3637 }
3638
3639
3640 bool GuiDocument::isValid()
3641 {
3642         return
3643                 validateListingsParameters().isEmpty() &&
3644                 localLayout->isValid() &&
3645                 (
3646                         // if we're asking for skips between paragraphs
3647                         !textLayoutModule->skipRB->isChecked() ||
3648                         // then either we haven't chosen custom
3649                         textLayoutModule->skipCO->currentIndex() != 3 ||
3650                         // or else a length has been given
3651                         !textLayoutModule->skipLE->text().isEmpty()
3652                 ) &&
3653                 (
3654                         // if we're asking for indentation
3655                         !textLayoutModule->indentRB->isChecked() ||
3656                         // then either we haven't chosen custom
3657                         textLayoutModule->indentCO->currentIndex() != 1 ||
3658                         // or else a length has been given
3659                         !textLayoutModule->indentLE->text().isEmpty()
3660                 );
3661 }
3662
3663
3664 char const * const GuiDocument::fontfamilies[5] = {
3665         "default", "rmdefault", "sfdefault", "ttdefault", ""
3666 };
3667
3668
3669 char const * GuiDocument::fontfamilies_gui[5] = {
3670         N_("Default"), N_("Roman"), N_("Sans Serif"), N_("Typewriter"), ""
3671 };
3672
3673
3674 bool GuiDocument::initialiseParams(string const &)
3675 {
3676         BufferView const * view = bufferview();
3677         if (!view) {
3678                 bp_ = BufferParams();
3679                 paramsToDialog();
3680                 return true;
3681         }
3682         bp_ = view->buffer().params();
3683         loadModuleInfo();
3684         updateAvailableModules();
3685         //FIXME It'd be nice to make sure here that the selected
3686         //modules are consistent: That required modules are actually
3687         //selected, and that we don't have conflicts. If so, we could
3688         //at least pop up a warning.
3689         paramsToDialog();
3690         return true;
3691 }
3692
3693
3694 void GuiDocument::clearParams()
3695 {
3696         bp_ = BufferParams();
3697 }
3698
3699
3700 BufferId GuiDocument::id() const
3701 {
3702         BufferView const * const view = bufferview();
3703         return view? &view->buffer() : 0;
3704 }
3705
3706
3707 list<GuiDocument::modInfoStruct> const & GuiDocument::getModuleInfo()
3708 {
3709         return moduleNames_;
3710 }
3711
3712
3713 list<GuiDocument::modInfoStruct> const
3714 GuiDocument::makeModuleInfo(LayoutModuleList const & mods)
3715 {
3716         list<modInfoStruct> mInfo;
3717         for (string const & name : mods) {
3718                 modInfoStruct m;
3719                 LyXModule const * const mod = theModuleList[name];
3720                 if (mod)
3721                         m = modInfo(*mod);
3722                 else {
3723                         m.id = name;
3724                         m.name = toqstr(name + " (") + qt_("Not Found") + toqstr(")");
3725                 }
3726                 mInfo.push_back(m);
3727         }
3728         return mInfo;
3729 }
3730
3731
3732 list<GuiDocument::modInfoStruct> const GuiDocument::getSelectedModules()
3733 {
3734         return makeModuleInfo(params().getModules());
3735 }
3736
3737
3738 list<GuiDocument::modInfoStruct> const GuiDocument::getProvidedModules()
3739 {
3740         return makeModuleInfo(params().baseClass()->providedModules());
3741 }
3742
3743
3744 DocumentClass const & GuiDocument::documentClass() const
3745 {
3746         return bp_.documentClass();
3747 }
3748
3749
3750 static void dispatch_bufferparams(Dialog const & dialog,
3751         BufferParams const & bp, FuncCode lfun, Buffer const * buf)
3752 {
3753         ostringstream ss;
3754         ss << "\\begin_header\n";
3755         bp.writeFile(ss, buf);
3756         ss << "\\end_header\n";
3757         dialog.dispatch(FuncRequest(lfun, ss.str()));
3758 }
3759
3760
3761 void GuiDocument::dispatchParams()
3762 {
3763         // We need a non-const buffer object.
3764         Buffer & buf = const_cast<BufferView *>(bufferview())->buffer();
3765         // There may be several undo records; group them (bug #8998)
3766         buf.undo().beginUndoGroup();
3767
3768         // This must come first so that a language change is correctly noticed
3769         setLanguage();
3770
3771         // Apply the BufferParams. Note that this will set the base class
3772         // and then update the buffer's layout.
3773         dispatch_bufferparams(*this, params(), LFUN_BUFFER_PARAMS_APPLY, &buffer());
3774
3775         if (!params().master.empty()) {
3776                 FileName const master_file = support::makeAbsPath(params().master,
3777                            support::onlyPath(buffer().absFileName()));
3778                 if (isLyXFileName(master_file.absFileName())) {
3779                         Buffer * master = checkAndLoadLyXFile(master_file);
3780                         if (master) {
3781                                 if (master->isChild(const_cast<Buffer *>(&buffer())))
3782                                         const_cast<Buffer &>(buffer()).setParent(master);
3783                                 else
3784                                         Alert::warning(_("Assigned master does not include this file"),
3785                                                 bformat(_("You must include this file in the document\n"
3786                                                           "'%1$s' in order to use the master document\n"
3787                                                           "feature."), from_utf8(params().master)));
3788                         } else
3789                                 Alert::warning(_("Could not load master"),
3790                                                 bformat(_("The master document '%1$s'\n"
3791                                                            "could not be loaded."),
3792                                                            from_utf8(params().master)));
3793                 }
3794         }
3795
3796         // Generate the colours requested by each new branch.
3797         BranchList & branchlist = params().branchlist();
3798         if (!branchlist.empty()) {
3799                 BranchList::const_iterator it = branchlist.begin();
3800                 BranchList::const_iterator const end = branchlist.end();
3801                 for (; it != end; ++it) {
3802                         docstring const & current_branch = it->branch();
3803                         Branch const * branch = branchlist.find(current_branch);
3804                         string const x11hexname = X11hexname(branch->color());
3805                         // display the new color
3806                         docstring const str = current_branch + ' ' + from_ascii(x11hexname);
3807                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
3808                 }
3809
3810                 // Open insets of selected branches, close deselected ones
3811                 dispatch(FuncRequest(LFUN_INSET_FORALL,
3812                         "Branch inset-toggle assign"));
3813         }
3814         // rename branches in the document
3815         executeBranchRenaming();
3816         // and clear changed branches cache
3817         changedBranches_.clear();
3818
3819         // Generate the colours requested by indices.
3820         IndicesList & indiceslist = params().indiceslist();
3821         if (!indiceslist.empty()) {
3822                 IndicesList::const_iterator it = indiceslist.begin();
3823                 IndicesList::const_iterator const end = indiceslist.end();
3824                 for (; it != end; ++it) {
3825                         docstring const & current_index = it->shortcut();
3826                         Index const * index = indiceslist.findShortcut(current_index);
3827                         string const x11hexname = X11hexname(index->color());
3828                         // display the new color
3829                         docstring const str = current_index + ' ' + from_ascii(x11hexname);
3830                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
3831                 }
3832         }
3833         // FIXME LFUN
3834         // If we used an LFUN, we would not need these two lines:
3835         BufferView * bv = const_cast<BufferView *>(bufferview());
3836         bv->processUpdateFlags(Update::Force | Update::FitCursor);
3837
3838         // Don't forget to close the group. Note that it is important
3839         // to check that there is no early return in the method.
3840         buf.undo().endUndoGroup();
3841 }
3842
3843
3844 void GuiDocument::setLanguage() const
3845 {
3846         Language const * const newL = bp_.language;
3847         if (buffer().params().language == newL)
3848                 return;
3849
3850         string const & lang_name = newL->lang();
3851         dispatch(FuncRequest(LFUN_BUFFER_LANGUAGE, lang_name));
3852 }
3853
3854
3855 void GuiDocument::saveAsDefault() const
3856 {
3857         dispatch_bufferparams(*this, params(), LFUN_BUFFER_SAVE_AS_DEFAULT, &buffer());
3858 }
3859
3860
3861 bool GuiDocument::providesOSF(QString const & font) const
3862 {
3863         if (fontModule->osFontsCB->isChecked())
3864                 // FIXME: we should check if the fonts really
3865                 // have OSF support. But how?
3866                 return true;
3867         return theLaTeXFonts().getLaTeXFont(
3868                                 qstring_to_ucs4(font)).providesOSF(ot1(),
3869                                                                    completeFontset(),
3870                                                                    noMathFont());
3871 }
3872
3873
3874 bool GuiDocument::providesSC(QString const & font) const
3875 {
3876         if (fontModule->osFontsCB->isChecked())
3877                 return false;
3878         return theLaTeXFonts().getLaTeXFont(
3879                                 qstring_to_ucs4(font)).providesSC(ot1(),
3880                                                                   completeFontset(),
3881                                                                   noMathFont());
3882 }
3883
3884
3885 bool GuiDocument::providesScale(QString const & font) const
3886 {
3887         if (fontModule->osFontsCB->isChecked())
3888                 return true;
3889         return theLaTeXFonts().getLaTeXFont(
3890                                 qstring_to_ucs4(font)).providesScale(ot1(),
3891                                                                      completeFontset(),
3892                                                                      noMathFont());
3893 }
3894
3895
3896 bool GuiDocument::providesNoMath(QString const & font) const
3897 {
3898         if (fontModule->osFontsCB->isChecked())
3899                 return false;
3900         return theLaTeXFonts().getLaTeXFont(
3901                                 qstring_to_ucs4(font)).providesNoMath(ot1(),
3902                                                                       completeFontset());
3903 }
3904
3905
3906 bool GuiDocument::hasMonolithicExpertSet(QString const & font) const
3907 {
3908         if (fontModule->osFontsCB->isChecked())
3909                 return false;
3910         return theLaTeXFonts().getLaTeXFont(
3911                                 qstring_to_ucs4(font)).hasMonolithicExpertSet(ot1(),
3912                                                                               completeFontset(),
3913                                                                               noMathFont());
3914 }
3915
3916
3917 //static
3918 GuiDocument::modInfoStruct GuiDocument::modInfo(LyXModule const & mod)
3919 {
3920         // FIXME Unicode: docstrings would be better for these parameters but this
3921         // change requires a lot of others
3922         modInfoStruct m;
3923         m.id = mod.getID();
3924         m.name = toqstr(translateIfPossible(from_utf8(mod.getName())));
3925         QString desc = toqstr(translateIfPossible(from_utf8(mod.getDescription())));
3926         // Find the first sentence of the description
3927         QTextBoundaryFinder bf(QTextBoundaryFinder::Sentence, desc);
3928         int pos = bf.toNextBoundary();
3929         if (pos > 0)
3930                 desc.truncate(pos);
3931         QString modulename = QString(qt_("(Module name: %1)")).arg(toqstr(m.id));
3932         // Tooltip is the desc followed by the module name
3933         m.description = QString("%1<i>%2</i>")
3934                 .arg(desc.isEmpty() ? QString() : QString("<p>%1</p>").arg(desc),
3935                      modulename);
3936         return m;
3937 }
3938
3939
3940 void GuiDocument::loadModuleInfo()
3941 {
3942         moduleNames_.clear();
3943         for (LyXModule const & mod : theModuleList)
3944                 if (mod.category().substr(0, 8) != "Citation")
3945                         moduleNames_.push_back(modInfo(mod));
3946 }
3947
3948
3949 void GuiDocument::updateUnknownBranches()
3950 {
3951         if (!bufferview())
3952                 return;
3953         list<docstring> used_branches;
3954         buffer().getUsedBranches(used_branches);
3955         list<docstring>::const_iterator it = used_branches.begin();
3956         QStringList unknown_branches;
3957         for (; it != used_branches.end() ; ++it) {
3958                 if (!buffer().params().branchlist().find(*it))
3959                         unknown_branches.append(toqstr(*it));
3960         }
3961         branchesModule->setUnknownBranches(unknown_branches);
3962 }
3963
3964
3965 void GuiDocument::branchesRename(docstring const & oldname, docstring const & newname)
3966 {
3967         map<docstring, docstring>::iterator it = changedBranches_.begin();
3968         for (; it != changedBranches_.end() ; ++it) {
3969                 if (it->second == oldname) {
3970                         // branch has already been renamed
3971                         it->second = newname;
3972                         return;
3973                 }
3974         }
3975         // store new name
3976         changedBranches_[oldname] = newname;
3977 }
3978
3979
3980 void GuiDocument::executeBranchRenaming() const
3981 {
3982         map<docstring, docstring>::const_iterator it = changedBranches_.begin();
3983         for (; it != changedBranches_.end() ; ++it) {
3984                 docstring const arg = '"' + it->first + '"' + " " + '"' + it->second + '"';
3985                 dispatch(FuncRequest(LFUN_BRANCHES_RENAME, arg));
3986         }
3987 }
3988
3989
3990 void GuiDocument::allPackagesAuto()
3991 {
3992         allPackages(1);
3993 }
3994
3995
3996 void GuiDocument::allPackagesAlways()
3997 {
3998         allPackages(2);
3999 }
4000
4001
4002 void GuiDocument::allPackagesNot()
4003 {
4004         allPackages(3);
4005 }
4006
4007
4008 void GuiDocument::allPackages(int col)
4009 {
4010         for (int row = 0; row < mathsModule->packagesTW->rowCount(); ++row) {
4011                 QRadioButton * rb = (QRadioButton*)mathsModule->packagesTW->cellWidget(row, col);
4012                 rb->setChecked(true);
4013         }
4014 }
4015
4016
4017 Dialog * createGuiDocument(GuiView & lv) { return new GuiDocument(lv); }
4018
4019
4020 } // namespace frontend
4021 } // namespace lyx
4022
4023 #include "moc_GuiDocument.cpp"