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