]> git.lyx.org Git - lyx.git/blob - src/frontends/qt/GuiDocument.cpp
Fix display of disabled page margins (#12887)
[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(toggled(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 }
2193
2194
2195 void GuiDocument::papersizeChanged(int paper_size)
2196 {
2197         setCustomPapersize(paper_size == 1);
2198 }
2199
2200
2201 void GuiDocument::setCustomPapersize(bool custom)
2202 {
2203         pageLayoutModule->paperwidthL->setEnabled(custom);
2204         pageLayoutModule->paperwidthLE->setEnabled(custom);
2205         pageLayoutModule->paperwidthUnitCO->setEnabled(custom);
2206         pageLayoutModule->paperheightL->setEnabled(custom);
2207         pageLayoutModule->paperheightLE->setEnabled(custom);
2208         pageLayoutModule->paperheightLE->setFocus();
2209         pageLayoutModule->paperheightUnitCO->setEnabled(custom);
2210 }
2211
2212
2213 void GuiDocument::setColSep()
2214 {
2215         setCustomMargins(marginsModule->marginCB->checkState() == Qt::Checked);
2216 }
2217
2218
2219 void GuiDocument::setCustomMargins(bool custom)
2220 {
2221         if (custom) {
2222                 // Cache current settings
2223                 tmp_leftmargin_ = widgetsToLength(marginsModule->innerLE,
2224                                                   marginsModule->innerUnit);
2225                 tmp_topmargin_ = widgetsToLength(marginsModule->topLE,
2226                                                  marginsModule->topUnit);
2227                 tmp_rightmargin_ = widgetsToLength(marginsModule->outerLE,
2228                                                    marginsModule->outerUnit);
2229                 tmp_bottommargin_ = widgetsToLength(marginsModule->bottomLE,
2230                                                     marginsModule->bottomUnit);
2231                 tmp_headheight_ = widgetsToLength(marginsModule->headheightLE,
2232                                                   marginsModule->headheightUnit);
2233                 tmp_headsep_ = widgetsToLength(marginsModule->headsepLE,
2234                                                marginsModule->headsepUnit);
2235                 tmp_footskip_ = widgetsToLength(marginsModule->footskipLE,
2236                                                 marginsModule->footskipUnit);
2237                 tmp_columnsep_ = widgetsToLength(marginsModule->columnsepLE,
2238                                                  marginsModule->columnsepUnit);
2239                 // clear widgets
2240                 marginsModule->topLE->clear();
2241                 marginsModule->bottomLE->clear();
2242                 marginsModule->innerLE->clear();
2243                 marginsModule->outerLE->clear();
2244                 marginsModule->headheightLE->clear();
2245                 marginsModule->headsepLE->clear();
2246                 marginsModule->footskipLE->clear();
2247                 marginsModule->columnsepLE->clear();
2248         } else {
2249                 Length::UNIT const default_unit = Length::defaultUnit();
2250                 // re-fill chached values
2251                 lengthToWidgets(marginsModule->topLE,
2252                                 marginsModule->topUnit,
2253                                 tmp_topmargin_, default_unit);
2254                 lengthToWidgets(marginsModule->bottomLE,
2255                                 marginsModule->bottomUnit,
2256                                 tmp_bottommargin_, default_unit);
2257                 lengthToWidgets(marginsModule->innerLE,
2258                                 marginsModule->innerUnit,
2259                                 tmp_leftmargin_, default_unit);
2260                 lengthToWidgets(marginsModule->outerLE,
2261                                 marginsModule->outerUnit,
2262                                 tmp_rightmargin_, default_unit);
2263                 lengthToWidgets(marginsModule->headheightLE,
2264                                 marginsModule->headheightUnit,
2265                                 tmp_headheight_, default_unit);
2266                 lengthToWidgets(marginsModule->headsepLE,
2267                                 marginsModule->headsepUnit,
2268                                 tmp_headsep_, default_unit);
2269                 lengthToWidgets(marginsModule->footskipLE,
2270                                 marginsModule->footskipUnit,
2271                                 tmp_footskip_, default_unit);
2272                 lengthToWidgets(marginsModule->columnsepLE,
2273                                 marginsModule->columnsepUnit,
2274                                 tmp_columnsep_, default_unit);
2275         }
2276         marginsModule->topL->setEnabled(!custom);
2277         marginsModule->topLE->setEnabled(!custom);
2278         marginsModule->topUnit->setEnabled(!custom);
2279
2280         marginsModule->bottomL->setEnabled(!custom);
2281         marginsModule->bottomLE->setEnabled(!custom);
2282         marginsModule->bottomUnit->setEnabled(!custom);
2283
2284         marginsModule->innerL->setEnabled(!custom);
2285         marginsModule->innerLE->setEnabled(!custom);
2286         marginsModule->innerUnit->setEnabled(!custom);
2287
2288         marginsModule->outerL->setEnabled(!custom);
2289         marginsModule->outerLE->setEnabled(!custom);
2290         marginsModule->outerUnit->setEnabled(!custom);
2291
2292         marginsModule->headheightL->setEnabled(!custom);
2293         marginsModule->headheightLE->setEnabled(!custom);
2294         marginsModule->headheightUnit->setEnabled(!custom);
2295
2296         marginsModule->headsepL->setEnabled(!custom);
2297         marginsModule->headsepLE->setEnabled(!custom);
2298         marginsModule->headsepUnit->setEnabled(!custom);
2299
2300         marginsModule->footskipL->setEnabled(!custom);
2301         marginsModule->footskipLE->setEnabled(!custom);
2302         marginsModule->footskipUnit->setEnabled(!custom);
2303
2304         bool const enableColSep = !custom &&
2305                         textLayoutModule->twoColumnCB->checkState() == Qt::Checked;
2306         marginsModule->columnsepL->setEnabled(enableColSep);
2307         marginsModule->columnsepLE->setEnabled(enableColSep);
2308         marginsModule->columnsepUnit->setEnabled(enableColSep);
2309
2310         // set some placeholder text that hint on defaults
2311         QString const placeholder = marginsModule->marginCB->isChecked() ?
2312                 qt_("Default margins") : qt_("Package defaults");
2313         // set tooltip depending on gemoetry state
2314         QString const tooltip = marginsModule->marginCB->isChecked() ?
2315                 qt_("If no value is given, the defaults as set by the class, a package or the preamble are used.")
2316                 : qt_("If no value is given, the defaults as set by the geometry package or a package/class overriding geometry's defaults are used.");
2317         marginsModule->topLE->setPlaceholderText(placeholder);
2318         marginsModule->bottomLE->setPlaceholderText(placeholder);
2319         marginsModule->innerLE->setPlaceholderText(placeholder);
2320         marginsModule->outerLE->setPlaceholderText(placeholder);
2321         marginsModule->headheightLE->setPlaceholderText(placeholder);
2322         marginsModule->headsepLE->setPlaceholderText(placeholder);
2323         marginsModule->footskipLE->setPlaceholderText(placeholder);
2324         marginsModule->columnsepLE->setPlaceholderText(placeholder);
2325         marginsModule->topLE->setToolTip(tooltip);
2326         marginsModule->bottomLE->setToolTip(tooltip);
2327         marginsModule->innerLE->setToolTip(tooltip);
2328         marginsModule->outerLE->setToolTip(tooltip);
2329         marginsModule->headheightLE->setToolTip(tooltip);
2330         marginsModule->headsepLE->setToolTip(tooltip);
2331         marginsModule->footskipLE->setToolTip(tooltip);
2332         marginsModule->columnsepLE->setToolTip(tooltip);
2333 }
2334
2335
2336 void GuiDocument::changeBackgroundColor()
2337 {
2338         QColor const & newColor = getColor(rgb2qcolor(set_backgroundcolor));
2339         if (!newColor.isValid())
2340                 return;
2341         // set the color
2342         colorModule->pageBackgroundCF->setVisible(true);
2343         colorModule->pageBackgroundCF->setStyleSheet(
2344                 colorFrameStyleSheet(newColor));
2345         // save color
2346         set_backgroundcolor = rgbFromHexName(fromqstr(newColor.name()));
2347         is_backgroundcolor = true;
2348         change_adaptor();
2349 }
2350
2351
2352 void GuiDocument::deleteBackgroundColor()
2353 {
2354         // set the color back to default by setting an empty StyleSheet
2355         colorModule->pageBackgroundCF->setStyleSheet(QLatin1String(""));
2356         colorModule->pageBackgroundCF->setVisible(false);
2357         // save default color (white)
2358         set_backgroundcolor = rgbFromHexName("#ffffff");
2359         is_backgroundcolor = false;
2360         change_adaptor();
2361 }
2362
2363
2364 void GuiDocument::changeFontColor()
2365 {
2366         QColor const & newColor = getColor(rgb2qcolor(set_fontcolor));
2367         if (!newColor.isValid())
2368                 return;
2369         //  set the color
2370         colorModule->mainTextCF->setVisible(true);
2371         colorModule->mainTextCF->setStyleSheet(
2372                 colorFrameStyleSheet(newColor));
2373         // save color
2374         set_fontcolor = rgbFromHexName(fromqstr(newColor.name()));
2375         is_fontcolor = true;
2376         change_adaptor();
2377 }
2378
2379
2380 void GuiDocument::deleteFontColor()
2381 {
2382         // set the button color back to default by setting an empty StyleSheet
2383         colorModule->mainTextCF->setStyleSheet(QLatin1String(""));
2384         colorModule->mainTextCF->setVisible(false);
2385         // save default color (black)
2386         set_fontcolor = rgbFromHexName("#000000");
2387         is_fontcolor = false;
2388         change_adaptor();
2389 }
2390
2391
2392 void GuiDocument::changeNoteFontColor()
2393 {
2394         QColor const & newColor = getColor(rgb2qcolor(set_notefontcolor));
2395         if (!newColor.isValid())
2396                 return;
2397         // set the color
2398         colorModule->noteFontCF->setStyleSheet(
2399                 colorFrameStyleSheet(newColor));
2400         // save color
2401         set_notefontcolor = rgbFromHexName(fromqstr(newColor.name()));
2402         is_notefontcolor = true;
2403         change_adaptor();
2404 }
2405
2406
2407 void GuiDocument::deleteNoteFontColor()
2408 {
2409         // set the color back to pref
2410         theApp()->getRgbColor(Color_greyedouttext, set_notefontcolor);
2411         colorModule->noteFontCF->setStyleSheet(
2412                 colorFrameStyleSheet(rgb2qcolor(set_notefontcolor)));
2413         is_notefontcolor = false;
2414         change_adaptor();
2415 }
2416
2417
2418 void GuiDocument::changeBoxBackgroundColor()
2419 {
2420         QColor const & newColor = getColor(rgb2qcolor(set_boxbgcolor));
2421         if (!newColor.isValid())
2422                 return;
2423         // set the color
2424         colorModule->boxBackgroundCF->setStyleSheet(
2425                 colorFrameStyleSheet(newColor));
2426         // save color
2427         set_boxbgcolor = rgbFromHexName(fromqstr(newColor.name()));
2428         is_boxbgcolor = true;
2429         change_adaptor();
2430 }
2431
2432
2433 void GuiDocument::deleteBoxBackgroundColor()
2434 {
2435         // set the color back to pref
2436         theApp()->getRgbColor(Color_shadedbg, set_boxbgcolor);
2437         colorModule->boxBackgroundCF->setStyleSheet(
2438                 colorFrameStyleSheet(rgb2qcolor(set_boxbgcolor)));
2439         is_boxbgcolor = false;
2440         change_adaptor();
2441 }
2442
2443
2444 void GuiDocument::updateQuoteStyles(bool const set)
2445 {
2446         Language const * lang = lyx::languages.getLanguage(
2447                 fromqstr(langModule->languageCO->itemData(
2448                         langModule->languageCO->currentIndex()).toString()));
2449
2450         QuoteStyle def = bp_.getQuoteStyle(lang->quoteStyle());
2451
2452         langModule->quoteStyleCO->clear();
2453
2454         bool has_default = false;
2455         for (int i = 0; i < quoteparams.stylescount(); ++i) {
2456                 QuoteStyle qs = QuoteStyle(i);
2457                 if (qs == QuoteStyle::Dynamic)
2458                         continue;
2459                 bool const langdef = (qs == def);
2460                 if (langdef) {
2461                         // add the default style on top
2462                         langModule->quoteStyleCO->insertItem(0,
2463                                 toqstr(quoteparams.getGuiLabel(qs, langdef)), static_cast<int>(qs));
2464                         has_default = true;
2465                 }
2466                 else
2467                         langModule->quoteStyleCO->addItem(
2468                                 toqstr(quoteparams.getGuiLabel(qs, langdef)), static_cast<int>(qs));
2469         }
2470         // Use document serif font to assure quotation marks are distinguishable
2471         QFont comboFont(toqstr(lyxrc.roman_font_name),
2472                         langModule->quoteStyleCO->fontInfo().pointSize() * 1.4, -1, false);
2473         QFontMetrics fm(comboFont);
2474         // calculate width of the widest item in the set font
2475         int qswidth = 0;
2476         for (int i = 0; i < langModule->quoteStyleCO->count(); ++i) {
2477                 langModule->quoteStyleCO->setItemData(i, QVariant(comboFont), Qt::FontRole);
2478                 QString str = langModule->quoteStyleCO->itemText(i);
2479 #if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0))
2480                 qswidth = max(qswidth, fm.horizontalAdvance(str));
2481 #else
2482                 qswidth = max(qswidth, fm.width(str));
2483 #endif
2484         }
2485         // add scrollbar width and margin to width
2486         qswidth += langModule->quoteStyleCO->style()->pixelMetric(QStyle::PM_ScrollBarExtent);
2487         qswidth += langModule->quoteStyleCO->view()->autoScrollMargin();
2488         langModule->quoteStyleCO->view()->setMinimumWidth(qswidth);
2489         if (set && has_default)
2490                 // (re)set to the default style
2491                 langModule->quoteStyleCO->setCurrentIndex(0);
2492 }
2493
2494
2495 void GuiDocument::languageChanged(int i)
2496 {
2497         // some languages only work with Polyglossia
2498         Language const * lang = lyx::languages.getLanguage(
2499                 fromqstr(langModule->languageCO->itemData(i).toString()));
2500         if (lang->babel().empty() && !lang->polyglossia().empty()
2501                 && lang->required() != "CJK" && lang->required() != "japanese") {
2502                         // If we force to switch fontspec on, store
2503                         // current state (#8717)
2504                         if (fontModule->osFontsCB->isEnabled())
2505                                 forced_fontspec_activation =
2506                                         !fontModule->osFontsCB->isChecked();
2507                         fontModule->osFontsCB->setChecked(true);
2508                         fontModule->osFontsCB->setEnabled(false);
2509         }
2510         else {
2511                 fontModule->osFontsCB->setEnabled(true);
2512                 // If we have forced to switch fontspec on,
2513                 // restore previous state (#8717)
2514                 if (forced_fontspec_activation)
2515                         fontModule->osFontsCB->setChecked(false);
2516                 forced_fontspec_activation = false;
2517         }
2518
2519         // set appropriate quotation mark style
2520         updateQuoteStyles(true);
2521 }
2522
2523
2524 void GuiDocument::osFontsChanged(bool nontexfonts)
2525 {
2526         bool const tex_fonts = !nontexfonts;
2527         // store current fonts
2528         QString const font_roman = fontModule->fontsRomanCO->getData(
2529                         fontModule->fontsRomanCO->currentIndex());
2530         QString const font_sans = fontModule->fontsSansCO->getData(
2531                         fontModule->fontsSansCO->currentIndex());
2532         QString const font_typewriter = fontModule->fontsTypewriterCO->getData(
2533                         fontModule->fontsTypewriterCO->currentIndex());
2534         QString const font_math = fontModule->fontsMathCO->itemData(
2535                         fontModule->fontsMathCO->currentIndex()).toString();
2536         int const font_sf_scale = fontModule->scaleSansSB->value();
2537         int const font_tt_scale = fontModule->scaleTypewriterSB->value();
2538
2539         updateFontlist();
2540         // store default format
2541         QString const dformat = outputModule->defaultFormatCO->itemData(
2542                 outputModule->defaultFormatCO->currentIndex()).toString();
2543         updateDefaultFormat();
2544         // try to restore default format
2545         int index = outputModule->defaultFormatCO->findData(dformat);
2546         // set to default if format is not found
2547         if (index == -1)
2548                 index = 0;
2549         outputModule->defaultFormatCO->setCurrentIndex(index);
2550
2551         // try to restore fonts which were selected two toggles ago
2552         if (!fontModule->font_roman.isEmpty())
2553                 fontModule->fontsRomanCO->set(fontModule->font_roman);
2554         if (!fontModule->font_sans.isEmpty())
2555                 fontModule->fontsSansCO->set(fontModule->font_sans);
2556         if (!fontModule->font_typewriter.isEmpty())
2557                 fontModule->fontsTypewriterCO->set(fontModule->font_typewriter);
2558         index = fontModule->fontsMathCO->findData(fontModule->font_math);
2559         if (index != -1)
2560                 fontModule->fontsMathCO->setCurrentIndex(index);
2561         // save fonts for next next toggle
2562         fontModule->font_roman = font_roman;
2563         fontModule->font_sans = font_sans;
2564         fontModule->font_typewriter = font_typewriter;
2565         fontModule->font_math = font_math;
2566         fontModule->font_sf_scale = font_sf_scale;
2567         fontModule->font_tt_scale = font_tt_scale;
2568
2569         // non-tex fonts override the "\inputencoding" option with "utf8-plain"
2570         langModule->encodingCO->setEnabled(tex_fonts);
2571         inputencodingToDialog();
2572
2573         fontModule->cjkFontLE->setEnabled(tex_fonts);
2574         fontModule->cjkFontLA->setEnabled(tex_fonts);
2575
2576         updateFontOptions();
2577
2578         fontModule->fontencLA->setEnabled(tex_fonts);
2579         fontModule->fontencCO->setEnabled(tex_fonts);
2580         if (!tex_fonts)
2581                 fontModule->fontencLE->setEnabled(false);
2582         else
2583                 fontencChanged(fontModule->fontencCO->currentIndex());
2584 }
2585
2586
2587 void GuiDocument::encodingSwitched(int i)
2588 {
2589         bool const tex_fonts = !fontModule->osFontsCB->isChecked();
2590         langModule->unicodeEncodingCO->setEnabled(tex_fonts);
2591         langModule->customEncodingCO->setEnabled(tex_fonts);
2592         langModule->autoEncodingCO->setEnabled(tex_fonts);
2593         langModule->unicodeEncodingCO->setVisible(i == EncodingSets::unicode);
2594         langModule->autoEncodingCO->setVisible(i == EncodingSets::legacy);
2595         langModule->customEncodingCO->setVisible(i == EncodingSets::custom);
2596         switch (i) {
2597         case EncodingSets::unicode:
2598                 langModule->encodingVariantLA->setBuddy(langModule->unicodeEncodingCO);
2599                 break;
2600         case EncodingSets::legacy:
2601                 langModule->encodingVariantLA->setBuddy(langModule->autoEncodingCO);
2602                 break;
2603         case EncodingSets::custom:
2604                 langModule->encodingVariantLA->setBuddy(langModule->customEncodingCO);
2605                 break;
2606         }
2607  
2608         if (tex_fonts)
2609                 langModule->unicodeEncodingCO->setItemText(1, qt_("Direct (No inputenc)"));
2610         else
2611                 langModule->unicodeEncodingCO->setItemText(1, qt_("Direct (XeTeX/LuaTeX)"));
2612 }
2613
2614 void GuiDocument::inputencodingToDialog()
2615 {
2616         QString inputenc = toqstr(bp_.inputenc);
2617         int p;
2618         if (fontModule->osFontsCB->isChecked()) { // non-tex fonts require utf8-plain
2619                 langModule->encodingCO->setCurrentIndex(EncodingSets::unicode);
2620                 langModule->unicodeEncodingCO->setCurrentIndex(
2621                         langModule->unicodeEncodingCO->findData("utf8-plain"));
2622         } else if (inputenc.startsWith("utf8")) {
2623                 langModule->encodingCO->setCurrentIndex(EncodingSets::unicode);
2624                 p = langModule->unicodeEncodingCO->findData(inputenc);
2625                 if (p == -1)
2626                         p = 0;
2627                 langModule->unicodeEncodingCO->setCurrentIndex(p);
2628                 langModule->autoEncodingCO->setCurrentIndex(0);
2629                 langModule->customEncodingCO->setCurrentIndex(0);
2630         } else if (inputenc.startsWith("auto")) {
2631                 langModule->encodingCO->setCurrentIndex(EncodingSets::legacy);
2632                 p = langModule->autoEncodingCO->findData(inputenc);
2633                 if (p == -1)
2634                         p = 0;
2635                 langModule->unicodeEncodingCO->setCurrentIndex(0);
2636                 langModule->autoEncodingCO->setCurrentIndex(p);
2637                 langModule->customEncodingCO->setCurrentIndex(0);
2638         } else {
2639                 langModule->encodingCO->setCurrentIndex(EncodingSets::custom);
2640                 p = langModule->customEncodingCO->findData(inputenc);
2641                 if (p == -1) {
2642                         p = 0;
2643                         langModule->encodingCO->setCurrentIndex(EncodingSets::unicode);
2644                 }
2645                 langModule->unicodeEncodingCO->setCurrentIndex(0);
2646                 langModule->autoEncodingCO->setCurrentIndex(0);
2647                 langModule->customEncodingCO->setCurrentIndex(p);
2648         }
2649         encodingSwitched(langModule->encodingCO->currentIndex());
2650 }
2651
2652
2653 void GuiDocument::mathFontChanged(int)
2654 {
2655         updateFontOptions();
2656 }
2657
2658 void GuiDocument::fontOsfToggled(bool state)
2659 {
2660         if (fontModule->osFontsCB->isChecked())
2661                 return;
2662         QString font = fontModule->fontsRomanCO->getData(
2663                         fontModule->fontsRomanCO->currentIndex());
2664         if (hasMonolithicExpertSet(font))
2665                 fontModule->fontScCB->setChecked(state);
2666 }
2667
2668
2669 void GuiDocument::fontScToggled(bool state)
2670 {
2671         if (fontModule->osFontsCB->isChecked())
2672                 return;
2673         QString font = fontModule->fontsRomanCO->getData(
2674                         fontModule->fontsRomanCO->currentIndex());
2675         if (hasMonolithicExpertSet(font))
2676                 fontModule->fontOsfCB->setChecked(state);
2677 }
2678
2679
2680 void GuiDocument::updateExtraOpts()
2681 {
2682         QString font = fontModule->fontsRomanCO->getData(
2683                         fontModule->fontsRomanCO->currentIndex());
2684         bool const rm_opts = providesExtraOpts(font);
2685         font = fontModule->fontsSansCO->getData(
2686                         fontModule->fontsSansCO->currentIndex());
2687         bool const sf_opts = providesExtraOpts(font);
2688         font = fontModule->fontsTypewriterCO->getData(
2689                         fontModule->fontsTypewriterCO->currentIndex());
2690         bool const tt_opts = providesExtraOpts(font);
2691         fontModule->fontspecRomanLA->setEnabled(rm_opts);
2692         fontModule->fontspecRomanLE->setEnabled(rm_opts);
2693         fontModule->fontspecSansLA->setEnabled(sf_opts);
2694         fontModule->fontspecSansLE->setEnabled(sf_opts);
2695         fontModule->fontspecTypewriterLA->setEnabled(tt_opts);
2696         fontModule->fontspecTypewriterLE->setEnabled(tt_opts);
2697 }
2698
2699
2700 void GuiDocument::updateFontOptions()
2701 {
2702         QString font = fontModule->fontsSansCO->getData(
2703                         fontModule->fontsSansCO->currentIndex());
2704         bool scalable = providesScale(font);
2705         fontModule->scaleSansSB->setEnabled(scalable);
2706         fontModule->scaleSansLA->setEnabled(scalable);
2707         fontModule->fontSansOsfCB->setEnabled(providesOSF(font));
2708         font = fontModule->fontsTypewriterCO->getData(
2709                         fontModule->fontsTypewriterCO->currentIndex());
2710         scalable = providesScale(font);
2711         fontModule->scaleTypewriterSB->setEnabled(scalable);
2712         fontModule->scaleTypewriterLA->setEnabled(scalable);
2713         fontModule->fontTypewriterOsfCB->setEnabled(providesOSF(font));
2714         font = fontModule->fontsRomanCO->getData(
2715                         fontModule->fontsRomanCO->currentIndex());
2716         fontModule->fontScCB->setEnabled(providesSC(font));
2717         fontModule->fontOsfCB->setEnabled(providesOSF(font));
2718         updateExtraOpts();
2719         updateMathFonts(font);
2720 }
2721
2722
2723 void GuiDocument::updateFontsize(string const & items, string const & sel)
2724 {
2725         fontModule->fontsizeCO->clear();
2726         fontModule->fontsizeCO->addItem(qt_("Default"));
2727
2728         for (int n = 0; !token(items,'|',n).empty(); ++n)
2729                 fontModule->fontsizeCO->
2730                         addItem(toqstr(token(items,'|',n)));
2731
2732         for (int n = 0; n < fontModule->fontsizeCO->count(); ++n) {
2733                 if (fromqstr(fontModule->fontsizeCO->itemText(n)) == sel) {
2734                         fontModule->fontsizeCO->setCurrentIndex(n);
2735                         break;
2736                 }
2737         }
2738 }
2739
2740
2741 bool GuiDocument::ot1() const
2742 {
2743         QString const fontenc =
2744                 fontModule->fontencCO->itemData(fontModule->fontencCO->currentIndex()).toString();
2745         int const i = langModule->languageCO->currentIndex();
2746         if (i == -1)
2747                 return false;
2748         QString const langname = langModule->languageCO->itemData(i).toString();
2749         Language const * newlang = lyx::languages.getLanguage(fromqstr(langname));
2750         return (fontenc == "default"
2751                 || (fontenc == "auto" && newlang->fontenc(buffer().params()) == "OT1")
2752                 || (fontenc == "custom" && fontModule->fontencLE->text() == "OT1"));
2753 }
2754
2755
2756 bool GuiDocument::completeFontset() const
2757 {
2758         return (fontModule->fontsSansCO->getData(
2759                         fontModule->fontsSansCO->currentIndex()) == "default"
2760                 && fontModule->fontsSansCO->getData(
2761                         fontModule->fontsTypewriterCO->currentIndex()) == "default");
2762 }
2763
2764
2765 bool GuiDocument::noMathFont() const
2766 {
2767         return (fontModule->fontsMathCO->itemData(
2768                 fontModule->fontsMathCO->currentIndex()).toString() == "default");
2769 }
2770
2771
2772 void GuiDocument::updateTexFonts()
2773 {
2774         LaTeXFonts::TexFontMap texfontmap = theLaTeXFonts().getLaTeXFonts();
2775
2776         LaTeXFonts::TexFontMap::const_iterator it = texfontmap.begin();
2777         LaTeXFonts::TexFontMap::const_iterator end = texfontmap.end();
2778         for (; it != end; ++it) {
2779                 LaTeXFont lf = it->second;
2780                 if (lf.name().empty()) {
2781                         LYXERR0("Error: Unnamed font: " << it->first);
2782                         continue;
2783                 }
2784                 docstring const family = lf.family();
2785                 docstring guiname = translateIfPossible(lf.guiname());
2786                 if (!lf.available(ot1(), noMathFont()))
2787                         guiname += _(" (not installed)");
2788                 if (family == "rm")
2789                         rmfonts_.insert(toqstr(guiname), toqstr(it->first));
2790                 else if (family == "sf")
2791                         sffonts_.insert(toqstr(guiname), toqstr(it->first));
2792                 else if (family == "tt")
2793                         ttfonts_.insert(toqstr(guiname), toqstr(it->first));
2794                 else if (family == "math")
2795                         mathfonts_.insert(toqstr(guiname), toqstr(it->first));
2796         }
2797 }
2798
2799
2800 void GuiDocument::updateFontlist()
2801 {
2802         // reset the filters of the CategorizedCombos
2803         fontModule->fontsRomanCO->resetFilter();
2804         fontModule->fontsSansCO->resetFilter();
2805         fontModule->fontsTypewriterCO->resetFilter();
2806         fontModule->fontsRomanCO->clear();
2807         fontModule->fontsSansCO->clear();
2808         fontModule->fontsTypewriterCO->clear();
2809         fontModule->fontsMathCO->clear();
2810
2811         // With fontspec (XeTeX, LuaTeX), we have access to all system fonts, but not the LaTeX fonts
2812         if (fontModule->osFontsCB->isChecked()) {
2813                 fontModule->fontsRomanCO->addItemSort(QString("default"), qt_("Default"),
2814                                                       QString(), qt_("Default font (as set by class)"),
2815                                                       false, false, false, true, true);
2816                 fontModule->fontsSansCO->addItemSort(QString("default"), qt_("Default"),
2817                                                      QString(), qt_("Default font (as set by class)"),
2818                                                      false, false, false, true, true);
2819                 fontModule->fontsTypewriterCO->addItemSort(QString("default"), qt_("Default"),
2820                                                            QString(), qt_("Default font (as set by class)"),
2821                                                            false, false, false, true, true);
2822                 QString unimath = qt_("Non-TeX Fonts Default");
2823                 if (!LaTeXFeatures::isAvailable("unicode-math"))
2824                         unimath += qt_(" (not available)");
2825                 fontModule->fontsMathCO->addItem(qt_("Class Default (TeX Fonts)"), QString("auto"));
2826                 fontModule->fontsMathCO->addItem(unimath, QString("default"));
2827
2828 #if QT_VERSION >= 0x060000
2829                 const QStringList families(QFontDatabase::families());
2830 #else
2831                 QFontDatabase fontdb;
2832                 const QStringList families(fontdb.families());
2833 #endif
2834                 for (auto const & family : families) {
2835                         fontModule->fontsRomanCO->addItemSort(family, family,
2836                                                               QString(), QString(),
2837                                                               false, false, false, true, true);
2838                         fontModule->fontsSansCO->addItemSort(family, family,
2839                                                              QString(), QString(),
2840                                                              false, false, false, true, true);
2841                         fontModule->fontsTypewriterCO->addItemSort(family, family,
2842                                                                    QString(), QString(),
2843                                                                    false, false, false, true, true);
2844                 }
2845                 return;
2846         }
2847
2848         if (rmfonts_.empty())
2849                 updateTexFonts();
2850
2851         fontModule->fontsRomanCO->addItemSort(QString("default"), qt_("Default"),
2852                                               QString(), qt_("Default font (as set by class)"),
2853                                               false, false, false, true, true);
2854         QMap<QString, QString>::const_iterator rmi = rmfonts_.constBegin();
2855         while (rmi != rmfonts_.constEnd()) {
2856                 fontModule->fontsRomanCO->addItemSort(rmi.value(), rmi.key(),
2857                                                       QString(), QString(),
2858                                                       false, false, false, true, true);
2859                 ++rmi;
2860         }
2861
2862         fontModule->fontsSansCO->addItemSort(QString("default"), qt_("Default"),
2863                                              QString(), qt_("Default font (as set by class)"),
2864                                              false, false, false, true, true);
2865         QMap<QString, QString>::const_iterator sfi = sffonts_.constBegin();
2866         while (sfi != sffonts_.constEnd()) {
2867                 fontModule->fontsSansCO->addItemSort(sfi.value(), sfi.key(),
2868                                                      QString(), QString(),
2869                                                      false, false, false, true, true);
2870                 ++sfi;
2871         }
2872
2873         fontModule->fontsTypewriterCO->addItemSort(QString("default"), qt_("Default"),
2874                                                    QString(), qt_("Default font (as set by class)"),
2875                                                    false, false, false, true, true);
2876         QMap<QString, QString>::const_iterator tti = ttfonts_.constBegin();
2877         while (tti != ttfonts_.constEnd()) {
2878                 fontModule->fontsTypewriterCO->addItemSort(tti.value(), tti.key(),
2879                                                            QString(), QString(),
2880                                                            false, false, false, true, true);
2881                 ++tti;
2882         }
2883
2884         fontModule->fontsMathCO->addItem(qt_("Automatic"), QString("auto"));
2885         fontModule->fontsMathCO->addItem(qt_("Class Default"), QString("default"));
2886         QMap<QString, QString>::const_iterator mmi = mathfonts_.constBegin();
2887         while (mmi != mathfonts_.constEnd()) {
2888                 fontModule->fontsMathCO->addItem(mmi.key(), mmi.value());
2889                 ++mmi;
2890         }
2891 }
2892
2893
2894 void GuiDocument::fontencChanged(int item)
2895 {
2896         fontModule->fontencLE->setEnabled(
2897                 fontModule->fontencCO->itemData(item).toString() == "custom");
2898         // The availability of TeX fonts depends on the font encoding
2899         updateTexFonts();
2900         updateFontOptions();
2901 }
2902
2903
2904 void GuiDocument::updateMathFonts(QString const & rm)
2905 {
2906         if (fontModule->osFontsCB->isChecked())
2907                 return;
2908         QString const math =
2909                 fontModule->fontsMathCO->itemData(fontModule->fontsMathCO->currentIndex()).toString();
2910         int const i = fontModule->fontsMathCO->findData("default");
2911         if (providesNoMath(rm) && i == -1)
2912                 fontModule->fontsMathCO->insertItem(1, qt_("Class Default"), QString("default"));
2913         else if (!providesNoMath(rm) && i != -1) {
2914                 int const c = fontModule->fontsMathCO->currentIndex();
2915                 fontModule->fontsMathCO->removeItem(i);
2916                 if (c == i)
2917                         fontModule->fontsMathCO->setCurrentIndex(0);
2918         }
2919 }
2920
2921
2922 void GuiDocument::romanChanged(int item)
2923 {
2924         QString const font = fontModule->fontsRomanCO->getData(item);
2925         fontModule->fontOsfCB->setEnabled(providesOSF(font));
2926         updateExtraOpts();
2927         if (fontModule->osFontsCB->isChecked())
2928                 return;
2929         fontModule->fontScCB->setEnabled(providesSC(font));
2930         updateMathFonts(font);
2931 }
2932
2933
2934 void GuiDocument::sansChanged(int item)
2935 {
2936         QString const font = fontModule->fontsSansCO->getData(item);
2937         bool const scalable = providesScale(font);
2938         fontModule->scaleSansSB->setEnabled(scalable);
2939         fontModule->scaleSansLA->setEnabled(scalable);
2940         fontModule->fontSansOsfCB->setEnabled(providesOSF(font));
2941         updateExtraOpts();
2942 }
2943
2944
2945 void GuiDocument::ttChanged(int item)
2946 {
2947         QString const font = fontModule->fontsTypewriterCO->getData(item);
2948         bool scalable = providesScale(font);
2949         fontModule->scaleTypewriterSB->setEnabled(scalable);
2950         fontModule->scaleTypewriterLA->setEnabled(scalable);
2951         fontModule->fontTypewriterOsfCB->setEnabled(providesOSF(font));
2952         updateExtraOpts();
2953 }
2954
2955
2956 void GuiDocument::updatePagestyle(string const & items, string const & sel)
2957 {
2958         pagestyles.clear();
2959         pageLayoutModule->pagestyleCO->clear();
2960         pageLayoutModule->pagestyleCO->addItem(qt_("Default"));
2961
2962         for (int n = 0; !token(items, '|', n).empty(); ++n) {
2963                 string style = token(items, '|', n);
2964                 QString style_gui = qt_(style);
2965                 pagestyles.push_back(pair<string, QString>(style, style_gui));
2966                 pageLayoutModule->pagestyleCO->addItem(style_gui);
2967         }
2968
2969         if (sel == "default") {
2970                 pageLayoutModule->pagestyleCO->setCurrentIndex(0);
2971                 return;
2972         }
2973
2974         int nn = 0;
2975
2976         for (auto const & pagestyle : pagestyles)
2977                 if (pagestyle.first == sel)
2978                         nn = pageLayoutModule->pagestyleCO->findText(pagestyle.second);
2979
2980         if (nn > 0)
2981                 pageLayoutModule->pagestyleCO->setCurrentIndex(nn);
2982 }
2983
2984
2985 void GuiDocument::browseLayout()
2986 {
2987         QString const label1 = qt_("Lay&outs");
2988         QString const dir1 = toqstr(lyxrc.document_path);
2989         QStringList const filter(qt_("LyX Layout (*.layout)"));
2990         QString file = browseRelToParent(QString(), bufferFilePath(),
2991                 qt_("Local layout file"), filter, false,
2992                 label1, dir1);
2993
2994         if (!file.endsWith(".layout"))
2995                 return;
2996
2997         FileName layoutFile = support::makeAbsPath(fromqstr(file),
2998                 fromqstr(bufferFilePath()));
2999
3000         int const ret = Alert::prompt(_("Local layout file"),
3001                 _("The layout file you have selected is a local layout\n"
3002                   "file, not one in the system or user directory.\n"
3003                   "Your document will not work with this layout if you\n"
3004                   "move the layout file to a different directory."),
3005                   1, 1, _("&Set Layout"), _("&Cancel"));
3006         if (ret == 1)
3007                 return;
3008
3009         // load the layout file
3010         LayoutFileList & bcl = LayoutFileList::get();
3011         string classname = layoutFile.onlyFileName();
3012         // this will update an existing layout if that layout has been loaded before.
3013         LayoutFileIndex name = support::onlyFileName(bcl.addLocalLayout(
3014                 classname.substr(0, classname.size() - 7),
3015                 layoutFile.onlyPath().absFileName()));
3016
3017         if (name.empty()) {
3018                 Alert::error(_("Error"),
3019                         _("Unable to read local layout file."));
3020                 return;
3021         }
3022
3023         const_cast<Buffer &>(buffer()).setLayoutPos(layoutFile.onlyPath().absFileName());
3024
3025         // do not trigger classChanged if there is no change.
3026         if (latexModule->classCO->currentText() == toqstr(name))
3027                 return;
3028
3029         // add to combo box
3030         bool const avail = latexModule->classCO->set(toqstr(name));
3031         if (!avail) {
3032                 LayoutFile const & tc = bcl[name];
3033                 docstring const guiname = translateIfPossible(from_utf8(tc.description()));
3034                 // tooltip sensu "KOMA-Script Article [Class 'scrartcl']"
3035                 QString tooltip = toqstr(bformat(_("%1$s [Class '%2$s']"), guiname, from_utf8(tc.latexname())));
3036                 tooltip += '\n' + qt_("This is a local layout file.");
3037                 latexModule->classCO->addItemSort(toqstr(tc.name()), toqstr(guiname),
3038                                                   toqstr(translateIfPossible(from_utf8(tc.category()))),
3039                                                   tooltip,
3040                                                   true, true, true, true);
3041                 latexModule->classCO->set(toqstr(name));
3042         }
3043
3044         classChanged();
3045 }
3046
3047
3048 void GuiDocument::browseMaster()
3049 {
3050         QString const title = qt_("Select master document");
3051         QString const dir1 = toqstr(lyxrc.document_path);
3052         QString const old = latexModule->childDocLE->text();
3053         QString const docpath = toqstr(support::onlyPath(buffer().absFileName()));
3054         QStringList const filter(qt_("LyX Files (*.lyx)"));
3055         QString file = browseRelToSub(old, docpath, title, filter, false,
3056                 qt_("D&ocuments"), toqstr(lyxrc.document_path));
3057
3058         if (!file.isEmpty())
3059                 latexModule->childDocLE->setText(file);
3060 }
3061
3062
3063 void GuiDocument::classChanged_adaptor()
3064 {
3065         const_cast<Buffer &>(buffer()).setLayoutPos(string());
3066         classChanged();
3067 }
3068
3069
3070 void GuiDocument::classChanged()
3071 {
3072         int idx = latexModule->classCO->currentIndex();
3073         if (idx < 0)
3074                 return;
3075         string const classname = fromqstr(latexModule->classCO->getData(idx));
3076
3077         if (buttonBox->button(QDialogButtonBox::Apply)->isEnabled()) {
3078                 int const ret = Alert::prompt(_("Unapplied changes"),
3079                                 _("Some changes in the dialog were not yet applied.\n"
3080                                 "If you do not apply now, they will be lost after this action."),
3081                                 1, 1, _("&Apply"), _("&Dismiss"));
3082                 if (ret == 0)
3083                         applyView();
3084         }
3085
3086         // We load the TextClass as soon as it is selected. This is
3087         // necessary so that other options in the dialog can be updated
3088         // according to the new class. Note, however, that, if you use
3089         // the scroll wheel when sitting on the combo box, we'll load a
3090         // lot of TextClass objects very quickly....
3091         if (!bp_.setBaseClass(classname, buffer().layoutPos())) {
3092                 Alert::error(_("Error"), _("Unable to set document class."));
3093                 return;
3094         }
3095         if (lyxrc.auto_reset_options)
3096                 bp_.useClassDefaults();
3097
3098         // With the introduction of modules came a distinction between the base
3099         // class and the document class. The former corresponds to the main layout
3100         // file; the latter is that plus the modules (or the document-specific layout,
3101         // or  whatever else there could be). Our parameters come from the document
3102         // class. So when we set the base class, we also need to recreate the document
3103         // class. Otherwise, we still have the old one.
3104         bp_.makeDocumentClass();
3105         paramsToDialog();
3106 }
3107
3108
3109 void GuiDocument::languagePackageChanged(int i)
3110 {
3111          langModule->languagePackageLE->setEnabled(
3112                 langModule->languagePackageCO->itemData(i).toString() == "custom");
3113 }
3114
3115
3116 void GuiDocument::biblioChanged()
3117 {
3118         biblioChanged_ = true;
3119         change_adaptor();
3120 }
3121
3122
3123 void GuiDocument::checkPossibleCiteEngines()
3124 {
3125         // Check if the class provides a specific engine,
3126         // and if so, enforce this.
3127         string force_engine;
3128         if (documentClass().provides("natbib")
3129             || documentClass().provides("natbib-internal"))
3130                 force_engine = "natbib";
3131         else if (documentClass().provides("jurabib"))
3132                 force_engine = "jurabib";
3133         else if (documentClass().provides("biblatex"))
3134                 force_engine = "biblatex";
3135         else if (documentClass().provides("biblatex-natbib"))
3136                 force_engine = "biblatex-natbib";
3137
3138         if (!force_engine.empty())
3139                 biblioModule->citeEngineCO->setCurrentIndex(
3140                         biblioModule->citeEngineCO->findData(toqstr(force_engine)));
3141         biblioModule->citeEngineCO->setEnabled(force_engine.empty());
3142 }
3143
3144
3145 void GuiDocument::rescanBibFiles()
3146 {
3147         if (isBiblatex())
3148                 rescanTexStyles("bbx cbx");
3149         else
3150                 rescanTexStyles("bst");
3151 }
3152
3153
3154 void GuiDocument::resetDefaultBibfile(string const & which)
3155 {
3156         QString const engine =
3157                 biblioModule->citeEngineCO->itemData(
3158                                 biblioModule->citeEngineCO->currentIndex()).toString();
3159
3160         CiteEngineType const cet =
3161                 CiteEngineType(biblioModule->citeStyleCO->itemData(
3162                                                           biblioModule->citeStyleCO->currentIndex()).toInt());
3163
3164         updateDefaultBiblio(theCiteEnginesList[fromqstr(engine)]->getDefaultBiblio(cet), which);
3165 }
3166
3167
3168 void GuiDocument::resetDefaultBbxBibfile()
3169 {
3170         resetDefaultBibfile("bbx");
3171 }
3172
3173
3174 void GuiDocument::resetDefaultCbxBibfile()
3175 {
3176         resetDefaultBibfile("cbx");
3177 }
3178
3179
3180 void GuiDocument::citeEngineChanged(int n)
3181 {
3182         QString const engine =
3183                 biblioModule->citeEngineCO->itemData(n).toString();
3184
3185         vector<string> const engs =
3186                 theCiteEnginesList[fromqstr(engine)]->getEngineType();
3187
3188         updateCiteStyles(engs);
3189         updateEngineDependends();
3190         resetDefaultBibfile();
3191         biblioChanged();
3192 }
3193
3194
3195 void GuiDocument::updateEngineDependends()
3196 {
3197         bool const biblatex = isBiblatex();
3198
3199         // These are only useful with BibTeX
3200         biblioModule->defaultBiblioCO->setEnabled(!biblatex);
3201         biblioModule->bibtexStyleLA->setEnabled(!biblatex);
3202         biblioModule->resetDefaultBiblioPB->setEnabled(!biblatex);
3203         biblioModule->bibtopicCB->setEnabled(!biblatex);
3204
3205         // These are only useful with Biblatex
3206         biblioModule->biblatexBbxCO->setEnabled(biblatex);
3207         biblioModule->biblatexBbxLA->setEnabled(biblatex);
3208         biblioModule->biblatexCbxCO->setEnabled(biblatex);
3209         biblioModule->biblatexCbxLA->setEnabled(biblatex);
3210         biblioModule->resetBbxPB->setEnabled(biblatex);
3211         biblioModule->resetCbxPB->setEnabled(biblatex);
3212         biblioModule->matchBbxPB->setEnabled(biblatex);
3213
3214         // These are useful with biblatex, jurabib and natbib
3215         QString const engine =
3216                 biblioModule->citeEngineCO->itemData(
3217                                 biblioModule->citeEngineCO->currentIndex()).toString();
3218         LyXCiteEngine const * ce = theCiteEnginesList[fromqstr(engine)];
3219
3220         bool const citepack = ce->required("biblatex.sty") || ce->required("jurabib.sty")
3221                         || ce->required("natbib.sty");
3222         biblioModule->citePackageOptionsLE->setEnabled(citepack);
3223         biblioModule->citePackageOptionsL->setEnabled(citepack);
3224 }
3225
3226
3227 void GuiDocument::citeStyleChanged()
3228 {
3229         QString const engine =
3230                 biblioModule->citeEngineCO->itemData(
3231                                 biblioModule->citeEngineCO->currentIndex()).toString();
3232         QString const currentDef = isBiblatex() ?
3233                 biblioModule->biblatexBbxCO->currentText()
3234                 : biblioModule->defaultBiblioCO->currentText();
3235         if (theCiteEnginesList[fromqstr(engine)]->isDefaultBiblio(fromqstr(currentDef)))
3236                 resetDefaultBibfile();
3237
3238         biblioChanged();
3239 }
3240
3241
3242 void GuiDocument::bibtexChanged(int n)
3243 {
3244         biblioModule->bibtexOptionsLE->setEnabled(
3245                 biblioModule->bibtexCO->itemData(n).toString() != "default");
3246         biblioChanged();
3247 }
3248
3249
3250 void GuiDocument::updateCiteStyles(vector<string> const & engs, CiteEngineType const & sel)
3251 {
3252         biblioModule->citeStyleCO->clear();
3253
3254         vector<string>::const_iterator it  = engs.begin();
3255         vector<string>::const_iterator end = engs.end();
3256         for (; it != end; ++it) {
3257                 if (*it == "default")
3258                         biblioModule->citeStyleCO->addItem(qt_("Basic numerical"),
3259                                                            ENGINE_TYPE_DEFAULT);
3260                 else if (*it == "authoryear")
3261                         biblioModule->citeStyleCO->addItem(qt_("Author-year"),
3262                                                            ENGINE_TYPE_AUTHORYEAR);
3263                 else if (*it == "numerical")
3264                         biblioModule->citeStyleCO->addItem(qt_("Author-number"),
3265                                                            ENGINE_TYPE_NUMERICAL);
3266         }
3267         int i = biblioModule->citeStyleCO->findData(sel);
3268         if (biblioModule->citeStyleCO->findData(sel) == -1)
3269                 i = 0;
3270         biblioModule->citeStyleCO->setCurrentIndex(i);
3271
3272         biblioModule->citationStyleL->setEnabled(engs.size() > 1);
3273         biblioModule->citeStyleCO->setEnabled(engs.size() > 1);
3274 }
3275
3276
3277 void GuiDocument::updateEngineType(string const & items, CiteEngineType const & sel)
3278 {
3279         engine_types_.clear();
3280
3281         for (int n = 0; !token(items, '|', n).empty(); ++n) {
3282                 string style = token(items, '|', n);
3283                 engine_types_.push_back(style);
3284         }
3285
3286         updateCiteStyles(engine_types_, sel);
3287 }
3288
3289
3290 namespace {
3291         // FIXME unicode
3292         // both of these should take a vector<docstring>
3293
3294         // This is an insanely complicated attempt to make this sort of thing
3295         // work with RTL languages.
3296         docstring formatStrVec(vector<string> const & v, docstring const & s)
3297         {
3298                 //this mess formats the list as "v[0], v[1], ..., [s] v[n]"
3299                 if (v.empty())
3300                         return docstring();
3301                 if (v.size() == 1)
3302                         return translateIfPossible(from_utf8(v[0]));
3303                 if (v.size() == 2) {
3304                         docstring retval = _("%1$s and %2$s");
3305                         retval = subst(retval, _("and"), s);
3306                         return bformat(retval, translateIfPossible(from_utf8(v[0])),
3307                                        translateIfPossible(from_utf8(v[1])));
3308                 }
3309                 // The idea here is to format all but the last two items...
3310                 int const vSize = v.size();
3311                 docstring t2 = _("%1$s, %2$s");
3312                 docstring retval = translateIfPossible(from_utf8(v[0]));
3313                 for (int i = 1; i < vSize - 2; ++i)
3314                         retval = bformat(t2, retval, translateIfPossible(from_utf8(v[i])));
3315                 //...and then to  plug them, and the last two, into this schema
3316                 docstring t = _("%1$s, %2$s, and %3$s");
3317                 t = subst(t, _("and"), s);
3318                 return bformat(t, retval, translateIfPossible(from_utf8(v[vSize - 2])),
3319                                translateIfPossible(from_utf8(v[vSize - 1])));
3320         }
3321
3322         vector<string> idsToNames(vector<string> const & idList)
3323         {
3324                 vector<string> retval;
3325                 vector<string>::const_iterator it  = idList.begin();
3326                 vector<string>::const_iterator end = idList.end();
3327                 for (; it != end; ++it) {
3328                         LyXModule const * const mod = theModuleList[*it];
3329                         if (!mod)
3330                                 retval.push_back(to_utf8(bformat(_("%1$s (unavailable)"),
3331                                                 translateIfPossible(from_utf8(*it)))));
3332                         else
3333                                 retval.push_back(mod->getName());
3334                 }
3335                 return retval;
3336         }
3337 } // end anonymous namespace
3338
3339
3340 void GuiDocument::modulesToParams(BufferParams & bp)
3341 {
3342         // update list of loaded modules
3343         bp.clearLayoutModules();
3344         int const srows = modules_sel_model_.rowCount();
3345         for (int i = 0; i < srows; ++i)
3346                 bp.addLayoutModule(modules_sel_model_.getIDString(i));
3347         updateSelectedModules();
3348
3349         // update the list of removed modules
3350         bp.clearRemovedModules();
3351         LayoutModuleList const & reqmods = bp.baseClass()->defaultModules();
3352         list<string>::const_iterator rit = reqmods.begin();
3353         list<string>::const_iterator ren = reqmods.end();
3354
3355         // check each of the default modules
3356         for (; rit != ren; ++rit) {
3357                 list<string>::const_iterator mit = bp.getModules().begin();
3358                 list<string>::const_iterator men = bp.getModules().end();
3359                 bool found = false;
3360                 for (; mit != men; ++mit) {
3361                         if (*rit == *mit) {
3362                                 found = true;
3363                                 break;
3364                         }
3365                 }
3366                 if (!found) {
3367                         // the module isn't present so must have been removed by the user
3368                         bp.addRemovedModule(*rit);
3369                 }
3370         }
3371 }
3372
3373 void GuiDocument::modulesChanged()
3374 {
3375         modulesToParams(bp_);
3376
3377         if (buttonBox->button(QDialogButtonBox::Apply)->isEnabled()
3378             && (nonModuleChanged_ || shellescapeChanged_)) {
3379                 int const ret = Alert::prompt(_("Unapplied changes"),
3380                                 _("Some changes in the dialog were not yet applied.\n"
3381                                 "If you do not apply now, they will be lost after this action."),
3382                                 1, 1, _("&Apply"), _("&Dismiss"));
3383                 if (ret == 0)
3384                         applyView();
3385         }
3386
3387         modulesChanged_ = true;
3388         bp_.makeDocumentClass();
3389         paramsToDialog();
3390         changed();
3391 }
3392
3393
3394 void GuiDocument::updateModuleInfo()
3395 {
3396         selectionManager->update();
3397
3398         //Module description
3399         bool const focus_on_selected = selectionManager->selectedFocused();
3400         QAbstractItemView * lv;
3401         bool category = false;
3402         if (focus_on_selected) {
3403                 lv = modulesModule->selectedLV;
3404                 category = true;
3405         } else
3406                 lv = modulesModule->availableLV;
3407         if (lv->selectionModel()->selectedIndexes().isEmpty()) {
3408                 modulesModule->infoML->document()->clear();
3409                 return;
3410         }
3411         QModelIndex const & idx = lv->selectionModel()->currentIndex();
3412
3413         if (!idx.isValid())
3414                 return;
3415
3416         if (!focus_on_selected
3417             && modules_av_model_.itemFromIndex(idx)->hasChildren()) {
3418                 // This is a category header
3419                 modulesModule->infoML->document()->clear();
3420                 return;
3421         }
3422
3423         string const modName = focus_on_selected ?
3424                                 modules_sel_model_.getIDString(idx.row())
3425                               : fromqstr(modules_av_model_.data(idx, Qt::UserRole).toString());
3426         docstring desc = getModuleDescription(modName);
3427
3428         LayoutModuleList const & provmods = bp_.baseClass()->providedModules();
3429         if (std::find(provmods.begin(), provmods.end(), modName) != provmods.end()) {
3430                 if (!desc.empty())
3431                         desc += "\n";
3432                 desc += _("Module provided by document class.");
3433         }
3434
3435         if (category) {
3436                 docstring cat = getModuleCategory(modName);
3437                 if (!cat.empty()) {
3438                         if (!desc.empty())
3439                                 desc += "\n";
3440                         desc += bformat(_("<p><b>Category:</b> %1$s.</p>"),
3441                                         translateIfPossible(cat));
3442                 }
3443         }
3444
3445         vector<string> pkglist = getPackageList(modName);
3446         docstring pkgdesc = formatStrVec(pkglist, _("and"));
3447         if (!pkgdesc.empty()) {
3448                 if (!desc.empty())
3449                         desc += "\n";
3450                 desc += bformat(_("<p><b>Package(s) required:</b> %1$s.</p>"), pkgdesc);
3451         }
3452
3453         pkglist = getRequiredList(modName);
3454         if (!pkglist.empty()) {
3455                 vector<string> const reqdescs = idsToNames(pkglist);
3456                 pkgdesc = formatStrVec(reqdescs, _("or"));
3457                 if (!desc.empty())
3458                         desc += "\n";
3459                 desc += bformat(_("<p><b>Modules required:</b> %1$s.</p>"), pkgdesc);
3460         }
3461
3462         pkglist = getExcludedList(modName);
3463         if (!pkglist.empty()) {
3464                 vector<string> const reqdescs = idsToNames(pkglist);
3465                 pkgdesc = formatStrVec(reqdescs, _( "and"));
3466                 if (!desc.empty())
3467                         desc += "\n";
3468                 desc += bformat(_("<p><b>Modules excluded:</b> %1$s.</p>"), pkgdesc);
3469         }
3470
3471         if (!desc.empty())
3472                 desc += "\n";
3473         desc += bformat(_("<p><b>Filename:</b> <tt>%1$s.module</tt>.</p>"), from_utf8(modName));
3474
3475         if (!isModuleAvailable(modName)) {
3476                 if (!desc.empty())
3477                         desc += "\n";
3478                 desc += _("<p><font color=red><b>WARNING: Some required packages are unavailable!</b></font></p>");
3479         }
3480
3481         modulesModule->infoML->document()->setHtml(toqstr(desc));
3482 }
3483
3484
3485 void GuiDocument::updateNumbering()
3486 {
3487         DocumentClass const & tclass = documentClass();
3488
3489         numberingModule->tocTW->setUpdatesEnabled(false);
3490         numberingModule->tocTW->clear();
3491
3492         int const depth = numberingModule->depthSL->value();
3493         int const toc = numberingModule->tocSL->value();
3494         QString const no = qt_("No");
3495         QString const yes = qt_("Yes");
3496         QTreeWidgetItem * item = nullptr;
3497
3498         DocumentClass::const_iterator lit = tclass.begin();
3499         DocumentClass::const_iterator len = tclass.end();
3500         for (; lit != len; ++lit) {
3501                 int const toclevel = lit->toclevel;
3502                 if (toclevel != Layout::NOT_IN_TOC && !lit->counter.empty()) {
3503                         item = new QTreeWidgetItem(numberingModule->tocTW);
3504                         item->setText(0, toqstr(translateIfPossible(lit->name())));
3505                         item->setText(1, (toclevel <= depth) ? yes : no);
3506                         item->setText(2, (toclevel <= toc) ? yes : no);
3507                 }
3508         }
3509
3510         numberingModule->tocTW->setUpdatesEnabled(true);
3511         numberingModule->tocTW->update();
3512 }
3513
3514
3515 void GuiDocument::getTableStyles()
3516 {
3517         // We look for lyx files in the subdirectory dir of
3518         //   1) user_lyxdir
3519         //   2) build_lyxdir (if not empty)
3520         //   3) system_lyxdir
3521         // in this order. Files with a given sub-hierarchy will
3522         // only be listed once.
3523         // We also consider i18n subdirectories and store them separately.
3524         QStringList dirs;
3525
3526         // The three locations to look at.
3527         string const user = addPath(package().user_support().absFileName(), "tabletemplates");
3528         string const build = addPath(package().build_support().absFileName(), "tabletemplates");
3529         string const system = addPath(package().system_support().absFileName(), "tabletemplates");
3530
3531         dirs << toqstr(user)
3532              << toqstr(build)
3533              << toqstr(system);
3534
3535         for (int i = 0; i < dirs.size(); ++i) {
3536                 QString const & dir = dirs.at(i);
3537                 QDirIterator it(dir, QDir::Files, QDirIterator::Subdirectories);
3538                 while (it.hasNext()) {
3539                         QString fn = QFileInfo(it.next()).fileName();
3540                         if (!fn.endsWith(".lyx") || fn.contains("_1x"))
3541                                 continue;
3542                         QString data = fn.left(fn.lastIndexOf(".lyx"));
3543                         QString guiname = data;
3544                         guiname = toqstr(translateIfPossible(qstring_to_ucs4(guiname.replace('_', ' '))));
3545                         QString relpath = toqstr(makeRelPath(qstring_to_ucs4(fn),
3546                                                              qstring_to_ucs4(dir)));
3547                         if (textLayoutModule->tableStyleCO->findData(data) == -1)
3548                                 textLayoutModule->tableStyleCO->addItem(guiname, data);
3549                 }
3550         }
3551 }
3552
3553
3554 void GuiDocument::updateDefaultFormat()
3555 {
3556         if (!bufferview())
3557                 return;
3558         // make a copy in order to consider unapplied changes
3559         BufferParams param_copy = buffer().params();
3560         param_copy.useNonTeXFonts = fontModule->osFontsCB->isChecked();
3561         int const idx = latexModule->classCO->currentIndex();
3562         if (idx >= 0) {
3563                 string const classname = fromqstr(latexModule->classCO->getData(idx));
3564                 param_copy.setBaseClass(classname, buffer().layoutPos());
3565                 param_copy.makeDocumentClass(true);
3566         }
3567         outputModule->defaultFormatCO->blockSignals(true);
3568         outputModule->defaultFormatCO->clear();
3569         outputModule->defaultFormatCO->addItem(qt_("Default"),
3570                                 QVariant(QString("default")));
3571         FormatList const & formats =
3572                                 param_copy.exportableFormats(true);
3573         for (Format const * f : formats)
3574                 outputModule->defaultFormatCO->addItem
3575                         (toqstr(translateIfPossible(f->prettyname())),
3576                          QVariant(toqstr(f->name())));
3577         outputModule->defaultFormatCO->blockSignals(false);
3578 }
3579
3580
3581 bool GuiDocument::isChildIncluded(string const & child)
3582 {
3583         if (includeonlys_.empty())
3584                 return false;
3585         return (std::find(includeonlys_.begin(),
3586                           includeonlys_.end(), child) != includeonlys_.end());
3587 }
3588
3589
3590 void GuiDocument::applyView()
3591 {
3592         // auto-validate local layout
3593         if (!localLayout->isValid()) {
3594                 localLayout->validate();
3595                 if (!localLayout->isValid()) {
3596                         setApplyStopped(true);
3597                         docPS->setCurrentPanel(N_("Local Layout"));
3598                         return;
3599                 }
3600         }
3601
3602         // preamble
3603         preambleModule->apply(bp_);
3604         localLayout->apply(bp_);
3605
3606         // date
3607         bp_.suppress_date = latexModule->suppressDateCB->isChecked();
3608         bp_.use_refstyle  = latexModule->refstyleCB->isChecked();
3609         bp_.use_formatted_ref  = latexModule->refFormattedCB->isChecked();
3610
3611         // biblio
3612         string const engine =
3613                 fromqstr(biblioModule->citeEngineCO->itemData(
3614                                 biblioModule->citeEngineCO->currentIndex()).toString());
3615         bp_.setCiteEngine(engine);
3616
3617         CiteEngineType const style = CiteEngineType(biblioModule->citeStyleCO->itemData(
3618                 biblioModule->citeStyleCO->currentIndex()).toInt());
3619         if (theCiteEnginesList[engine]->hasEngineType(style))
3620                 bp_.setCiteEngineType(style);
3621         else
3622                 bp_.setCiteEngineType(ENGINE_TYPE_DEFAULT);
3623
3624         bp_.splitbib(biblioModule->bibtopicCB->isChecked());
3625
3626         bp_.multibib = fromqstr(biblioModule->bibunitsCO->itemData(
3627                                 biblioModule->bibunitsCO->currentIndex()).toString());
3628
3629         bp_.setDefaultBiblioStyle(fromqstr(biblioModule->defaultBiblioCO->currentText()));
3630
3631         bp_.biblatex_bibstyle = fromqstr(biblioModule->biblatexBbxCO->currentText());
3632         bp_.biblatex_citestyle = fromqstr(biblioModule->biblatexCbxCO->currentText());
3633         bp_.biblio_opts = fromqstr(biblioModule->citePackageOptionsLE->text());
3634
3635         string const bibtex_command =
3636                 fromqstr(biblioModule->bibtexCO->itemData(
3637                         biblioModule->bibtexCO->currentIndex()).toString());
3638         string const bibtex_options =
3639                 fromqstr(biblioModule->bibtexOptionsLE->text());
3640         if (bibtex_command == "default" || bibtex_options.empty())
3641                 bp_.bibtex_command = bibtex_command;
3642         else
3643                 bp_.bibtex_command = bibtex_command + " " + bibtex_options;
3644
3645         if (biblioChanged_) {
3646                 buffer().invalidateBibinfoCache();
3647                 buffer().removeBiblioTempFiles();
3648         }
3649
3650         // Indices
3651         indicesModule->apply(bp_);
3652
3653         // language & quotes
3654         switch (langModule->encodingCO->currentIndex()) {
3655                 case EncodingSets::unicode: {
3656                         if (!fontModule->osFontsCB->isChecked())
3657                                 bp_.inputenc = fromqstr(langModule->unicodeEncodingCO->itemData(
3658                                         langModule->unicodeEncodingCO->currentIndex()).toString());
3659                         break;
3660                 }
3661                 case EncodingSets::legacy: {
3662                         bp_.inputenc = "auto-legacy";
3663                         bp_.inputenc = fromqstr(langModule->autoEncodingCO->itemData(
3664                                 langModule->autoEncodingCO->currentIndex()).toString());
3665                         break;
3666                 }
3667                 case EncodingSets::custom: {
3668                         bp_.inputenc = fromqstr(langModule->customEncodingCO->itemData(
3669                                 langModule->customEncodingCO->currentIndex()).toString());
3670                         break;
3671                 }
3672                 default:
3673                         // this should never happen
3674                         bp_.inputenc = "utf8";
3675         }
3676         bp_.quotes_style = QuoteStyle(langModule->quoteStyleCO->itemData(
3677                 langModule->quoteStyleCO->currentIndex()).toInt());
3678         bp_.dynamic_quotes = langModule->dynamicQuotesCB->isChecked();
3679
3680         QString const langname = langModule->languageCO->itemData(
3681                 langModule->languageCO->currentIndex()).toString();
3682         Language const * newlang = lyx::languages.getLanguage(fromqstr(langname));
3683         Cursor & cur = const_cast<BufferView *>(bufferview())->cursor();
3684         // If current cursor language was the document language, then update it too.
3685         if (cur.current_font.language() == bp_.language) {
3686                 cur.current_font.setLanguage(newlang);
3687                 cur.real_current_font.setLanguage(newlang);
3688         }
3689         bp_.language = newlang;
3690
3691         QString const pack = langModule->languagePackageCO->itemData(
3692                 langModule->languagePackageCO->currentIndex()).toString();
3693         if (pack == "custom")
3694                 bp_.lang_package =
3695                         fromqstr(langModule->languagePackageLE->text());
3696         else
3697                 bp_.lang_package = fromqstr(pack);
3698
3699         //color
3700         bp_.backgroundcolor = set_backgroundcolor;
3701         bp_.isbackgroundcolor = is_backgroundcolor;
3702         bp_.fontcolor = set_fontcolor;
3703         bp_.isfontcolor = is_fontcolor;
3704         bp_.notefontcolor = set_notefontcolor;
3705         bp_.isnotefontcolor = is_notefontcolor;
3706         if (is_notefontcolor) {
3707                 // Set information used in statusbar (#12130)
3708                 lcolor.setColor("notefontcolor", lyx::X11hexname(set_notefontcolor));
3709                 lcolor.setGUIName("notefontcolor", N_("greyedout inset text"));
3710         }
3711         bp_.boxbgcolor = set_boxbgcolor;
3712         bp_.isboxbgcolor = is_boxbgcolor;
3713
3714         // numbering
3715         if (bp_.documentClass().hasTocLevels()) {
3716                 bp_.tocdepth = numberingModule->tocSL->value();
3717                 bp_.secnumdepth = numberingModule->depthSL->value();
3718         }
3719         bp_.use_lineno = numberingModule->linenoCB->isChecked();
3720         bp_.lineno_opts = fromqstr(numberingModule->linenoLE->text());
3721
3722         // bullets
3723         bp_.user_defined_bullet(0) = bulletsModule->bullet(0);
3724         bp_.user_defined_bullet(1) = bulletsModule->bullet(1);
3725         bp_.user_defined_bullet(2) = bulletsModule->bullet(2);
3726         bp_.user_defined_bullet(3) = bulletsModule->bullet(3);
3727
3728         // packages
3729         bp_.graphics_driver =
3730                 tex_graphics[latexModule->psdriverCO->currentIndex()];
3731
3732         // text layout
3733         int idx = latexModule->classCO->currentIndex();
3734         if (idx >= 0) {
3735                 string const classname = fromqstr(latexModule->classCO->getData(idx));
3736                 bp_.setBaseClass(classname, buffer().layoutPos());
3737         }
3738
3739         // Modules
3740         modulesToParams(bp_);
3741
3742         // Math
3743         map<string, string> const & packages = BufferParams::auto_packages();
3744         for (map<string, string>::const_iterator it = packages.begin();
3745              it != packages.end(); ++it) {
3746                 QTableWidgetItem * item = mathsModule->packagesTW->findItems(toqstr(it->first), Qt::MatchExactly)[0];
3747                 if (!item)
3748                         continue;
3749                 int row = mathsModule->packagesTW->row(item);
3750
3751                 QRadioButton * rb =
3752                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 1)->layout()->itemAt(0)->widget();
3753                 if (rb->isChecked()) {
3754                         bp_.use_package(it->first, BufferParams::package_auto);
3755                         continue;
3756                 }
3757                 rb = (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 2)->layout()->itemAt(0)->widget();
3758                 if (rb->isChecked()) {
3759                         bp_.use_package(it->first, BufferParams::package_on);
3760                         continue;
3761                 }
3762                 rb = (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 3)->layout()->itemAt(0)->widget();
3763                 if (rb->isChecked())
3764                         bp_.use_package(it->first, BufferParams::package_off);
3765         }
3766         // if math is indented
3767         bp_.is_math_indent = mathsModule->MathIndentCB->isChecked();
3768         if (bp_.is_math_indent) {
3769                 // if formulas are indented
3770                 if (mathsModule->MathIndentCO->itemData(mathsModule->MathIndentCO->currentIndex()) == "custom") {
3771                         Length mathindent(widgetsToLength(mathsModule->MathIndentLE,
3772                                                           mathsModule->MathIndentLengthCO));
3773                         bp_.setMathIndent(mathindent);
3774                 } else
3775                         // default
3776                         bp_.setMathIndent(Length());
3777         }
3778         switch (mathsModule->MathNumberingPosCO->currentIndex()) {
3779                 case 0:
3780                         bp_.math_numbering_side = BufferParams::LEFT;
3781                         break;
3782                 case 1:
3783                         bp_.math_numbering_side = BufferParams::DEFAULT;
3784                         break;
3785                 case 2:
3786                         bp_.math_numbering_side = BufferParams::RIGHT;
3787                         break;
3788                 default:
3789                         // this should never happen
3790                         bp_.math_numbering_side = BufferParams::DEFAULT;
3791                         break;
3792         }
3793
3794         // Page Layout
3795         if (pageLayoutModule->pagestyleCO->currentIndex() == 0)
3796                 bp_.pagestyle = "default";
3797         else {
3798                 QString style_gui = pageLayoutModule->pagestyleCO->currentText();
3799                 for (size_t i = 0; i != pagestyles.size(); ++i)
3800                         if (pagestyles[i].second == style_gui)
3801                                 bp_.pagestyle = pagestyles[i].first;
3802         }
3803
3804         // Text Layout
3805         switch (textLayoutModule->lspacingCO->currentIndex()) {
3806         case 0:
3807                 bp_.spacing().set(Spacing::Single);
3808                 break;
3809         case 1:
3810                 bp_.spacing().set(Spacing::Onehalf);
3811                 break;
3812         case 2:
3813                 bp_.spacing().set(Spacing::Double);
3814                 break;
3815         case 3: {
3816                 string s = widgetToDoubleStr(textLayoutModule->lspacingLE);
3817                 if (s.empty())
3818                         bp_.spacing().set(Spacing::Single);
3819                 else
3820                         bp_.spacing().set(Spacing::Other, s);
3821                 break;
3822                 }
3823         }
3824
3825         if (textLayoutModule->twoColumnCB->isChecked())
3826                 bp_.columns = 2;
3827         else
3828                 bp_.columns = 1;
3829
3830         bp_.justification = textLayoutModule->justCB->isChecked();
3831
3832         if (textLayoutModule->indentRB->isChecked()) {
3833                 // if paragraphs are separated by an indentation
3834                 bp_.paragraph_separation = BufferParams::ParagraphIndentSeparation;
3835                 if (textLayoutModule->indentCO->itemData(textLayoutModule->indentCO->currentIndex()) == "custom") {
3836                         Length parindent(widgetsToLength(textLayoutModule->indentLE,
3837                                                          textLayoutModule->indentLengthCO));
3838                         bp_.setParIndent(parindent);
3839                 } else
3840                         // default
3841                         bp_.setParIndent(Length());
3842         } else {
3843                 // if paragraphs are separated by a skip
3844                 bp_.paragraph_separation = BufferParams::ParagraphSkipSeparation;
3845                 VSpace::VSpaceKind spacekind =
3846                         VSpace::VSpaceKind(textLayoutModule->skipCO->itemData(textLayoutModule->skipCO->currentIndex()).toInt());
3847                 switch (spacekind) {
3848                 case VSpace::SMALLSKIP:
3849                 case VSpace::MEDSKIP:
3850                 case VSpace::BIGSKIP:
3851                 case VSpace::HALFLINE:
3852                 case VSpace::FULLLINE:
3853                         bp_.setDefSkip(VSpace(spacekind));
3854                         break;
3855                 case VSpace::LENGTH: {
3856                         VSpace vs = VSpace(
3857                                 widgetsToLength(textLayoutModule->skipLE,
3858                                 textLayoutModule->skipLengthCO)
3859                                 );
3860                         bp_.setDefSkip(vs);
3861                         break;
3862                 }
3863                 default:
3864                         // this should never happen
3865                         bp_.setDefSkip(VSpace(VSpace::MEDSKIP));
3866                         break;
3867                 }
3868         }
3869         bp_.tablestyle = fromqstr(textLayoutModule->tableStyleCO->itemData(
3870                                       textLayoutModule->tableStyleCO->currentIndex()).toString());
3871
3872         bp_.options =
3873                 fromqstr(latexModule->optionsLE->text());
3874
3875         bp_.use_default_options =
3876                 latexModule->defaultOptionsCB->isChecked();
3877
3878         if (latexModule->childDocGB->isChecked())
3879                 bp_.master =
3880                         fromqstr(latexModule->childDocLE->text());
3881         else
3882                 bp_.master = string();
3883
3884         // Master/Child
3885         bp_.clearIncludedChildren();
3886         updateIncludeonlys();
3887         if (masterChildModule->includeonlyRB->isChecked()) {
3888                 list<string>::const_iterator it = includeonlys_.begin();
3889                 for (; it != includeonlys_.end() ; ++it) {
3890                         bp_.addIncludedChildren(*it);
3891                 }
3892         }
3893         if (masterChildModule->maintainCRNoneRB->isChecked())
3894                 bp_.maintain_unincluded_children =
3895                         BufferParams::CM_None;
3896         else if (masterChildModule->maintainCRMostlyRB->isChecked())
3897                 bp_.maintain_unincluded_children =
3898                         BufferParams::CM_Mostly;
3899         else
3900                 bp_.maintain_unincluded_children =
3901                         BufferParams::CM_Strict;
3902         updateIncludeonlyDisplay();
3903
3904         // Float Settings
3905         bp_.float_placement = floatModule->getPlacement();
3906         bp_.float_alignment = floatModule->getAlignment();
3907
3908         // Listings
3909         // text should have passed validation
3910         idx = listingsModule->packageCO->currentIndex();
3911         bp_.use_minted = string(lst_packages[idx]) == "Minted";
3912         bp_.listings_params =
3913                 InsetListingsParams(fromqstr(listingsModule->listingsED->toPlainText())).params();
3914
3915         // Formats
3916         bp_.default_output_format = fromqstr(outputModule->defaultFormatCO->itemData(
3917                 outputModule->defaultFormatCO->currentIndex()).toString());
3918
3919         bool const nontexfonts = fontModule->osFontsCB->isChecked();
3920         bp_.useNonTeXFonts = nontexfonts;
3921
3922         bp_.shell_escape = outputModule->shellescapeCB->isChecked();
3923         if (!bp_.shell_escape)
3924             theSession().shellescapeFiles().remove(buffer().absFileName());
3925         else if (!theSession().shellescapeFiles().find(buffer().absFileName()))
3926             theSession().shellescapeFiles().insert(buffer().absFileName());
3927         Buffer & buf = const_cast<Buffer &>(buffer());
3928         buf.params().shell_escape = bp_.shell_escape;
3929
3930         bp_.output_sync = outputModule->outputsyncCB->isChecked();
3931
3932         bp_.output_sync_macro = fromqstr(outputModule->synccustomCB->currentText());
3933
3934         int mathfmt = outputModule->mathoutCB->currentIndex();
3935         if (mathfmt == -1)
3936                 mathfmt = 0;
3937         BufferParams::MathOutput const mo =
3938                 static_cast<BufferParams::MathOutput>(mathfmt);
3939         bp_.html_math_output = mo;
3940         bp_.html_be_strict = outputModule->strictCB->isChecked();
3941         bp_.html_css_as_file = outputModule->cssCB->isChecked();
3942         bp_.html_math_img_scale = outputModule->mathimgSB->value();
3943         bp_.display_pixel_ratio = theGuiApp()->pixelRatio();
3944
3945         int tablefmt = outputModule->tableoutCB->currentIndex();
3946         if (tablefmt == -1)
3947                 tablefmt = 0;
3948         auto const to = static_cast<BufferParams::TableOutput>(tablefmt);
3949         bp_.docbook_table_output = to;
3950
3951         int mathmlprefix = outputModule->mathmlprefixCB->currentIndex();
3952         if (mathmlprefix == -1)
3953                 mathmlprefix = 0;
3954         auto const mp = static_cast<BufferParams::MathMLNameSpacePrefix>(mathmlprefix);
3955         bp_.docbook_mathml_prefix = mp;
3956
3957         bp_.save_transient_properties =
3958                 outputModule->saveTransientPropertiesCB->isChecked();
3959         bp_.postpone_fragile_content =
3960                 outputModule->postponeFragileCB->isChecked();
3961
3962         // fonts
3963         bp_.fonts_roman[nontexfonts] =
3964                 fromqstr(fontModule->fontsRomanCO->
3965                         getData(fontModule->fontsRomanCO->currentIndex()));
3966         bp_.fonts_roman[!nontexfonts] = fromqstr(fontModule->font_roman);
3967         bp_.font_roman_opts = fromqstr(fontModule->fontspecRomanLE->text());
3968
3969         bp_.fonts_sans[nontexfonts] =
3970                 fromqstr(fontModule->fontsSansCO->
3971                         getData(fontModule->fontsSansCO->currentIndex()));
3972         bp_.fonts_sans[!nontexfonts] = fromqstr(fontModule->font_sans);
3973         bp_.font_sans_opts = fromqstr(fontModule->fontspecSansLE->text());
3974
3975         bp_.fonts_typewriter[nontexfonts] =
3976                 fromqstr(fontModule->fontsTypewriterCO->
3977                         getData(fontModule->fontsTypewriterCO->currentIndex()));
3978         bp_.fonts_typewriter[!nontexfonts] = fromqstr(fontModule->font_typewriter);
3979         bp_.font_typewriter_opts = fromqstr(fontModule->fontspecTypewriterLE->text());
3980
3981         bp_.fonts_math[nontexfonts] =
3982                 fromqstr(fontModule->fontsMathCO->
3983                         itemData(fontModule->fontsMathCO->currentIndex()).toString());
3984         bp_.fonts_math[!nontexfonts] = fromqstr(fontModule->font_math);
3985
3986         QString const fontenc =
3987                 fontModule->fontencCO->itemData(fontModule->fontencCO->currentIndex()).toString();
3988         if (fontenc == "custom")
3989                 bp_.fontenc = fromqstr(fontModule->fontencLE->text());
3990         else
3991                 bp_.fontenc = fromqstr(fontenc);
3992
3993         bp_.fonts_cjk =
3994                 fromqstr(fontModule->cjkFontLE->text());
3995
3996         bp_.use_microtype = fontModule->microtypeCB->isChecked();
3997         bp_.use_dash_ligatures = !fontModule->dashesCB->isChecked();
3998
3999         bp_.fonts_sans_scale[nontexfonts] = fontModule->scaleSansSB->value();
4000         bp_.fonts_sans_scale[!nontexfonts] = fontModule->font_sf_scale;
4001
4002         bp_.fonts_typewriter_scale[nontexfonts] = fontModule->scaleTypewriterSB->value();
4003         bp_.fonts_typewriter_scale[!nontexfonts] = fontModule->font_tt_scale;
4004
4005         bp_.fonts_expert_sc = fontModule->fontScCB->isChecked();
4006
4007         bp_.fonts_roman_osf = fontModule->fontOsfCB->isChecked();
4008         bp_.fonts_sans_osf = fontModule->fontSansOsfCB->isChecked();
4009         bp_.fonts_typewriter_osf = fontModule->fontTypewriterOsfCB->isChecked();
4010
4011         bp_.fonts_default_family = GuiDocument::fontfamilies[
4012                 fontModule->fontsDefaultCO->currentIndex()];
4013
4014         if (fontModule->fontsizeCO->currentIndex() == 0)
4015                 bp_.fontsize = "default";
4016         else
4017                 bp_.fontsize =
4018                         fromqstr(fontModule->fontsizeCO->currentText());
4019
4020         // paper
4021         bp_.papersize = PAPER_SIZE(
4022                 pageLayoutModule->papersizeCO->currentIndex());
4023
4024         bp_.paperwidth = widgetsToLength(pageLayoutModule->paperwidthLE,
4025                 pageLayoutModule->paperwidthUnitCO);
4026
4027         bp_.paperheight = widgetsToLength(pageLayoutModule->paperheightLE,
4028                 pageLayoutModule->paperheightUnitCO);
4029
4030         if (pageLayoutModule->facingPagesCB->isChecked())
4031                 bp_.sides = TwoSides;
4032         else
4033                 bp_.sides = OneSide;
4034
4035         if (pageLayoutModule->landscapeRB->isChecked())
4036                 bp_.orientation = ORIENTATION_LANDSCAPE;
4037         else
4038                 bp_.orientation = ORIENTATION_PORTRAIT;
4039
4040         // margins
4041         bp_.use_geometry = !marginsModule->marginCB->isChecked();
4042
4043         Ui::MarginsUi const * m = marginsModule;
4044
4045         if (bp_.use_geometry) {
4046                 bp_.leftmargin = widgetsToLength(m->innerLE, m->innerUnit);
4047                 bp_.topmargin = widgetsToLength(m->topLE, m->topUnit);
4048                 bp_.rightmargin = widgetsToLength(m->outerLE, m->outerUnit);
4049                 bp_.bottommargin = widgetsToLength(m->bottomLE, m->bottomUnit);
4050                 bp_.headheight = widgetsToLength(m->headheightLE, m->headheightUnit);
4051                 bp_.headsep = widgetsToLength(m->headsepLE, m->headsepUnit);
4052                 bp_.footskip = widgetsToLength(m->footskipLE, m->footskipUnit);
4053                 bp_.columnsep = widgetsToLength(m->columnsepLE, m->columnsepUnit);
4054         }
4055
4056         // branches
4057         branchesModule->apply(bp_);
4058
4059         // PDF support
4060         PDFOptions & pdf = bp_.pdfoptions();
4061         pdf.use_hyperref = pdfSupportModule->use_hyperrefGB->isChecked();
4062         pdf.title = fromqstr(pdfSupportModule->titleLE->text());
4063         pdf.author = fromqstr(pdfSupportModule->authorLE->text());
4064         pdf.subject = fromqstr(pdfSupportModule->subjectLE->text());
4065         pdf.keywords = fromqstr(pdfSupportModule->keywordsLE->text());
4066
4067         pdf.bookmarks = pdfSupportModule->bookmarksGB->isChecked();
4068         pdf.bookmarksnumbered = pdfSupportModule->bookmarksnumberedCB->isChecked();
4069         pdf.bookmarksopen = pdfSupportModule->bookmarksopenGB->isChecked();
4070         pdf.bookmarksopenlevel = pdfSupportModule->bookmarksopenlevelSB->value();
4071
4072         pdf.breaklinks = pdfSupportModule->breaklinksCB->isChecked();
4073         pdf.pdfborder = pdfSupportModule->pdfborderCB->isChecked();
4074         pdf.pdfusetitle = pdfSupportModule->pdfusetitleCB->isChecked();
4075         pdf.colorlinks = pdfSupportModule->colorlinksCB->isChecked();
4076         pdf.backref =
4077                 backref_opts[pdfSupportModule->backrefCO->currentIndex()];
4078         if (pdfSupportModule->fullscreenCB->isChecked())
4079                 pdf.pagemode = pdf.pagemode_fullscreen;
4080         else
4081                 pdf.pagemode.clear();
4082         pdf.quoted_options = pdf.quoted_options_check(
4083                                 fromqstr(pdfSupportModule->optionsTE->toPlainText()));
4084         bp_.document_metadata = qstring_to_ucs4(pdfSupportModule->metadataTE->toPlainText()
4085                                                 .trimmed().replace(QRegularExpression("\n+"), "\n"));
4086
4087         // change tracking
4088         bp_.track_changes = changesModule->trackChangesCB->isChecked();
4089         bp_.output_changes = changesModule->outputChangesCB->isChecked();
4090         bool const cb_switched_off = (bp_.change_bars
4091                                       && !changesModule->changeBarsCB->isChecked());
4092         bp_.change_bars = changesModule->changeBarsCB->isChecked();
4093         if (cb_switched_off)
4094                 // if change bars have been switched off,
4095                 // we need to ditch the aux file
4096                 buffer().requireFreshStart(true);
4097
4098         // reset trackers
4099         nonModuleChanged_ = false;
4100         shellescapeChanged_ = false;
4101 }
4102
4103
4104 void GuiDocument::paramsToDialog()
4105 {
4106         // set the default unit
4107         Length::UNIT const default_unit = Length::defaultUnit();
4108
4109         // preamble
4110         preambleModule->update(bp_, id());
4111         localLayout->update(bp_, id());
4112
4113         // date
4114         latexModule->suppressDateCB->setChecked(bp_.suppress_date);
4115         latexModule->refstyleCB->setChecked(bp_.use_refstyle);
4116         latexModule->refFormattedCB->setChecked(bp_.use_formatted_ref);
4117
4118         // biblio
4119         string const cite_engine = bp_.citeEngine();
4120
4121         biblioModule->citeEngineCO->setCurrentIndex(
4122                 biblioModule->citeEngineCO->findData(toqstr(cite_engine)));
4123
4124         updateEngineType(documentClass().opt_enginetype(),
4125                 bp_.citeEngineType());
4126
4127         checkPossibleCiteEngines();
4128
4129         biblioModule->citeStyleCO->setCurrentIndex(
4130                 biblioModule->citeStyleCO->findData(bp_.citeEngineType()));
4131
4132         biblioModule->bibtopicCB->setChecked(bp_.splitbib());
4133
4134         biblioModule->bibunitsCO->clear();
4135         biblioModule->bibunitsCO->addItem(qt_("No"), QString());
4136         if (documentClass().hasLaTeXLayout("part"))
4137                 biblioModule->bibunitsCO->addItem(qt_("per part"), toqstr("part"));
4138         if (documentClass().hasLaTeXLayout("chapter"))
4139                 biblioModule->bibunitsCO->addItem(qt_("per chapter"), toqstr("chapter"));
4140         if (documentClass().hasLaTeXLayout("section"))
4141                 biblioModule->bibunitsCO->addItem(qt_("per section"), toqstr("section"));
4142         if (documentClass().hasLaTeXLayout("subsection"))
4143                 biblioModule->bibunitsCO->addItem(qt_("per subsection"), toqstr("subsection"));
4144         biblioModule->bibunitsCO->addItem(qt_("per child document"), toqstr("child"));
4145
4146         int const mbpos = biblioModule->bibunitsCO->findData(toqstr(bp_.multibib));
4147         if (mbpos != -1)
4148                 biblioModule->bibunitsCO->setCurrentIndex(mbpos);
4149         else
4150                 biblioModule->bibunitsCO->setCurrentIndex(0);
4151
4152         updateEngineDependends();
4153
4154         if (isBiblatex()) {
4155                 updateDefaultBiblio(bp_.biblatex_bibstyle, "bbx");
4156                 updateDefaultBiblio(bp_.biblatex_citestyle, "cbx");
4157         } else
4158                 updateDefaultBiblio(bp_.defaultBiblioStyle());
4159
4160         biblioModule->citePackageOptionsLE->setText(toqstr(bp_.biblio_opts));
4161
4162         string command;
4163         string options =
4164                 split(bp_.bibtex_command, command, ' ');
4165
4166         int bpos = biblioModule->bibtexCO->findData(toqstr(command));
4167         if (bpos == -1) {
4168                 // We add and set the unknown compiler, indicating that it is unavailable
4169                 // to assure document compilation and for security reasons, a fallback
4170                 // will be used on document processing stage
4171                 biblioModule->bibtexCO->addItem(toqstr(bformat(_("%1$s (not available)"),
4172                                                         from_utf8(command))), toqstr(command));
4173                 bpos = biblioModule->bibtexCO->findData(toqstr(command));
4174         }
4175         biblioModule->bibtexCO->setCurrentIndex(bpos);
4176         biblioModule->bibtexOptionsLE->setText(toqstr(options).trimmed());
4177         biblioModule->bibtexOptionsLE->setEnabled(
4178                 biblioModule->bibtexCO->currentIndex() != 0);
4179
4180         biblioChanged_ = false;
4181
4182         // indices
4183         // We may be called when there is no Buffer, e.g., when
4184         // the last view has just been closed.
4185         bool const isReadOnly = isBufferAvailable() ? buffer().isReadonly() : false;
4186         indicesModule->update(bp_, isReadOnly);
4187
4188         // language & quotes
4189         int const pos = langModule->languageCO->findData(toqstr(
4190                 bp_.language->lang()));
4191         langModule->languageCO->setCurrentIndex(pos);
4192
4193         updateQuoteStyles();
4194
4195         langModule->quoteStyleCO->setCurrentIndex(
4196                 langModule->quoteStyleCO->findData(static_cast<int>(bp_.quotes_style)));
4197         langModule->dynamicQuotesCB->setChecked(bp_.dynamic_quotes);
4198
4199         // LaTeX input encoding: set after the fonts (see below)
4200
4201         int p = langModule->languagePackageCO->findData(toqstr(bp_.lang_package));
4202         if (p == -1) {
4203                 langModule->languagePackageCO->setCurrentIndex(
4204                           langModule->languagePackageCO->findData("custom"));
4205                 langModule->languagePackageLE->setText(toqstr(bp_.lang_package));
4206         } else {
4207                 langModule->languagePackageCO->setCurrentIndex(p);
4208                 langModule->languagePackageLE->clear();
4209         }
4210
4211         //color
4212         if (bp_.isfontcolor) {
4213                 colorModule->mainTextCF->setStyleSheet(
4214                         colorFrameStyleSheet(rgb2qcolor(bp_.fontcolor)));
4215                 colorModule->mainTextCF->setVisible(true);
4216         } else
4217                 colorModule->mainTextCF->setVisible(false);
4218         set_fontcolor = bp_.fontcolor;
4219         is_fontcolor = bp_.isfontcolor;
4220
4221         colorModule->noteFontCF->setStyleSheet(
4222                 colorFrameStyleSheet(rgb2qcolor(bp_.notefontcolor)));
4223         set_notefontcolor = bp_.notefontcolor;
4224         is_notefontcolor = bp_.isnotefontcolor;
4225
4226         if (bp_.isbackgroundcolor) {
4227                 colorModule->pageBackgroundCF->setStyleSheet(
4228                         colorFrameStyleSheet(rgb2qcolor(bp_.backgroundcolor)));
4229                 colorModule->pageBackgroundCF->setVisible(true);
4230         } else
4231                 colorModule->pageBackgroundCF->setVisible(false);
4232         set_backgroundcolor = bp_.backgroundcolor;
4233         is_backgroundcolor = bp_.isbackgroundcolor;
4234
4235         colorModule->boxBackgroundCF->setStyleSheet(
4236                 colorFrameStyleSheet(rgb2qcolor(bp_.boxbgcolor)));
4237         set_boxbgcolor = bp_.boxbgcolor;
4238         is_boxbgcolor = bp_.isboxbgcolor;
4239
4240         // numbering
4241         int const min_toclevel = documentClass().min_toclevel();
4242         int const max_toclevel = documentClass().max_toclevel();
4243         if (documentClass().hasTocLevels()) {
4244                 numberingModule->setEnabled(true);
4245                 numberingModule->depthSL->setMinimum(min_toclevel - 1);
4246                 numberingModule->depthSL->setMaximum(max_toclevel);
4247                 numberingModule->depthSL->setValue(bp_.secnumdepth);
4248                 numberingModule->tocSL->setMaximum(min_toclevel - 1);
4249                 numberingModule->tocSL->setMaximum(max_toclevel);
4250                 numberingModule->tocSL->setValue(bp_.tocdepth);
4251                 updateNumbering();
4252         } else {
4253                 numberingModule->setEnabled(false);
4254                 numberingModule->tocTW->clear();
4255         }
4256
4257         numberingModule->linenoCB->setChecked(bp_.use_lineno);
4258         numberingModule->linenoLE->setEnabled(bp_.use_lineno);
4259         numberingModule->linenoLA->setEnabled(bp_.use_lineno);
4260         numberingModule->linenoLE->setText(toqstr(bp_.lineno_opts));
4261
4262         // bullets
4263         bulletsModule->setBullet(0, bp_.user_defined_bullet(0));
4264         bulletsModule->setBullet(1, bp_.user_defined_bullet(1));
4265         bulletsModule->setBullet(2, bp_.user_defined_bullet(2));
4266         bulletsModule->setBullet(3, bp_.user_defined_bullet(3));
4267         bulletsModule->init();
4268
4269         // packages
4270         int nitem = findToken(tex_graphics, bp_.graphics_driver);
4271         if (nitem >= 0)
4272                 latexModule->psdriverCO->setCurrentIndex(nitem);
4273         updateModuleInfo();
4274
4275         // math
4276         mathsModule->MathIndentCB->setChecked(bp_.is_math_indent);
4277         if (bp_.is_math_indent) {
4278                 Length const mathindent = bp_.getMathIndent();
4279                 int indent = 0;
4280                 if (!mathindent.empty()) {
4281                         lengthToWidgets(mathsModule->MathIndentLE,
4282                                         mathsModule->MathIndentLengthCO,
4283                                         mathindent, default_unit);
4284                         indent = 1;
4285                 }
4286                 mathsModule->MathIndentCO->setCurrentIndex(indent);
4287                 enableMathIndent(indent);
4288         }
4289         switch(bp_.math_numbering_side) {
4290         case BufferParams::LEFT:
4291                 mathsModule->MathNumberingPosCO->setCurrentIndex(0);
4292                 break;
4293         case BufferParams::DEFAULT:
4294                 mathsModule->MathNumberingPosCO->setCurrentIndex(1);
4295                 break;
4296         case BufferParams::RIGHT:
4297                 mathsModule->MathNumberingPosCO->setCurrentIndex(2);
4298         }
4299
4300         map<string, string> const & packages = BufferParams::auto_packages();
4301         for (map<string, string>::const_iterator it = packages.begin();
4302              it != packages.end(); ++it) {
4303                 QTableWidgetItem * item = mathsModule->packagesTW->findItems(toqstr(it->first), Qt::MatchExactly)[0];
4304                 if (!item)
4305                         continue;
4306                 int row = mathsModule->packagesTW->row(item);
4307                 switch (bp_.use_package(it->first)) {
4308                         case BufferParams::package_off: {
4309                                 QRadioButton * rb =
4310                                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 3)->layout()->itemAt(0)->widget();
4311                                 rb->setChecked(true);
4312                                 break;
4313                         }
4314                         case BufferParams::package_on: {
4315                                 QRadioButton * rb =
4316                                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 2)->layout()->itemAt(0)->widget();
4317                                 rb->setChecked(true);
4318                                 break;
4319                         }
4320                         case BufferParams::package_auto: {
4321                                 QRadioButton * rb =
4322                                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 1)->layout()->itemAt(0)->widget();
4323                                 rb->setChecked(true);
4324                                 break;
4325                         }
4326                 }
4327         }
4328
4329         switch (bp_.spacing().getSpace()) {
4330                 case Spacing::Other: nitem = 3; break;
4331                 case Spacing::Double: nitem = 2; break;
4332                 case Spacing::Onehalf: nitem = 1; break;
4333                 case Spacing::Default: case Spacing::Single: nitem = 0; break;
4334         }
4335
4336         // text layout
4337         string const & layoutID = bp_.baseClassID();
4338         setLayoutComboByIDString(layoutID);
4339
4340         updatePagestyle(documentClass().opt_pagestyle(),
4341                                  bp_.pagestyle);
4342
4343         textLayoutModule->lspacingCO->setCurrentIndex(nitem);
4344         if (bp_.spacing().getSpace() == Spacing::Other) {
4345                 doubleToWidget(textLayoutModule->lspacingLE,
4346                         bp_.spacing().getValueAsString());
4347         }
4348         setLSpacing(nitem);
4349         int ts = textLayoutModule->tableStyleCO->findData(toqstr(bp_.tablestyle));
4350         if (ts != -1)
4351                 textLayoutModule->tableStyleCO->setCurrentIndex(ts);
4352
4353         if (bp_.paragraph_separation == BufferParams::ParagraphIndentSeparation) {
4354                 textLayoutModule->indentRB->setChecked(true);
4355                 string parindent = bp_.getParIndent().asString();
4356                 QString indent = toqstr("default");
4357                 if (!parindent.empty()) {
4358                         lengthToWidgets(textLayoutModule->indentLE,
4359                                         textLayoutModule->indentLengthCO,
4360                                         parindent, default_unit);
4361                         indent = toqstr("custom");
4362                 }
4363                 textLayoutModule->indentCO->setCurrentIndex(textLayoutModule->indentCO->findData(indent));
4364                 setIndent(textLayoutModule->indentCO->currentIndex());
4365         } else {
4366                 textLayoutModule->skipRB->setChecked(true);
4367                 VSpace::VSpaceKind skip = bp_.getDefSkip().kind();
4368                 textLayoutModule->skipCO->setCurrentIndex(textLayoutModule->skipCO->findData(skip));
4369                 if (skip == VSpace::LENGTH) {
4370                         string const length = bp_.getDefSkip().asLyXCommand();
4371                         lengthToWidgets(textLayoutModule->skipLE,
4372                                 textLayoutModule->skipLengthCO,
4373                                 length, default_unit);
4374                 }
4375                 setSkip(textLayoutModule->skipCO->currentIndex());
4376         }
4377
4378         textLayoutModule->twoColumnCB->setChecked(
4379                 bp_.columns == 2);
4380         textLayoutModule->justCB->setChecked(bp_.justification);
4381
4382         if (!bp_.options.empty()) {
4383                 latexModule->optionsLE->setText(
4384                         toqstr(bp_.options));
4385         } else {
4386                 latexModule->optionsLE->setText(QString());
4387         }
4388
4389         // latex
4390         latexModule->defaultOptionsCB->setChecked(
4391                         bp_.use_default_options);
4392         updateSelectedModules();
4393         selectionManager->updateProvidedModules(
4394                         bp_.baseClass()->providedModules());
4395         selectionManager->updateExcludedModules(
4396                         bp_.baseClass()->excludedModules());
4397
4398         if (!documentClass().options().empty()) {
4399                 latexModule->defaultOptionsLE->setText(
4400                         toqstr(documentClass().options()));
4401         } else {
4402                 latexModule->defaultOptionsLE->setText(
4403                         toqstr(_("[No options predefined]")));
4404         }
4405
4406         latexModule->defaultOptionsLE->setEnabled(
4407                 bp_.use_default_options
4408                 && !documentClass().options().empty());
4409
4410         latexModule->defaultOptionsCB->setEnabled(
4411                 !documentClass().options().empty());
4412
4413         if (!bp_.master.empty()) {
4414                 latexModule->childDocGB->setChecked(true);
4415                 latexModule->childDocLE->setText(
4416                         toqstr(bp_.master));
4417         } else {
4418                 latexModule->childDocLE->setText(QString());
4419                 latexModule->childDocGB->setChecked(false);
4420         }
4421
4422         // Master/Child
4423         if (!bufferview() || !buffer().hasChildren()) {
4424                 masterChildModule->childrenTW->clear();
4425                 includeonlys_.clear();
4426                 docPS->showPanel("Child Documents", false);
4427                 if (docPS->isCurrentPanel("Child Documents"))
4428                         docPS->setCurrentPanel("Document Class");
4429         } else {
4430                 docPS->showPanel("Child Documents", true);
4431                 masterChildModule->setEnabled(true);
4432                 includeonlys_ = bp_.getIncludedChildren();
4433                 updateIncludeonlys();
4434                 updateIncludeonlyDisplay();
4435         }
4436         switch (bp_.maintain_unincluded_children) {
4437         case BufferParams::CM_None:
4438                 masterChildModule->maintainCRNoneRB->setChecked(true);
4439                 break;
4440         case BufferParams::CM_Mostly:
4441                 masterChildModule->maintainCRMostlyRB->setChecked(true);
4442                 break;
4443         case BufferParams::CM_Strict:
4444         default:
4445                 masterChildModule->maintainCRStrictRB->setChecked(true);
4446                 break;
4447         }
4448
4449         // Float Settings
4450         floatModule->setPlacement(bp_.float_placement);
4451         floatModule->setAlignment(bp_.float_alignment);
4452
4453         // ListingsSettings
4454         // break listings_params to multiple lines
4455         string lstparams =
4456                 InsetListingsParams(bp_.listings_params).separatedParams();
4457         listingsModule->listingsED->setPlainText(toqstr(lstparams));
4458         int nn = findToken(lst_packages, bp_.use_minted ? "Minted" : "Listings");
4459         if (nn >= 0)
4460                 listingsModule->packageCO->setCurrentIndex(nn);
4461
4462         // Fonts
4463         // some languages only work with Polyglossia (which requires non-TeX fonts)
4464         Language const * lang = lyx::languages.getLanguage(
4465                 fromqstr(langModule->languageCO->itemData(
4466                         langModule->languageCO->currentIndex()).toString()));
4467         bool const need_fontspec =
4468                 lang->babel().empty() && !lang->polyglossia().empty()
4469                 && lang->required() != "CJK" && lang->required() != "japanese";
4470         bool const os_fonts_available =
4471                 bp_.baseClass()->outputType() == lyx::LATEX
4472                 && LaTeXFeatures::isAvailable("fontspec");
4473         fontModule->osFontsCB->setEnabled(os_fonts_available && !need_fontspec);
4474         fontModule->osFontsCB->setChecked(
4475                 (os_fonts_available && bp_.useNonTeXFonts) || need_fontspec);
4476         updateFontsize(documentClass().opt_fontsize(),
4477                         bp_.fontsize);
4478
4479         QString font = toqstr(bp_.fontsRoman());
4480         bool foundfont = fontModule->fontsRomanCO->set(font, false);
4481         if (!foundfont) {
4482                 fontModule->fontsRomanCO->addItemSort(font, font + qt_(" (not installed)"),
4483                                                       qt_("Uninstalled used fonts"),
4484                                                       qt_("This font is not installed and won't be used in output"),
4485                                                       false, false, false, true);
4486                 fontModule->fontsRomanCO->set(font);
4487         }
4488         fontModule->font_roman = toqstr(bp_.fonts_roman[!bp_.useNonTeXFonts]);
4489
4490         font = toqstr(bp_.fontsSans());
4491         foundfont = fontModule->fontsSansCO->set(font, false);
4492         if (!foundfont) {
4493                 fontModule->fontsSansCO->addItemSort(font, font + qt_(" (not installed)"),
4494                                                      qt_("Uninstalled used fonts"),
4495                                                      qt_("This font is not installed and won't be used in output"),
4496                                                      false, false, false, true);
4497                 fontModule->fontsSansCO->set(font);
4498         }
4499         fontModule->font_sans = toqstr(bp_.fonts_sans[!bp_.useNonTeXFonts]);
4500
4501         font = toqstr(bp_.fontsTypewriter());
4502         foundfont = fontModule->fontsTypewriterCO->set(font, false);
4503         if (!foundfont) {
4504                 fontModule->fontsTypewriterCO->addItemSort(font, font + qt_(" (not installed)"),
4505                                                            qt_("Uninstalled used fonts"),
4506                                                            qt_("This font is not installed and won't be used in output"),
4507                                                            false, false, false, true);
4508                 fontModule->fontsTypewriterCO->set(font);
4509         }
4510         fontModule->font_typewriter = toqstr(bp_.fonts_typewriter[!bp_.useNonTeXFonts]);
4511
4512         font = toqstr(bp_.fontsMath());
4513         int mpos = fontModule->fontsMathCO->findData(font);
4514         if (mpos == -1) {
4515                 mpos = fontModule->fontsMathCO->count();
4516                 fontModule->fontsMathCO->addItem(font + qt_(" (not installed)"), font);
4517         }
4518         fontModule->fontsMathCO->setCurrentIndex(mpos);
4519         fontModule->font_math = toqstr(bp_.fonts_math[!bp_.useNonTeXFonts]);
4520
4521         if (bp_.useNonTeXFonts && os_fonts_available) {
4522                 fontModule->fontencLA->setEnabled(false);
4523                 fontModule->fontencCO->setEnabled(false);
4524                 fontModule->fontencLE->setEnabled(false);
4525         } else {
4526                 fontModule->fontencLA->setEnabled(true);
4527                 fontModule->fontencCO->setEnabled(true);
4528                 fontModule->fontencLE->setEnabled(true);
4529                 romanChanged(fontModule->fontsRomanCO->currentIndex());
4530                 sansChanged(fontModule->fontsSansCO->currentIndex());
4531                 ttChanged(fontModule->fontsTypewriterCO->currentIndex());
4532         }
4533         // Handle options enabling
4534         updateFontOptions();
4535
4536         if (!bp_.fonts_cjk.empty())
4537                 fontModule->cjkFontLE->setText(
4538                         toqstr(bp_.fonts_cjk));
4539         else
4540                 fontModule->cjkFontLE->setText(QString());
4541
4542         fontModule->microtypeCB->setChecked(bp_.use_microtype);
4543         fontModule->dashesCB->setChecked(!bp_.use_dash_ligatures);
4544
4545         fontModule->fontScCB->setChecked(bp_.fonts_expert_sc);
4546         fontModule->fontOsfCB->setChecked(bp_.fonts_roman_osf);
4547         fontModule->fontSansOsfCB->setChecked(bp_.fonts_sans_osf);
4548         fontModule->fontTypewriterOsfCB->setChecked(bp_.fonts_typewriter_osf);
4549         fontModule->scaleSansSB->setValue(bp_.fontsSansScale());
4550         fontModule->font_sf_scale = bp_.fonts_sans_scale[!bp_.useNonTeXFonts];
4551         fontModule->scaleTypewriterSB->setValue(bp_.fontsTypewriterScale());
4552         fontModule->font_tt_scale = bp_.fonts_typewriter_scale[!bp_.useNonTeXFonts];
4553         if (!bp_.font_roman_opts.empty())
4554                 fontModule->fontspecRomanLE->setText(
4555                         toqstr(bp_.font_roman_opts));
4556         else
4557                 fontModule->fontspecRomanLE->setText(QString());
4558         if (!bp_.font_sans_opts.empty())
4559                 fontModule->fontspecSansLE->setText(
4560                         toqstr(bp_.font_sans_opts));
4561         else
4562                 fontModule->fontspecSansLE->setText(QString());
4563         if (!bp_.font_typewriter_opts.empty())
4564                 fontModule->fontspecTypewriterLE->setText(
4565                         toqstr(bp_.font_typewriter_opts));
4566         else
4567                 fontModule->fontspecTypewriterLE->setText(QString());
4568
4569         nn = findToken(GuiDocument::fontfamilies, bp_.fonts_default_family);
4570         if (nn >= 0)
4571                 fontModule->fontsDefaultCO->setCurrentIndex(nn);
4572
4573         if (bp_.fontenc == "auto" || bp_.fontenc == "default") {
4574                 fontModule->fontencCO->setCurrentIndex(
4575                         fontModule->fontencCO->findData(toqstr(bp_.fontenc)));
4576                 fontModule->fontencLE->setEnabled(false);
4577         } else {
4578                 fontModule->fontencCO->setCurrentIndex(
4579                                         fontModule->fontencCO->findData("custom"));
4580                 fontModule->fontencLE->setText(toqstr(bp_.fontenc));
4581         }
4582
4583         // LaTeX input encoding
4584         // Set after fonts because non-tex fonts override "\inputencoding".
4585         inputencodingToDialog();
4586
4587         // Formats
4588         // This must be set _after_ fonts since updateDefaultFormat()
4589         // checks osFontsCB settings.
4590         // update combobox with formats
4591         updateDefaultFormat();
4592         int index = outputModule->defaultFormatCO->findData(toqstr(
4593                 bp_.default_output_format));
4594         // set to default if format is not found
4595         if (index == -1)
4596                 index = 0;
4597         outputModule->defaultFormatCO->setCurrentIndex(index);
4598
4599         outputModule->shellescapeCB->setChecked(bp_.shell_escape);
4600         outputModule->outputsyncCB->setChecked(bp_.output_sync);
4601         outputModule->synccustomCB->setEditText(toqstr(bp_.output_sync_macro));
4602         outputModule->synccustomCB->setEnabled(bp_.output_sync);
4603         outputModule->synccustomLA->setEnabled(bp_.output_sync);
4604
4605         outputModule->mathimgSB->setValue(bp_.html_math_img_scale);
4606         outputModule->mathoutCB->setCurrentIndex(bp_.html_math_output);
4607         outputModule->strictCB->setChecked(bp_.html_be_strict);
4608         outputModule->cssCB->setChecked(bp_.html_css_as_file);
4609
4610         outputModule->tableoutCB->setCurrentIndex(bp_.docbook_table_output);
4611         outputModule->mathmlprefixCB->setCurrentIndex(bp_.docbook_mathml_prefix);
4612
4613         outputModule->saveTransientPropertiesCB
4614                 ->setChecked(bp_.save_transient_properties);
4615         outputModule->postponeFragileCB
4616                 ->setChecked(bp_.postpone_fragile_content);
4617
4618         // paper
4619         bool const extern_geometry =
4620                 documentClass().provides("geometry");
4621         int const psize = bp_.papersize;
4622         pageLayoutModule->papersizeCO->setCurrentIndex(psize);
4623         setCustomPapersize(!extern_geometry && psize == 1);
4624         pageLayoutModule->papersizeCO->setEnabled(!extern_geometry);
4625
4626         bool const landscape =
4627                 bp_.orientation == ORIENTATION_LANDSCAPE;
4628         pageLayoutModule->landscapeRB->setChecked(landscape);
4629         pageLayoutModule->portraitRB->setChecked(!landscape);
4630         pageLayoutModule->landscapeRB->setEnabled(!extern_geometry);
4631         pageLayoutModule->portraitRB->setEnabled(!extern_geometry);
4632
4633         pageLayoutModule->facingPagesCB->setChecked(
4634                 bp_.sides == TwoSides);
4635
4636         lengthToWidgets(pageLayoutModule->paperwidthLE,
4637                 pageLayoutModule->paperwidthUnitCO, bp_.paperwidth, default_unit);
4638         lengthToWidgets(pageLayoutModule->paperheightLE,
4639                 pageLayoutModule->paperheightUnitCO, bp_.paperheight, default_unit);
4640
4641         // margins
4642         Ui::MarginsUi * m = marginsModule;
4643
4644         tmp_leftmargin_ = bp_.leftmargin;
4645         tmp_topmargin_ = bp_.topmargin;
4646         tmp_rightmargin_ = bp_.rightmargin;
4647         tmp_bottommargin_ = bp_.bottommargin;
4648         tmp_headheight_ = bp_.headheight;
4649         tmp_headsep_ = bp_.headsep;
4650         tmp_footskip_ = bp_.footskip;
4651         tmp_columnsep_ = bp_.columnsep;
4652
4653         lengthToWidgets(m->topLE, m->topUnit,
4654                 bp_.topmargin, default_unit);
4655         lengthToWidgets(m->bottomLE, m->bottomUnit,
4656                 bp_.bottommargin, default_unit);
4657         lengthToWidgets(m->innerLE, m->innerUnit,
4658                 bp_.leftmargin, default_unit);
4659         lengthToWidgets(m->outerLE, m->outerUnit,
4660                 bp_.rightmargin, default_unit);
4661         lengthToWidgets(m->headheightLE, m->headheightUnit,
4662                 bp_.headheight, default_unit);
4663         lengthToWidgets(m->headsepLE, m->headsepUnit,
4664                 bp_.headsep, default_unit);
4665         lengthToWidgets(m->footskipLE, m->footskipUnit,
4666                 bp_.footskip, default_unit);
4667         lengthToWidgets(m->columnsepLE, m->columnsepUnit,
4668                 bp_.columnsep, default_unit);
4669
4670         setMargins();
4671
4672         // branches
4673         updateUnknownBranches();
4674         branchesModule->update(bp_);
4675
4676         // PDF support
4677         PDFOptions const & pdf = bp_.pdfoptions();
4678         pdfSupportModule->use_hyperrefGB->setChecked(pdf.use_hyperref);
4679         if (bp_.documentClass().provides("hyperref"))
4680                 pdfSupportModule->use_hyperrefGB->setTitle(qt_("C&ustomize Hyperref Options"));
4681         else
4682                 pdfSupportModule->use_hyperrefGB->setTitle(qt_("&Use Hyperref Support"));
4683         pdfSupportModule->titleLE->setText(toqstr(pdf.title));
4684         pdfSupportModule->authorLE->setText(toqstr(pdf.author));
4685         pdfSupportModule->subjectLE->setText(toqstr(pdf.subject));
4686         pdfSupportModule->keywordsLE->setText(toqstr(pdf.keywords));
4687
4688         pdfSupportModule->bookmarksGB->setChecked(pdf.bookmarks);
4689         pdfSupportModule->bookmarksnumberedCB->setChecked(pdf.bookmarksnumbered);
4690         pdfSupportModule->bookmarksopenGB->setChecked(pdf.bookmarksopen);
4691
4692         pdfSupportModule->bookmarksopenlevelSB->setValue(pdf.bookmarksopenlevel);
4693         pdfSupportModule->bookmarksopenlevelSB->setEnabled(pdf.bookmarksopen);
4694         pdfSupportModule->bookmarksopenlevelLA->setEnabled(pdf.bookmarksopen);
4695
4696         pdfSupportModule->breaklinksCB->setChecked(pdf.breaklinks);
4697         pdfSupportModule->pdfborderCB->setChecked(pdf.pdfborder);
4698         pdfSupportModule->pdfusetitleCB->setChecked(pdf.pdfusetitle);
4699         pdfSupportModule->colorlinksCB->setChecked(pdf.colorlinks);
4700
4701         nn = findToken(backref_opts, pdf.backref);
4702         if (nn >= 0)
4703                 pdfSupportModule->backrefCO->setCurrentIndex(nn);
4704
4705         pdfSupportModule->fullscreenCB->setChecked
4706                 (pdf.pagemode == pdf.pagemode_fullscreen);
4707
4708         pdfSupportModule->optionsTE->setPlainText(
4709                 toqstr(pdf.quoted_options));
4710
4711         pdfSupportModule->metadataTE->setPlainText(
4712                 toqstr(rtrim(bp_.document_metadata, "\n")));
4713
4714         // change tracking
4715         changesModule->trackChangesCB->setChecked(bp_.track_changes);
4716         changesModule->outputChangesCB->setChecked(bp_.output_changes);
4717         changesModule->changeBarsCB->setChecked(bp_.change_bars);
4718         changesModule->changeBarsCB->setEnabled(bp_.output_changes);
4719
4720         // Make sure that the bc is in the INITIAL state
4721         if (bc().policy().buttonStatus(ButtonPolicy::RESTORE))
4722                 bc().restore();
4723
4724         // clear changed branches cache
4725         changedBranches_.clear();
4726
4727         // re-initiate module filter
4728         if (!filter_->text().isEmpty())
4729                 moduleFilterPressed();
4730
4731         // reset trackers
4732         nonModuleChanged_ = false;
4733         shellescapeChanged_ = false;
4734 }
4735
4736
4737 void GuiDocument::saveDocDefault()
4738 {
4739         // we have to apply the params first
4740         applyView();
4741         saveAsDefault();
4742 }
4743
4744
4745 void GuiDocument::updateAvailableModules()
4746 {
4747         modules_av_model_.clear();
4748         list<modInfoStruct> modInfoList = getModuleInfo();
4749         // Sort names according to the locale
4750         modInfoList.sort([](modInfoStruct const & a, modInfoStruct const & b) {
4751                         return 0 < b.name.localeAwareCompare(a.name);
4752                 });
4753         QIcon user_icon(guiApp ? guiApp->getScaledPixmap("images/", "lyxfiles-user")
4754                                : getPixmap("images/", "lyxfiles-user", "svgz,png"));
4755         QIcon system_icon(guiApp ? guiApp->getScaledPixmap("images/", "lyxfiles-system")
4756                                  : getPixmap("images/", "lyxfiles-system", "svgz,png"));
4757         int i = 0;
4758         QFont catfont;
4759         catfont.setBold(true);
4760         QBrush unavbrush;
4761         unavbrush.setColor(Qt::gray);
4762         for (modInfoStruct const & m : modInfoList) {
4763                 QStandardItem * item = new QStandardItem();
4764                 QStandardItem * catItem;
4765                 QString const catname = m.category;
4766                 QList<QStandardItem *> fcats = modules_av_model_.findItems(catname, Qt::MatchExactly);
4767                 if (!fcats.empty())
4768                         catItem = fcats.first();
4769                 else {
4770                         catItem = new QStandardItem();
4771                         catItem->setText(catname);
4772                         catItem->setFont(catfont);
4773                         modules_av_model_.insertRow(i, catItem);
4774                         ++i;
4775                 }
4776                 item->setEditable(false);
4777                 catItem->setEditable(false);
4778                 item->setData(m.name, Qt::DisplayRole);
4779                 if (m.missingreqs)
4780                         item->setForeground(unavbrush);
4781                 item->setData(toqstr(m.id), Qt::UserRole);
4782                 item->setData(m.description, Qt::ToolTipRole);
4783                 if (m.local)
4784                         item->setIcon(user_icon);
4785                 else
4786                         item->setIcon(system_icon);
4787                 catItem->appendRow(item);
4788         }
4789         modules_av_model_.sort(0);
4790 }
4791
4792
4793 void GuiDocument::updateSelectedModules()
4794 {
4795         modules_sel_model_.clear();
4796         list<modInfoStruct> const selModList = getSelectedModules();
4797         int i = 0;
4798         for (modInfoStruct const & m : selModList) {
4799                 modules_sel_model_.insertRow(i, m.name, m.id, m.description);
4800                 ++i;
4801         }
4802 }
4803
4804
4805 void GuiDocument::updateIncludeonlyDisplay()
4806 {
4807         if (includeonlys_.empty()) {
4808                 masterChildModule->includeallRB->setChecked(true);
4809                 masterChildModule->childrenTW->setEnabled(false);
4810                 masterChildModule->maintainGB->setEnabled(false);
4811         } else {
4812                 masterChildModule->includeonlyRB->setChecked(true);
4813                 masterChildModule->childrenTW->setEnabled(true);
4814                 masterChildModule->maintainGB->setEnabled(true);
4815         }
4816 }
4817
4818
4819 void GuiDocument::updateIncludeonlys(bool const cleanup)
4820 {
4821         masterChildModule->childrenTW->clear();
4822         QString const no = qt_("No");
4823         QString const yes = qt_("Yes");
4824
4825         ListOfBuffers children = buffer().getChildren();
4826         ListOfBuffers::const_iterator it  = children.begin();
4827         ListOfBuffers::const_iterator end = children.end();
4828         bool has_unincluded = false;
4829         bool all_unincluded = true;
4830         for (; it != end; ++it) {
4831                 QTreeWidgetItem * item = new QTreeWidgetItem(masterChildModule->childrenTW);
4832                 // FIXME Unicode
4833                 string const name =
4834                         to_utf8(makeRelPath(from_utf8((*it)->fileName().absFileName()),
4835                                                         from_utf8(buffer().filePath())));
4836                 item->setText(0, toqstr(name));
4837                 item->setText(1, isChildIncluded(name) ? yes : no);
4838                 if (!isChildIncluded(name))
4839                         has_unincluded = true;
4840                 else
4841                         all_unincluded = false;
4842         }
4843         // Both if all children are included and if none is included
4844         // is equal to "include all" (i.e., omit \includeonly).
4845         if (cleanup && (!has_unincluded || all_unincluded))
4846                 includeonlys_.clear();
4847 }
4848
4849
4850 bool GuiDocument::isBiblatex() const
4851 {
4852         QString const engine =
4853                 biblioModule->citeEngineCO->itemData(
4854                                 biblioModule->citeEngineCO->currentIndex()).toString();
4855
4856         // this can happen if the cite engine is unknown, which can happen
4857         // if one is using a file that came from someone else, etc. in that
4858         // case, we crash if we proceed.
4859         if (engine.isEmpty())
4860             return false;
4861
4862         return theCiteEnginesList[fromqstr(engine)]->getCiteFramework() == "biblatex";
4863 }
4864
4865
4866 void GuiDocument::updateDefaultBiblio(string const & style,
4867                                       string const & which)
4868 {
4869         QString const bibstyle = toqstr(style);
4870         biblioModule->defaultBiblioCO->clear();
4871
4872         int item_nr = -1;
4873
4874         if (isBiblatex()) {
4875                 if (which != "cbx") {
4876                         // First the bbx styles
4877                         biblioModule->biblatexBbxCO->clear();
4878                         QStringList str = texFileList("bbxFiles.lst");
4879                         // test whether we have a valid list, otherwise run rescan
4880                         if (str.isEmpty()) {
4881                                 rescanTexStyles("bbx");
4882                                 str = texFileList("bbxFiles.lst");
4883                         }
4884                         for (int i = 0; i != str.size(); ++i)
4885                                 str[i] = onlyFileName(str[i]);
4886                         // sort on filename only (no path)
4887                         str.sort();
4888
4889                         for (int i = 0; i != str.count(); ++i) {
4890                                 QString item = changeExtension(str[i], "");
4891                                 if (item == bibstyle)
4892                                         item_nr = i;
4893                                 biblioModule->biblatexBbxCO->addItem(item);
4894                         }
4895
4896                         if (item_nr == -1 && !bibstyle.isEmpty()) {
4897                                 biblioModule->biblatexBbxCO->addItem(bibstyle);
4898                                 item_nr = biblioModule->biblatexBbxCO->count() - 1;
4899                         }
4900
4901                         if (item_nr != -1)
4902                                 biblioModule->biblatexBbxCO->setCurrentIndex(item_nr);
4903                         else
4904                                 biblioModule->biblatexBbxCO->clearEditText();
4905                 }
4906
4907                 if (which != "bbx") {
4908                         // now the cbx styles
4909                         biblioModule->biblatexCbxCO->clear();
4910                         QStringList str = texFileList("cbxFiles.lst");
4911                         // test whether we have a valid list, otherwise run rescan
4912                         if (str.isEmpty()) {
4913                                 rescanTexStyles("cbx");
4914                                 str = texFileList("cbxFiles.lst");
4915                         }
4916                         for (int i = 0; i != str.size(); ++i)
4917                                 str[i] = onlyFileName(str[i]);
4918                         // sort on filename only (no path)
4919                         str.sort();
4920
4921                         for (int i = 0; i != str.count(); ++i) {
4922                                 QString item = changeExtension(str[i], "");
4923                                 if (item == bibstyle)
4924                                         item_nr = i;
4925                                 biblioModule->biblatexCbxCO->addItem(item);
4926                         }
4927
4928                         if (item_nr == -1 && !bibstyle.isEmpty()) {
4929                                 biblioModule->biblatexCbxCO->addItem(bibstyle);
4930                                 item_nr = biblioModule->biblatexCbxCO->count() - 1;
4931                         }
4932
4933                         if (item_nr != -1)
4934                                 biblioModule->biblatexCbxCO->setCurrentIndex(item_nr);
4935                         else
4936                                 biblioModule->biblatexCbxCO->clearEditText();
4937                 }
4938         } else {// BibTeX
4939                 biblioModule->biblatexBbxCO->clear();
4940                 biblioModule->biblatexCbxCO->clear();
4941                 QStringList str = texFileList("bstFiles.lst");
4942                 // test whether we have a valid list, otherwise run rescan
4943                 if (str.isEmpty()) {
4944                         rescanTexStyles("bst");
4945                         str = texFileList("bstFiles.lst");
4946                 }
4947                 for (int i = 0; i != str.size(); ++i)
4948                         str[i] = onlyFileName(str[i]);
4949                 // sort on filename only (no path)
4950                 str.sort();
4951
4952                 for (int i = 0; i != str.count(); ++i) {
4953                         QString item = changeExtension(str[i], "");
4954                         if (item == bibstyle)
4955                                 item_nr = i;
4956                         biblioModule->defaultBiblioCO->addItem(item);
4957                 }
4958
4959                 if (item_nr == -1 && !bibstyle.isEmpty()) {
4960                         biblioModule->defaultBiblioCO->addItem(bibstyle);
4961                         item_nr = biblioModule->defaultBiblioCO->count() - 1;
4962                 }
4963
4964                 if (item_nr != -1)
4965                         biblioModule->defaultBiblioCO->setCurrentIndex(item_nr);
4966                 else
4967                         biblioModule->defaultBiblioCO->clearEditText();
4968         }
4969
4970         updateResetDefaultBiblio();
4971 }
4972
4973
4974 void GuiDocument::updateResetDefaultBiblio()
4975 {
4976         QString const engine =
4977                 biblioModule->citeEngineCO->itemData(
4978                                 biblioModule->citeEngineCO->currentIndex()).toString();
4979         CiteEngineType const cet =
4980                 CiteEngineType(biblioModule->citeStyleCO->itemData(
4981                                                           biblioModule->citeStyleCO->currentIndex()).toInt());
4982
4983         string const defbib = theCiteEnginesList[fromqstr(engine)]->getDefaultBiblio(cet);
4984         if (isBiblatex()) {
4985                 QString const bbx = biblioModule->biblatexBbxCO->currentText();
4986                 QString const cbx = biblioModule->biblatexCbxCO->currentText();
4987                 biblioModule->resetCbxPB->setEnabled(defbib != fromqstr(cbx));
4988                 biblioModule->resetBbxPB->setEnabled(defbib != fromqstr(bbx));
4989                 biblioModule->matchBbxPB->setEnabled(bbx != cbx && !cbx.isEmpty()
4990                         && biblioModule->biblatexBbxCO->findText(cbx) != -1);
4991         } else
4992                 biblioModule->resetDefaultBiblioPB->setEnabled(
4993                         defbib != fromqstr(biblioModule->defaultBiblioCO->currentText()));
4994 }
4995
4996
4997 void GuiDocument::matchBiblatexStyles()
4998 {
4999         updateDefaultBiblio(fromqstr(biblioModule->biblatexCbxCO->currentText()), "bbx");
5000         biblioChanged();
5001 }
5002
5003
5004 void GuiDocument::updateContents()
5005 {
5006         // Nothing to do here as the document settings is not cursor dependent.
5007         return;
5008 }
5009
5010
5011 void GuiDocument::useClassDefaults()
5012 {
5013         if (buttonBox->button(QDialogButtonBox::Apply)->isEnabled()) {
5014                 int const ret = Alert::prompt(_("Unapplied changes"),
5015                                 _("Some changes in the dialog were not yet applied.\n"
5016                                   "If you do not apply now, they will be lost after this action."),
5017                                 1, 1, _("&Apply"), _("&Dismiss"));
5018                 if (ret == 0)
5019                         applyView();
5020         }
5021
5022         int idx = latexModule->classCO->currentIndex();
5023         string const classname = fromqstr(latexModule->classCO->getData(idx));
5024         if (!bp_.setBaseClass(classname, buffer().layoutPos())) {
5025                 Alert::error(_("Error"), _("Unable to set document class."));
5026                 return;
5027         }
5028         bp_.useClassDefaults();
5029         paramsToDialog();
5030         changed();
5031 }
5032
5033
5034 void GuiDocument::setLayoutComboByIDString(string const & idString)
5035 {
5036         if (!latexModule->classCO->set(toqstr(idString)))
5037                 Alert::warning(_("Can't set layout!"),
5038                         bformat(_("Unable to set layout for ID: %1$s"), from_utf8(idString)));
5039 }
5040
5041
5042 bool GuiDocument::isValid()
5043 {
5044         bool const listings_valid = validateListingsParameters().isEmpty();
5045         bool const local_layout_valid = !localLayout->editing();
5046         bool const preamble_valid = !preambleModule->editing();
5047
5048         docPS->markPanelValid(N_("Listings[[inset]]"), listings_valid);
5049         docPS->markPanelValid(N_("Local Layout"), local_layout_valid && localLayout->isValid());
5050         docPS->markPanelValid(N_("LaTeX Preamble"), preamble_valid);
5051         
5052         return listings_valid && local_layout_valid && preamble_valid;
5053 }
5054
5055
5056 char const * const GuiDocument::fontfamilies[5] = {
5057         "default", "rmdefault", "sfdefault", "ttdefault", ""
5058 };
5059
5060
5061 char const * GuiDocument::fontfamilies_gui[5] = {
5062         N_("Default"), N_("Roman"), N_("Sans Serif"), N_("Typewriter"), ""
5063 };
5064
5065
5066 bool GuiDocument::initialiseParams(string const &)
5067 {
5068         BufferView const * view = bufferview();
5069         if (!view) {
5070                 bp_ = BufferParams();
5071                 paramsToDialog();
5072                 return true;
5073         }
5074         prev_buffer_filename_ = view->buffer().absFileName();
5075         bp_ = view->buffer().params();
5076         loadModuleInfo();
5077         updateAvailableModules();
5078         //FIXME It'd be nice to make sure here that the selected
5079         //modules are consistent: That required modules are actually
5080         //selected, and that we don't have conflicts. If so, we could
5081         //at least pop up a warning.
5082         paramsToDialog();
5083         return true;
5084 }
5085
5086
5087 void GuiDocument::clearParams()
5088 {
5089         bp_ = BufferParams();
5090 }
5091
5092
5093 BufferId GuiDocument::id() const
5094 {
5095         BufferView const * const view = bufferview();
5096         return view? &view->buffer() : nullptr;
5097 }
5098
5099
5100 list<GuiDocument::modInfoStruct> const & GuiDocument::getModuleInfo()
5101 {
5102         return moduleNames_;
5103 }
5104
5105
5106 list<GuiDocument::modInfoStruct> const
5107 GuiDocument::makeModuleInfo(LayoutModuleList const & mods)
5108 {
5109         list<modInfoStruct> mInfo;
5110         for (string const & name : mods) {
5111                 modInfoStruct m;
5112                 LyXModule const * const mod = theModuleList[name];
5113                 if (mod)
5114                         m = modInfo(*mod);
5115                 else {
5116                         m.id = name;
5117                         m.name = toqstr(name + " (") + qt_("Not Found") + toqstr(")");
5118                         m.local = false;
5119                         m.missingreqs = true;
5120                 }
5121                 mInfo.push_back(m);
5122         }
5123         return mInfo;
5124 }
5125
5126
5127 list<GuiDocument::modInfoStruct> const GuiDocument::getSelectedModules()
5128 {
5129         return makeModuleInfo(params().getModules());
5130 }
5131
5132
5133 list<GuiDocument::modInfoStruct> const GuiDocument::getProvidedModules()
5134 {
5135         return makeModuleInfo(params().baseClass()->providedModules());
5136 }
5137
5138
5139 DocumentClass const & GuiDocument::documentClass() const
5140 {
5141         return bp_.documentClass();
5142 }
5143
5144
5145 static void dispatch_bufferparams(Dialog const & dialog,
5146         BufferParams const & bp, FuncCode lfun, Buffer const * buf)
5147 {
5148         ostringstream ss;
5149         ss << "\\begin_header\n";
5150         bp.writeFile(ss, buf);
5151         ss << "\\end_header\n";
5152         dialog.dispatch(FuncRequest(lfun, ss.str()));
5153 }
5154
5155
5156 void GuiDocument::dispatchParams()
5157 {
5158         // We need a non-const buffer object.
5159         Buffer & buf = const_cast<BufferView *>(bufferview())->buffer();
5160         // There may be several undo records; group them (bug #8998)
5161         // This handles undo groups automagically
5162         UndoGroupHelper ugh(&buf);
5163
5164         // This must come first so that a language change is correctly noticed
5165         setLanguage();
5166
5167         // We need to load the master before we formally update the params,
5168         // since otherwise we run updateBuffer, etc, before the child's master
5169         // has been set.
5170         if (!params().master.empty()) {
5171                 FileName const master_file = support::makeAbsPath(params().master,
5172                            support::onlyPath(buffer().absFileName()));
5173                 if (isLyXFileName(master_file.absFileName())) {
5174                         Buffer * master = checkAndLoadLyXFile(master_file, true);
5175                         if (master) {
5176                                 if (master->isChild(const_cast<Buffer *>(&buffer())))
5177                                         const_cast<Buffer &>(buffer()).setParent(master);
5178                                 else
5179                                         Alert::warning(_("Assigned master does not include this file"),
5180                                                 bformat(_("You must include this file in the document\n"
5181                                                           "'%1$s' in order to use the master document\n"
5182                                                           "feature."), from_utf8(params().master)));
5183                         } else
5184                                 Alert::warning(_("Could not load master"),
5185                                                 bformat(_("The master document '%1$s'\n"
5186                                                            "could not be loaded."),
5187                                                            from_utf8(params().master)));
5188                 }
5189         }
5190
5191         // Apply the BufferParams. Note that this will set the base class
5192         // and then update the buffer's layout.
5193         dispatch_bufferparams(*this, params(), LFUN_BUFFER_PARAMS_APPLY, &buffer());
5194
5195         // Generate the colours requested by each new branch.
5196         BranchList & branchlist = params().branchlist();
5197         if (!branchlist.empty()) {
5198                 BranchList::const_iterator it = branchlist.begin();
5199                 BranchList::const_iterator const end = branchlist.end();
5200                 for (; it != end; ++it) {
5201                         docstring const & current_branch = it->branch();
5202                         Branch const * branch = branchlist.find(current_branch);
5203                         string const bcolor = branch->color();
5204                         RGBColor rgbcol;
5205                         if (bcolor.size() == 7 && bcolor[0] == '#')
5206                                 rgbcol = lyx::rgbFromHexName(bcolor);
5207                         else
5208                                 guiApp->getRgbColor(lcolor.getFromLyXName(bcolor), rgbcol);
5209                         string const x11hexname = X11hexname(rgbcol);
5210                         // display the new color
5211                         docstring const str = current_branch + ' ' + from_ascii(x11hexname);
5212                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
5213                 }
5214         }
5215         // rename branches in the document
5216         executeBranchRenaming();
5217         // and clear changed branches cache
5218         changedBranches_.clear();
5219
5220         // Generate the colours requested by indices.
5221         IndicesList & indiceslist = params().indiceslist();
5222         if (!indiceslist.empty()) {
5223                 IndicesList::const_iterator it = indiceslist.begin();
5224                 IndicesList::const_iterator const end = indiceslist.end();
5225                 for (; it != end; ++it) {
5226                         docstring const & current_index = it->shortcut();
5227                         Index const * index = indiceslist.findShortcut(current_index);
5228                         string const x11hexname = X11hexname(index->color());
5229                         // display the new color
5230                         docstring const str = current_index + ' ' + from_ascii(x11hexname);
5231                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
5232                 }
5233         }
5234         // FIXME LFUN
5235         // If we used an LFUN, we would not need these two lines:
5236         BufferView * bv = const_cast<BufferView *>(bufferview());
5237         bv->processUpdateFlags(Update::Force | Update::FitCursor);
5238 }
5239
5240
5241 void GuiDocument::setLanguage() const
5242 {
5243         Language const * const newL = bp_.language;
5244         if (buffer().params().language == newL)
5245                 return;
5246
5247         string const & lang_name = newL->lang();
5248         dispatch(FuncRequest(LFUN_BUFFER_LANGUAGE, lang_name));
5249 }
5250
5251
5252 void GuiDocument::saveAsDefault() const
5253 {
5254         dispatch_bufferparams(*this, params(), LFUN_BUFFER_SAVE_AS_DEFAULT, &buffer());
5255 }
5256
5257
5258 bool GuiDocument::providesOSF(QString const & font) const
5259 {
5260         if (fontModule->osFontsCB->isChecked())
5261                 // FIXME: we should check if the fonts really
5262                 // have OSF support. But how?
5263                 return font != "default";
5264         return theLaTeXFonts().getLaTeXFont(
5265                                 qstring_to_ucs4(font)).providesOSF(ot1(),
5266                                                                    completeFontset(),
5267                                                                    noMathFont());
5268 }
5269
5270
5271 bool GuiDocument::providesSC(QString const & font) const
5272 {
5273         if (fontModule->osFontsCB->isChecked())
5274                 return false;
5275         return theLaTeXFonts().getLaTeXFont(
5276                                 qstring_to_ucs4(font)).providesSC(ot1(),
5277                                                                   completeFontset(),
5278                                                                   noMathFont());
5279 }
5280
5281
5282 bool GuiDocument::providesScale(QString const & font) const
5283 {
5284         if (fontModule->osFontsCB->isChecked())
5285                 return font != "default";
5286         return theLaTeXFonts().getLaTeXFont(
5287                                 qstring_to_ucs4(font)).providesScale(ot1(),
5288                                                                      completeFontset(),
5289                                                                      noMathFont());
5290 }
5291
5292
5293 bool GuiDocument::providesExtraOpts(QString const & font) const
5294 {
5295         if (fontModule->osFontsCB->isChecked())
5296                 return font != "default";
5297         return theLaTeXFonts().getLaTeXFont(
5298                                 qstring_to_ucs4(font)).providesMoreOptions(ot1(),
5299                                                                      completeFontset(),
5300                                                                      noMathFont());
5301 }
5302
5303
5304 bool GuiDocument::providesNoMath(QString const & font) const
5305 {
5306         if (fontModule->osFontsCB->isChecked())
5307                 return false;
5308         return theLaTeXFonts().getLaTeXFont(
5309                                 qstring_to_ucs4(font)).providesNoMath(ot1(),
5310                                                                       completeFontset());
5311 }
5312
5313
5314 bool GuiDocument::hasMonolithicExpertSet(QString const & font) const
5315 {
5316         if (fontModule->osFontsCB->isChecked())
5317                 return false;
5318         return theLaTeXFonts().getLaTeXFont(
5319                                 qstring_to_ucs4(font)).hasMonolithicExpertSet(ot1(),
5320                                                                               completeFontset(),
5321                                                                               noMathFont());
5322 }
5323
5324
5325 //static
5326 GuiDocument::modInfoStruct GuiDocument::modInfo(LyXModule const & mod)
5327 {
5328         // FIXME Unicode: docstrings would be better for these parameters but this
5329         // change requires a lot of others
5330         modInfoStruct m;
5331         m.id = mod.getID();
5332         QString const guiname = toqstr(translateIfPossible(from_utf8(mod.getName())));
5333         m.missingreqs = !isModuleAvailable(mod.getID());
5334         if (m.missingreqs) {
5335                 m.name = qt_("%1 (missing req.)").arg(guiname);
5336         } else
5337                 m.name = guiname;
5338         m.category = mod.category().empty() ? qt_("Miscellaneous")
5339                                             : toqstr(translateIfPossible(from_utf8(mod.category())));
5340         QString desc = toqstr(translateIfPossible(from_utf8(mod.getDescription())));
5341         // Find the first sentence of the description
5342         QTextBoundaryFinder bf(QTextBoundaryFinder::Sentence, desc);
5343         int pos = bf.toNextBoundary();
5344         if (pos > 0)
5345                 desc.truncate(pos);
5346         m.local = mod.isLocal();
5347         QString const mtype = m.local ? qt_("personal module") : qt_("distributed module");
5348         QString modulename = qt_("<b>Module name:</b> <i>%1</i> (%2)").arg(toqstr(m.id)).arg(mtype);
5349         // Tooltip is the desc followed by the module name and the type
5350         m.description = QString("%1%2")
5351                 .arg(desc.isEmpty() ? QString() : QString("<p>%1</p>").arg(desc),
5352                      modulename);
5353         if (m.missingreqs)
5354                 m.description += QString("<p>%1</p>").arg(qt_("<b>Note:</b> Some requirements for this module are missing!"));
5355         return m;
5356 }
5357
5358
5359 void GuiDocument::loadModuleInfo()
5360 {
5361         moduleNames_.clear();
5362         for (LyXModule const & mod : theModuleList)
5363                 moduleNames_.push_back(modInfo(mod));
5364 }
5365
5366
5367 void GuiDocument::updateUnknownBranches()
5368 {
5369         if (!bufferview())
5370                 return;
5371         list<docstring> used_branches;
5372         buffer().getUsedBranches(used_branches);
5373         list<docstring>::const_iterator it = used_branches.begin();
5374         QStringList unknown_branches;
5375         for (; it != used_branches.end() ; ++it) {
5376                 if (!buffer().params().branchlist().find(*it))
5377                         unknown_branches.append(toqstr(*it));
5378         }
5379         branchesModule->setUnknownBranches(unknown_branches);
5380 }
5381
5382
5383 void GuiDocument::branchesRename(docstring const & oldname, docstring const & newname)
5384 {
5385         map<docstring, docstring>::iterator it = changedBranches_.begin();
5386         for (; it != changedBranches_.end() ; ++it) {
5387                 if (it->second == oldname) {
5388                         // branch has already been renamed
5389                         it->second = newname;
5390                         return;
5391                 }
5392         }
5393         // store new name
5394         changedBranches_[oldname] = newname;
5395 }
5396
5397
5398 void GuiDocument::executeBranchRenaming() const
5399 {
5400         map<docstring, docstring>::const_iterator it = changedBranches_.begin();
5401         for (; it != changedBranches_.end() ; ++it) {
5402                 docstring const arg = '"' + it->first + '"' + " " + '"' + it->second + '"';
5403                 dispatch(FuncRequest(LFUN_BRANCHES_RENAME, arg));
5404         }
5405 }
5406
5407
5408 void GuiDocument::allPackagesAuto()
5409 {
5410         allPackages(1);
5411 }
5412
5413
5414 void GuiDocument::allPackagesAlways()
5415 {
5416         allPackages(2);
5417 }
5418
5419
5420 void GuiDocument::allPackagesNot()
5421 {
5422         allPackages(3);
5423 }
5424
5425
5426 void GuiDocument::allPackages(int col)
5427 {
5428         for (int row = 0; row < mathsModule->packagesTW->rowCount(); ++row) {
5429                 QRadioButton * rb =
5430                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, col)->layout()->itemAt(0)->widget();
5431                 rb->setChecked(true);
5432         }
5433 }
5434
5435
5436 void GuiDocument::linenoToggled(bool on)
5437 {
5438         numberingModule->linenoLE->setEnabled(on);
5439         numberingModule->linenoLA->setEnabled(on);
5440 }
5441
5442
5443 void GuiDocument::outputChangesToggled(bool on)
5444 {
5445         changesModule->changeBarsCB->setEnabled(on);
5446         change_adaptor();
5447 }
5448
5449 void GuiDocument::setOutputSync(bool on)
5450 {
5451         outputModule->synccustomCB->setEnabled(on);
5452         outputModule->synccustomLA->setEnabled(on);
5453         change_adaptor();
5454 }
5455
5456
5457 bool GuiDocument::eventFilter(QObject * sender, QEvent * event)
5458 {
5459         if (event->type() == QEvent::ApplicationPaletteChange) {
5460                 // mode switch: colors need to be updated
5461                 // and the highlighting redone
5462                 if (pdf_options_highlighter_) {
5463                         pdf_options_highlighter_->setupColors();
5464                         pdf_options_highlighter_->rehighlight();
5465                 }
5466                 if (pdf_metadata_highlighter_) {
5467                         pdf_metadata_highlighter_->setupColors();
5468                         pdf_metadata_highlighter_->rehighlight();
5469                 }
5470         }
5471         return QWidget::eventFilter(sender, event);
5472 }
5473
5474
5475 } // namespace frontend
5476 } // namespace lyx
5477
5478 #include "moc_GuiDocument.cpp"