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