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