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