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