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