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