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