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