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