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