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