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