]> git.lyx.org Git - lyx.git/blob - src/frontends/qt/GuiDocument.cpp
disable-default-font-options LyX does not output any LaTeX code when adding optinos...
[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         if (set && has_default)
2428                 // (re)set to the default style
2429                 langModule->quoteStyleCO->setCurrentIndex(0);
2430 }
2431
2432
2433 void GuiDocument::languageChanged(int i)
2434 {
2435         // some languages only work with Polyglossia
2436         Language const * lang = lyx::languages.getLanguage(
2437                 fromqstr(langModule->languageCO->itemData(i).toString()));
2438         if (lang->babel().empty() && !lang->polyglossia().empty()
2439                 && lang->required() != "CJK" && lang->required() != "japanese") {
2440                         // If we force to switch fontspec on, store
2441                         // current state (#8717)
2442                         if (fontModule->osFontsCB->isEnabled())
2443                                 forced_fontspec_activation =
2444                                         !fontModule->osFontsCB->isChecked();
2445                         fontModule->osFontsCB->setChecked(true);
2446                         fontModule->osFontsCB->setEnabled(false);
2447         }
2448         else {
2449                 fontModule->osFontsCB->setEnabled(true);
2450                 // If we have forced to switch fontspec on,
2451                 // restore previous state (#8717)
2452                 if (forced_fontspec_activation)
2453                         fontModule->osFontsCB->setChecked(false);
2454                 forced_fontspec_activation = false;
2455         }
2456
2457         // set appropriate quotation mark style
2458         updateQuoteStyles(true);
2459 }
2460
2461
2462 void GuiDocument::osFontsChanged(bool nontexfonts)
2463 {
2464         bool const tex_fonts = !nontexfonts;
2465         // store current fonts
2466         QString const font_roman = fontModule->fontsRomanCO->getData(
2467                         fontModule->fontsRomanCO->currentIndex());
2468         QString const font_sans = fontModule->fontsSansCO->getData(
2469                         fontModule->fontsSansCO->currentIndex());
2470         QString const font_typewriter = fontModule->fontsTypewriterCO->getData(
2471                         fontModule->fontsTypewriterCO->currentIndex());
2472         QString const font_math = fontModule->fontsMathCO->itemData(
2473                         fontModule->fontsMathCO->currentIndex()).toString();
2474         int const font_sf_scale = fontModule->scaleSansSB->value();
2475         int const font_tt_scale = fontModule->scaleTypewriterSB->value();
2476
2477         updateFontlist();
2478         // store default format
2479         QString const dformat = outputModule->defaultFormatCO->itemData(
2480                 outputModule->defaultFormatCO->currentIndex()).toString();
2481         updateDefaultFormat();
2482         // try to restore default format
2483         int index = outputModule->defaultFormatCO->findData(dformat);
2484         // set to default if format is not found
2485         if (index == -1)
2486                 index = 0;
2487         outputModule->defaultFormatCO->setCurrentIndex(index);
2488
2489         // try to restore fonts which were selected two toggles ago
2490         if (!fontModule->font_roman.isEmpty())
2491                 fontModule->fontsRomanCO->set(fontModule->font_roman);
2492         if (!fontModule->font_sans.isEmpty())
2493                 fontModule->fontsSansCO->set(fontModule->font_sans);
2494         if (!fontModule->font_typewriter.isEmpty())
2495                 fontModule->fontsTypewriterCO->set(fontModule->font_typewriter);
2496         index = fontModule->fontsMathCO->findData(fontModule->font_math);
2497         if (index != -1)
2498                 fontModule->fontsMathCO->setCurrentIndex(index);
2499         // save fonts for next next toggle
2500         fontModule->font_roman = font_roman;
2501         fontModule->font_sans = font_sans;
2502         fontModule->font_typewriter = font_typewriter;
2503         fontModule->font_math = font_math;
2504         fontModule->font_sf_scale = font_sf_scale;
2505         fontModule->font_tt_scale = font_tt_scale;
2506
2507         // non-tex fonts override the "\inputencoding" option with "utf8-plain"
2508         langModule->encodingCO->setEnabled(tex_fonts);
2509         inputencodingToDialog();
2510
2511         fontModule->cjkFontLE->setEnabled(tex_fonts);
2512         fontModule->cjkFontLA->setEnabled(tex_fonts);
2513
2514         updateFontOptions();
2515
2516         fontModule->fontencLA->setEnabled(tex_fonts);
2517         fontModule->fontencCO->setEnabled(tex_fonts);
2518         if (!tex_fonts)
2519                 fontModule->fontencLE->setEnabled(false);
2520         else
2521                 fontencChanged(fontModule->fontencCO->currentIndex());
2522 }
2523
2524
2525 void GuiDocument::encodingSwitched(int i)
2526 {
2527         bool const tex_fonts = !fontModule->osFontsCB->isChecked();
2528         langModule->unicodeEncodingCO->setEnabled(tex_fonts);
2529         langModule->customEncodingCO->setEnabled(tex_fonts);
2530         langModule->autoEncodingCO->setEnabled(tex_fonts);
2531         langModule->unicodeEncodingCO->setVisible(i == EncodingSets::unicode);
2532         langModule->autoEncodingCO->setVisible(i == EncodingSets::legacy);
2533         langModule->customEncodingCO->setVisible(i == EncodingSets::custom);
2534         switch (i) {
2535         case EncodingSets::unicode:
2536                 langModule->encodingVariantLA->setBuddy(langModule->unicodeEncodingCO);
2537                 break;
2538         case EncodingSets::legacy:
2539                 langModule->encodingVariantLA->setBuddy(langModule->autoEncodingCO);
2540                 break;
2541         case EncodingSets::custom:
2542                 langModule->encodingVariantLA->setBuddy(langModule->customEncodingCO);
2543                 break;
2544         }
2545  
2546         if (tex_fonts)
2547                 langModule->unicodeEncodingCO->setItemText(1, qt_("Direct (No inputenc)"));
2548         else
2549                 langModule->unicodeEncodingCO->setItemText(1, qt_("Direct (XeTeX/LuaTeX)"));
2550 }
2551
2552 void GuiDocument::inputencodingToDialog()
2553 {
2554         QString inputenc = toqstr(bp_.inputenc);
2555         int p;
2556         if (fontModule->osFontsCB->isChecked()) { // non-tex fonts require utf8-plain
2557                 langModule->encodingCO->setCurrentIndex(EncodingSets::unicode);
2558                 langModule->unicodeEncodingCO->setCurrentIndex(
2559                         langModule->unicodeEncodingCO->findData("utf8-plain"));
2560         } else if (inputenc.startsWith("utf8")) {
2561                 langModule->encodingCO->setCurrentIndex(EncodingSets::unicode);
2562                 p = langModule->unicodeEncodingCO->findData(inputenc);
2563                 if (p == -1)
2564                         p = 0;
2565                 langModule->unicodeEncodingCO->setCurrentIndex(p);
2566                 langModule->autoEncodingCO->setCurrentIndex(0);
2567                 langModule->customEncodingCO->setCurrentIndex(0);
2568         } else if (inputenc.startsWith("auto")) {
2569                 langModule->encodingCO->setCurrentIndex(EncodingSets::legacy);
2570                 p = langModule->autoEncodingCO->findData(inputenc);
2571                 if (p == -1)
2572                         p = 0;
2573                 langModule->unicodeEncodingCO->setCurrentIndex(0);
2574                 langModule->autoEncodingCO->setCurrentIndex(p);
2575                 langModule->customEncodingCO->setCurrentIndex(0);
2576         } else {
2577                 langModule->encodingCO->setCurrentIndex(EncodingSets::custom);
2578                 p = langModule->customEncodingCO->findData(inputenc);
2579                 if (p == -1) {
2580                         p = 0;
2581                         langModule->encodingCO->setCurrentIndex(EncodingSets::unicode);
2582                 }
2583                 langModule->unicodeEncodingCO->setCurrentIndex(0);
2584                 langModule->autoEncodingCO->setCurrentIndex(0);
2585                 langModule->customEncodingCO->setCurrentIndex(p);
2586         }
2587         encodingSwitched(langModule->encodingCO->currentIndex());
2588 }
2589
2590
2591 void GuiDocument::mathFontChanged(int)
2592 {
2593         updateFontOptions();
2594 }
2595
2596 void GuiDocument::fontOsfToggled(bool state)
2597 {
2598         if (fontModule->osFontsCB->isChecked())
2599                 return;
2600         QString font = fontModule->fontsRomanCO->getData(
2601                         fontModule->fontsRomanCO->currentIndex());
2602         if (hasMonolithicExpertSet(font))
2603                 fontModule->fontScCB->setChecked(state);
2604 }
2605
2606
2607 void GuiDocument::fontScToggled(bool state)
2608 {
2609         if (fontModule->osFontsCB->isChecked())
2610                 return;
2611         QString font = fontModule->fontsRomanCO->getData(
2612                         fontModule->fontsRomanCO->currentIndex());
2613         if (hasMonolithicExpertSet(font))
2614                 fontModule->fontOsfCB->setChecked(state);
2615 }
2616
2617
2618 void GuiDocument::updateExtraOpts()
2619 {
2620         QString font;
2621         font = fontModule->fontsRomanCO->getData(
2622                         fontModule->fontsRomanCO->currentIndex());
2623         bool const rm_opts = providesExtraOpts(font);
2624         font = fontModule->fontsSansCO->getData(
2625                         fontModule->fontsSansCO->currentIndex());
2626         bool const sf_opts = providesExtraOpts(font);
2627         font = fontModule->fontsTypewriterCO->getData(
2628                         fontModule->fontsTypewriterCO->currentIndex());
2629         bool const tt_opts = providesExtraOpts(font);
2630         fontModule->fontspecRomanLA->setEnabled(rm_opts);
2631         fontModule->fontspecRomanLE->setEnabled(rm_opts);
2632         fontModule->fontspecSansLA->setEnabled(sf_opts);
2633         fontModule->fontspecSansLE->setEnabled(sf_opts);
2634         fontModule->fontspecTypewriterLA->setEnabled(tt_opts);
2635         fontModule->fontspecTypewriterLE->setEnabled(tt_opts);
2636 }
2637
2638
2639 void GuiDocument::updateFontOptions()
2640 {
2641         QString font;
2642         font = fontModule->fontsSansCO->getData(
2643                         fontModule->fontsSansCO->currentIndex());
2644         bool scalable = providesScale(font);
2645         fontModule->scaleSansSB->setEnabled(scalable);
2646         fontModule->scaleSansLA->setEnabled(scalable);
2647         fontModule->fontSansOsfCB->setEnabled(providesOSF(font));
2648         font = fontModule->fontsTypewriterCO->getData(
2649                         fontModule->fontsTypewriterCO->currentIndex());
2650         scalable = providesScale(font);
2651         fontModule->scaleTypewriterSB->setEnabled(scalable);
2652         fontModule->scaleTypewriterLA->setEnabled(scalable);
2653         fontModule->fontTypewriterOsfCB->setEnabled(providesOSF(font));
2654         font = fontModule->fontsRomanCO->getData(
2655                         fontModule->fontsRomanCO->currentIndex());
2656         fontModule->fontScCB->setEnabled(providesSC(font));
2657         fontModule->fontOsfCB->setEnabled(providesOSF(font));
2658         updateExtraOpts();
2659         updateMathFonts(font);
2660 }
2661
2662
2663 void GuiDocument::updateFontsize(string const & items, string const & sel)
2664 {
2665         fontModule->fontsizeCO->clear();
2666         fontModule->fontsizeCO->addItem(qt_("Default"));
2667
2668         for (int n = 0; !token(items,'|',n).empty(); ++n)
2669                 fontModule->fontsizeCO->
2670                         addItem(toqstr(token(items,'|',n)));
2671
2672         for (int n = 0; n < fontModule->fontsizeCO->count(); ++n) {
2673                 if (fromqstr(fontModule->fontsizeCO->itemText(n)) == sel) {
2674                         fontModule->fontsizeCO->setCurrentIndex(n);
2675                         break;
2676                 }
2677         }
2678 }
2679
2680
2681 bool GuiDocument::ot1() const
2682 {
2683         QString const fontenc =
2684                 fontModule->fontencCO->itemData(fontModule->fontencCO->currentIndex()).toString();
2685         int const i = langModule->languageCO->currentIndex();
2686         if (i == -1)
2687                 return false;
2688         QString const langname = langModule->languageCO->itemData(i).toString();
2689         Language const * newlang = lyx::languages.getLanguage(fromqstr(langname));
2690         return (fontenc == "default"
2691                 || (fontenc == "auto" && newlang->fontenc(buffer().params()) == "OT1")
2692                 || (fontenc == "custom" && fontModule->fontencLE->text() == "OT1"));
2693 }
2694
2695
2696 bool GuiDocument::completeFontset() const
2697 {
2698         return (fontModule->fontsSansCO->getData(
2699                         fontModule->fontsSansCO->currentIndex()) == "default"
2700                 && fontModule->fontsSansCO->getData(
2701                         fontModule->fontsTypewriterCO->currentIndex()) == "default");
2702 }
2703
2704
2705 bool GuiDocument::noMathFont() const
2706 {
2707         return (fontModule->fontsMathCO->itemData(
2708                 fontModule->fontsMathCO->currentIndex()).toString() == "default");
2709 }
2710
2711
2712 void GuiDocument::updateTexFonts()
2713 {
2714         LaTeXFonts::TexFontMap texfontmap = theLaTeXFonts().getLaTeXFonts();
2715
2716         LaTeXFonts::TexFontMap::const_iterator it = texfontmap.begin();
2717         LaTeXFonts::TexFontMap::const_iterator end = texfontmap.end();
2718         for (; it != end; ++it) {
2719                 LaTeXFont lf = it->second;
2720                 if (lf.name().empty()) {
2721                         LYXERR0("Error: Unnamed font: " << it->first);
2722                         continue;
2723                 }
2724                 docstring const family = lf.family();
2725                 docstring guiname = translateIfPossible(lf.guiname());
2726                 if (!lf.available(ot1(), noMathFont()))
2727                         guiname += _(" (not installed)");
2728                 if (family == "rm")
2729                         rmfonts_.insert(toqstr(guiname), toqstr(it->first));
2730                 else if (family == "sf")
2731                         sffonts_.insert(toqstr(guiname), toqstr(it->first));
2732                 else if (family == "tt")
2733                         ttfonts_.insert(toqstr(guiname), toqstr(it->first));
2734                 else if (family == "math")
2735                         mathfonts_.insert(toqstr(guiname), toqstr(it->first));
2736         }
2737 }
2738
2739
2740 void GuiDocument::updateFontlist()
2741 {
2742         // reset the filters of the CategorizedCombos
2743         fontModule->fontsRomanCO->resetFilter();
2744         fontModule->fontsSansCO->resetFilter();
2745         fontModule->fontsTypewriterCO->resetFilter();
2746         fontModule->fontsRomanCO->clear();
2747         fontModule->fontsSansCO->clear();
2748         fontModule->fontsTypewriterCO->clear();
2749         fontModule->fontsMathCO->clear();
2750
2751         // With fontspec (XeTeX, LuaTeX), we have access to all system fonts, but not the LaTeX fonts
2752         if (fontModule->osFontsCB->isChecked()) {
2753                 fontModule->fontsRomanCO->addItemSort(QString("default"), qt_("Default"),
2754                                                       QString(), qt_("Default font (as set by class)"),
2755                                                       false, false, false, true, true);
2756                 fontModule->fontsSansCO->addItemSort(QString("default"), qt_("Default"),
2757                                                      QString(), qt_("Default font (as set by class)"),
2758                                                      false, false, false, true, true);
2759                 fontModule->fontsTypewriterCO->addItemSort(QString("default"), qt_("Default"),
2760                                                            QString(), qt_("Default font (as set by class)"),
2761                                                            false, false, false, true, true);
2762                 QString unimath = qt_("Non-TeX Fonts Default");
2763                 if (!LaTeXFeatures::isAvailable("unicode-math"))
2764                         unimath += qt_(" (not available)");
2765                 fontModule->fontsMathCO->addItem(qt_("Class Default (TeX Fonts)"), QString("auto"));
2766                 fontModule->fontsMathCO->addItem(unimath, QString("default"));
2767
2768 #if QT_VERSION >= 0x060000
2769                 const QStringList families(QFontDatabase::families());
2770 #else
2771                 QFontDatabase fontdb;
2772                 const QStringList families(fontdb.families());
2773 #endif
2774                 for (auto const & family : families) {
2775                         fontModule->fontsRomanCO->addItemSort(family, family,
2776                                                               QString(), QString(),
2777                                                               false, false, false, true, true);
2778                         fontModule->fontsSansCO->addItemSort(family, family,
2779                                                              QString(), QString(),
2780                                                              false, false, false, true, true);
2781                         fontModule->fontsTypewriterCO->addItemSort(family, family,
2782                                                                    QString(), QString(),
2783                                                                    false, false, false, true, true);
2784                 }
2785                 return;
2786         }
2787
2788         if (rmfonts_.empty())
2789                 updateTexFonts();
2790
2791         fontModule->fontsRomanCO->addItemSort(QString("default"), qt_("Default"),
2792                                               QString(), qt_("Default font (as set by class)"),
2793                                               false, false, false, true, true);
2794         QMap<QString, QString>::const_iterator rmi = rmfonts_.constBegin();
2795         while (rmi != rmfonts_.constEnd()) {
2796                 fontModule->fontsRomanCO->addItemSort(rmi.value(), rmi.key(),
2797                                                       QString(), QString(),
2798                                                       false, false, false, true, true);
2799                 ++rmi;
2800         }
2801
2802         fontModule->fontsSansCO->addItemSort(QString("default"), qt_("Default"),
2803                                              QString(), qt_("Default font (as set by class)"),
2804                                              false, false, false, true, true);
2805         QMap<QString, QString>::const_iterator sfi = sffonts_.constBegin();
2806         while (sfi != sffonts_.constEnd()) {
2807                 fontModule->fontsSansCO->addItemSort(sfi.value(), sfi.key(),
2808                                                      QString(), QString(),
2809                                                      false, false, false, true, true);
2810                 ++sfi;
2811         }
2812
2813         fontModule->fontsTypewriterCO->addItemSort(QString("default"), qt_("Default"),
2814                                                    QString(), qt_("Default font (as set by class)"),
2815                                                    false, false, false, true, true);
2816         QMap<QString, QString>::const_iterator tti = ttfonts_.constBegin();
2817         while (tti != ttfonts_.constEnd()) {
2818                 fontModule->fontsTypewriterCO->addItemSort(tti.value(), tti.key(),
2819                                                            QString(), QString(),
2820                                                            false, false, false, true, true);
2821                 ++tti;
2822         }
2823
2824         fontModule->fontsMathCO->addItem(qt_("Automatic"), QString("auto"));
2825         fontModule->fontsMathCO->addItem(qt_("Class Default"), QString("default"));
2826         QMap<QString, QString>::const_iterator mmi = mathfonts_.constBegin();
2827         while (mmi != mathfonts_.constEnd()) {
2828                 fontModule->fontsMathCO->addItem(mmi.key(), mmi.value());
2829                 ++mmi;
2830         }
2831 }
2832
2833
2834 void GuiDocument::fontencChanged(int item)
2835 {
2836         fontModule->fontencLE->setEnabled(
2837                 fontModule->fontencCO->itemData(item).toString() == "custom");
2838         // The availability of TeX fonts depends on the font encoding
2839         updateTexFonts();
2840         updateFontOptions();
2841 }
2842
2843
2844 void GuiDocument::updateMathFonts(QString const & rm)
2845 {
2846         if (fontModule->osFontsCB->isChecked())
2847                 return;
2848         QString const math =
2849                 fontModule->fontsMathCO->itemData(fontModule->fontsMathCO->currentIndex()).toString();
2850         int const i = fontModule->fontsMathCO->findData("default");
2851         if (providesNoMath(rm) && i == -1)
2852                 fontModule->fontsMathCO->insertItem(1, qt_("Class Default"), QString("default"));
2853         else if (!providesNoMath(rm) && i != -1) {
2854                 int const c = fontModule->fontsMathCO->currentIndex();
2855                 fontModule->fontsMathCO->removeItem(i);
2856                 if (c == i)
2857                         fontModule->fontsMathCO->setCurrentIndex(0);
2858         }
2859 }
2860
2861
2862 void GuiDocument::romanChanged(int item)
2863 {
2864         QString const font = fontModule->fontsRomanCO->getData(item);
2865         fontModule->fontOsfCB->setEnabled(providesOSF(font));
2866         updateExtraOpts();
2867         if (fontModule->osFontsCB->isChecked())
2868                 return;
2869         fontModule->fontScCB->setEnabled(providesSC(font));
2870         updateMathFonts(font);
2871 }
2872
2873
2874 void GuiDocument::sansChanged(int item)
2875 {
2876         QString const font = fontModule->fontsSansCO->getData(item);
2877         bool const scalable = providesScale(font);
2878         fontModule->scaleSansSB->setEnabled(scalable);
2879         fontModule->scaleSansLA->setEnabled(scalable);
2880         fontModule->fontSansOsfCB->setEnabled(providesOSF(font));
2881         updateExtraOpts();
2882 }
2883
2884
2885 void GuiDocument::ttChanged(int item)
2886 {
2887         QString const font = fontModule->fontsTypewriterCO->getData(item);
2888         bool scalable = providesScale(font);
2889         fontModule->scaleTypewriterSB->setEnabled(scalable);
2890         fontModule->scaleTypewriterLA->setEnabled(scalable);
2891         fontModule->fontTypewriterOsfCB->setEnabled(providesOSF(font));
2892         updateExtraOpts();
2893 }
2894
2895
2896 void GuiDocument::updatePagestyle(string const & items, string const & sel)
2897 {
2898         pagestyles.clear();
2899         pageLayoutModule->pagestyleCO->clear();
2900         pageLayoutModule->pagestyleCO->addItem(qt_("Default"));
2901
2902         for (int n = 0; !token(items, '|', n).empty(); ++n) {
2903                 string style = token(items, '|', n);
2904                 QString style_gui = qt_(style);
2905                 pagestyles.push_back(pair<string, QString>(style, style_gui));
2906                 pageLayoutModule->pagestyleCO->addItem(style_gui);
2907         }
2908
2909         if (sel == "default") {
2910                 pageLayoutModule->pagestyleCO->setCurrentIndex(0);
2911                 return;
2912         }
2913
2914         int nn = 0;
2915
2916         for (auto const & pagestyle : pagestyles)
2917                 if (pagestyle.first == sel)
2918                         nn = pageLayoutModule->pagestyleCO->findText(pagestyle.second);
2919
2920         if (nn > 0)
2921                 pageLayoutModule->pagestyleCO->setCurrentIndex(nn);
2922 }
2923
2924
2925 void GuiDocument::browseLayout()
2926 {
2927         QString const label1 = qt_("Lay&outs");
2928         QString const dir1 = toqstr(lyxrc.document_path);
2929         QStringList const filter(qt_("LyX Layout (*.layout)"));
2930         QString file = browseRelToParent(QString(), bufferFilePath(),
2931                 qt_("Local layout file"), filter, false,
2932                 label1, dir1);
2933
2934         if (!file.endsWith(".layout"))
2935                 return;
2936
2937         FileName layoutFile = support::makeAbsPath(fromqstr(file),
2938                 fromqstr(bufferFilePath()));
2939
2940         int const ret = Alert::prompt(_("Local layout file"),
2941                 _("The layout file you have selected is a local layout\n"
2942                   "file, not one in the system or user directory.\n"
2943                   "Your document will not work with this layout if you\n"
2944                   "move the layout file to a different directory."),
2945                   1, 1, _("&Set Layout"), _("&Cancel"));
2946         if (ret == 1)
2947                 return;
2948
2949         // load the layout file
2950         LayoutFileList & bcl = LayoutFileList::get();
2951         string classname = layoutFile.onlyFileName();
2952         // this will update an existing layout if that layout has been loaded before.
2953         LayoutFileIndex name = support::onlyFileName(bcl.addLocalLayout(
2954                 classname.substr(0, classname.size() - 7),
2955                 layoutFile.onlyPath().absFileName()));
2956
2957         if (name.empty()) {
2958                 Alert::error(_("Error"),
2959                         _("Unable to read local layout file."));
2960                 return;
2961         }
2962
2963         const_cast<Buffer &>(buffer()).setLayoutPos(layoutFile.onlyPath().absFileName());
2964
2965         // do not trigger classChanged if there is no change.
2966         if (latexModule->classCO->currentText() == toqstr(name))
2967                 return;
2968
2969         // add to combo box
2970         bool const avail = latexModule->classCO->set(toqstr(name));
2971         if (!avail) {
2972                 LayoutFile const & tc = bcl[name];
2973                 docstring const guiname = translateIfPossible(from_utf8(tc.description()));
2974                 // tooltip sensu "KOMA-Script Article [Class 'scrartcl']"
2975                 QString tooltip = toqstr(bformat(_("%1$s [Class '%2$s']"), guiname, from_utf8(tc.latexname())));
2976                 tooltip += '\n' + qt_("This is a local layout file.");
2977                 latexModule->classCO->addItemSort(toqstr(tc.name()), toqstr(guiname),
2978                                                   toqstr(translateIfPossible(from_utf8(tc.category()))),
2979                                                   tooltip,
2980                                                   true, true, true, true);
2981                 latexModule->classCO->set(toqstr(name));
2982         }
2983
2984         classChanged();
2985 }
2986
2987
2988 void GuiDocument::browseMaster()
2989 {
2990         QString const title = qt_("Select master document");
2991         QString const dir1 = toqstr(lyxrc.document_path);
2992         QString const old = latexModule->childDocLE->text();
2993         QString const docpath = toqstr(support::onlyPath(buffer().absFileName()));
2994         QStringList const filter(qt_("LyX Files (*.lyx)"));
2995         QString file = browseRelToSub(old, docpath, title, filter, false,
2996                 qt_("D&ocuments"), toqstr(lyxrc.document_path));
2997
2998         if (!file.isEmpty())
2999                 latexModule->childDocLE->setText(file);
3000 }
3001
3002
3003 void GuiDocument::classChanged_adaptor()
3004 {
3005         const_cast<Buffer &>(buffer()).setLayoutPos(string());
3006         classChanged();
3007 }
3008
3009
3010 void GuiDocument::classChanged()
3011 {
3012         int idx = latexModule->classCO->currentIndex();
3013         if (idx < 0)
3014                 return;
3015         string const classname = fromqstr(latexModule->classCO->getData(idx));
3016
3017         if (buttonBox->button(QDialogButtonBox::Apply)->isEnabled()) {
3018                 int const ret = Alert::prompt(_("Unapplied changes"),
3019                                 _("Some changes in the dialog were not yet applied.\n"
3020                                 "If you do not apply now, they will be lost after this action."),
3021                                 1, 1, _("&Apply"), _("&Dismiss"));
3022                 if (ret == 0)
3023                         applyView();
3024         }
3025
3026         // We load the TextClass as soon as it is selected. This is
3027         // necessary so that other options in the dialog can be updated
3028         // according to the new class. Note, however, that, if you use
3029         // the scroll wheel when sitting on the combo box, we'll load a
3030         // lot of TextClass objects very quickly....
3031         if (!bp_.setBaseClass(classname, buffer().layoutPos())) {
3032                 Alert::error(_("Error"), _("Unable to set document class."));
3033                 return;
3034         }
3035         if (lyxrc.auto_reset_options)
3036                 bp_.useClassDefaults();
3037
3038         // With the introduction of modules came a distinction between the base
3039         // class and the document class. The former corresponds to the main layout
3040         // file; the latter is that plus the modules (or the document-specific layout,
3041         // or  whatever else there could be). Our parameters come from the document
3042         // class. So when we set the base class, we also need to recreate the document
3043         // class. Otherwise, we still have the old one.
3044         bp_.makeDocumentClass();
3045         paramsToDialog();
3046 }
3047
3048
3049 void GuiDocument::languagePackageChanged(int i)
3050 {
3051          langModule->languagePackageLE->setEnabled(
3052                 langModule->languagePackageCO->itemData(i).toString() == "custom");
3053 }
3054
3055
3056 void GuiDocument::biblioChanged()
3057 {
3058         biblioChanged_ = true;
3059         change_adaptor();
3060 }
3061
3062
3063 void GuiDocument::checkPossibleCiteEngines()
3064 {
3065         // Check if the class provides a specific engine,
3066         // and if so, enforce this.
3067         string force_engine;
3068         if (documentClass().provides("natbib")
3069             || documentClass().provides("natbib-internal"))
3070                 force_engine = "natbib";
3071         else if (documentClass().provides("jurabib"))
3072                 force_engine = "jurabib";
3073         else if (documentClass().provides("biblatex"))
3074                 force_engine = "biblatex";
3075         else if (documentClass().provides("biblatex-natbib"))
3076                 force_engine = "biblatex-natbib";
3077
3078         if (!force_engine.empty())
3079                 biblioModule->citeEngineCO->setCurrentIndex(
3080                         biblioModule->citeEngineCO->findData(toqstr(force_engine)));
3081         biblioModule->citeEngineCO->setEnabled(force_engine.empty());
3082 }
3083
3084
3085 void GuiDocument::rescanBibFiles()
3086 {
3087         if (isBiblatex())
3088                 rescanTexStyles("bbx cbx");
3089         else
3090                 rescanTexStyles("bst");
3091 }
3092
3093
3094 void GuiDocument::resetDefaultBibfile(string const & which)
3095 {
3096         QString const engine =
3097                 biblioModule->citeEngineCO->itemData(
3098                                 biblioModule->citeEngineCO->currentIndex()).toString();
3099
3100         CiteEngineType const cet =
3101                 CiteEngineType(biblioModule->citeStyleCO->itemData(
3102                                                           biblioModule->citeStyleCO->currentIndex()).toInt());
3103
3104         updateDefaultBiblio(theCiteEnginesList[fromqstr(engine)]->getDefaultBiblio(cet), which);
3105 }
3106
3107
3108 void GuiDocument::resetDefaultBbxBibfile()
3109 {
3110         resetDefaultBibfile("bbx");
3111 }
3112
3113
3114 void GuiDocument::resetDefaultCbxBibfile()
3115 {
3116         resetDefaultBibfile("cbx");
3117 }
3118
3119
3120 void GuiDocument::citeEngineChanged(int n)
3121 {
3122         QString const engine =
3123                 biblioModule->citeEngineCO->itemData(n).toString();
3124
3125         vector<string> const engs =
3126                 theCiteEnginesList[fromqstr(engine)]->getEngineType();
3127
3128         updateCiteStyles(engs);
3129         updateEngineDependends();
3130         resetDefaultBibfile();
3131         biblioChanged();
3132 }
3133
3134
3135 void GuiDocument::updateEngineDependends()
3136 {
3137         bool const biblatex = isBiblatex();
3138
3139         // These are only useful with BibTeX
3140         biblioModule->defaultBiblioCO->setEnabled(!biblatex);
3141         biblioModule->bibtexStyleLA->setEnabled(!biblatex);
3142         biblioModule->resetDefaultBiblioPB->setEnabled(!biblatex);
3143         biblioModule->bibtopicCB->setEnabled(!biblatex);
3144
3145         // These are only useful with Biblatex
3146         biblioModule->biblatexBbxCO->setEnabled(biblatex);
3147         biblioModule->biblatexBbxLA->setEnabled(biblatex);
3148         biblioModule->biblatexCbxCO->setEnabled(biblatex);
3149         biblioModule->biblatexCbxLA->setEnabled(biblatex);
3150         biblioModule->resetBbxPB->setEnabled(biblatex);
3151         biblioModule->resetCbxPB->setEnabled(biblatex);
3152         biblioModule->matchBbxPB->setEnabled(biblatex);
3153
3154         // These are useful with biblatex, jurabib and natbib
3155         QString const engine =
3156                 biblioModule->citeEngineCO->itemData(
3157                                 biblioModule->citeEngineCO->currentIndex()).toString();
3158         LyXCiteEngine const * ce = theCiteEnginesList[fromqstr(engine)];
3159
3160         bool const citepack = ce->required("biblatex.sty") || ce->required("jurabib.sty")
3161                         || ce->required("natbib.sty");
3162         biblioModule->citePackageOptionsLE->setEnabled(citepack);
3163         biblioModule->citePackageOptionsL->setEnabled(citepack);
3164 }
3165
3166
3167 void GuiDocument::citeStyleChanged()
3168 {
3169         QString const engine =
3170                 biblioModule->citeEngineCO->itemData(
3171                                 biblioModule->citeEngineCO->currentIndex()).toString();
3172         QString const currentDef = isBiblatex() ?
3173                 biblioModule->biblatexBbxCO->currentText()
3174                 : biblioModule->defaultBiblioCO->currentText();
3175         if (theCiteEnginesList[fromqstr(engine)]->isDefaultBiblio(fromqstr(currentDef)))
3176                 resetDefaultBibfile();
3177
3178         biblioChanged();
3179 }
3180
3181
3182 void GuiDocument::bibtexChanged(int n)
3183 {
3184         biblioModule->bibtexOptionsLE->setEnabled(
3185                 biblioModule->bibtexCO->itemData(n).toString() != "default");
3186         biblioChanged();
3187 }
3188
3189
3190 void GuiDocument::updateCiteStyles(vector<string> const & engs, CiteEngineType const & sel)
3191 {
3192         biblioModule->citeStyleCO->clear();
3193
3194         vector<string>::const_iterator it  = engs.begin();
3195         vector<string>::const_iterator end = engs.end();
3196         for (; it != end; ++it) {
3197                 if (*it == "default")
3198                         biblioModule->citeStyleCO->addItem(qt_("Basic numerical"),
3199                                                            ENGINE_TYPE_DEFAULT);
3200                 else if (*it == "authoryear")
3201                         biblioModule->citeStyleCO->addItem(qt_("Author-year"),
3202                                                            ENGINE_TYPE_AUTHORYEAR);
3203                 else if (*it == "numerical")
3204                         biblioModule->citeStyleCO->addItem(qt_("Author-number"),
3205                                                            ENGINE_TYPE_NUMERICAL);
3206         }
3207         int i = biblioModule->citeStyleCO->findData(sel);
3208         if (biblioModule->citeStyleCO->findData(sel) == -1)
3209                 i = 0;
3210         biblioModule->citeStyleCO->setCurrentIndex(i);
3211
3212         biblioModule->citationStyleL->setEnabled(engs.size() > 1);
3213         biblioModule->citeStyleCO->setEnabled(engs.size() > 1);
3214 }
3215
3216
3217 void GuiDocument::updateEngineType(string const & items, CiteEngineType const & sel)
3218 {
3219         engine_types_.clear();
3220
3221         for (int n = 0; !token(items, '|', n).empty(); ++n) {
3222                 string style = token(items, '|', n);
3223                 engine_types_.push_back(style);
3224         }
3225
3226         updateCiteStyles(engine_types_, sel);
3227 }
3228
3229
3230 namespace {
3231         // FIXME unicode
3232         // both of these should take a vector<docstring>
3233
3234         // This is an insanely complicated attempt to make this sort of thing
3235         // work with RTL languages.
3236         docstring formatStrVec(vector<string> const & v, docstring const & s)
3237         {
3238                 //this mess formats the list as "v[0], v[1], ..., [s] v[n]"
3239                 if (v.empty())
3240                         return docstring();
3241                 if (v.size() == 1)
3242                         return translateIfPossible(from_utf8(v[0]));
3243                 if (v.size() == 2) {
3244                         docstring retval = _("%1$s and %2$s");
3245                         retval = subst(retval, _("and"), s);
3246                         return bformat(retval, translateIfPossible(from_utf8(v[0])),
3247                                        translateIfPossible(from_utf8(v[1])));
3248                 }
3249                 // The idea here is to format all but the last two items...
3250                 int const vSize = v.size();
3251                 docstring t2 = _("%1$s, %2$s");
3252                 docstring retval = translateIfPossible(from_utf8(v[0]));
3253                 for (int i = 1; i < vSize - 2; ++i)
3254                         retval = bformat(t2, retval, translateIfPossible(from_utf8(v[i])));
3255                 //...and then to  plug them, and the last two, into this schema
3256                 docstring t = _("%1$s, %2$s, and %3$s");
3257                 t = subst(t, _("and"), s);
3258                 return bformat(t, retval, translateIfPossible(from_utf8(v[vSize - 2])),
3259                                translateIfPossible(from_utf8(v[vSize - 1])));
3260         }
3261
3262         vector<string> idsToNames(vector<string> const & idList)
3263         {
3264                 vector<string> retval;
3265                 vector<string>::const_iterator it  = idList.begin();
3266                 vector<string>::const_iterator end = idList.end();
3267                 for (; it != end; ++it) {
3268                         LyXModule const * const mod = theModuleList[*it];
3269                         if (!mod)
3270                                 retval.push_back(to_utf8(bformat(_("%1$s (unavailable)"),
3271                                                 translateIfPossible(from_utf8(*it)))));
3272                         else
3273                                 retval.push_back(mod->getName());
3274                 }
3275                 return retval;
3276         }
3277 } // end anonymous namespace
3278
3279
3280 void GuiDocument::modulesToParams(BufferParams & bp)
3281 {
3282         // update list of loaded modules
3283         bp.clearLayoutModules();
3284         int const srows = modules_sel_model_.rowCount();
3285         for (int i = 0; i < srows; ++i)
3286                 bp.addLayoutModule(modules_sel_model_.getIDString(i));
3287         updateSelectedModules();
3288
3289         // update the list of removed modules
3290         bp.clearRemovedModules();
3291         LayoutModuleList const & reqmods = bp.baseClass()->defaultModules();
3292         list<string>::const_iterator rit = reqmods.begin();
3293         list<string>::const_iterator ren = reqmods.end();
3294
3295         // check each of the default modules
3296         for (; rit != ren; ++rit) {
3297                 list<string>::const_iterator mit = bp.getModules().begin();
3298                 list<string>::const_iterator men = bp.getModules().end();
3299                 bool found = false;
3300                 for (; mit != men; ++mit) {
3301                         if (*rit == *mit) {
3302                                 found = true;
3303                                 break;
3304                         }
3305                 }
3306                 if (!found) {
3307                         // the module isn't present so must have been removed by the user
3308                         bp.addRemovedModule(*rit);
3309                 }
3310         }
3311 }
3312
3313 void GuiDocument::modulesChanged()
3314 {
3315         modulesToParams(bp_);
3316
3317         if (buttonBox->button(QDialogButtonBox::Apply)->isEnabled()
3318             && (nonModuleChanged_ || shellescapeChanged_)) {
3319                 int const ret = Alert::prompt(_("Unapplied changes"),
3320                                 _("Some changes in the dialog were not yet applied.\n"
3321                                 "If you do not apply now, they will be lost after this action."),
3322                                 1, 1, _("&Apply"), _("&Dismiss"));
3323                 if (ret == 0)
3324                         applyView();
3325         }
3326
3327         modulesChanged_ = true;
3328         bp_.makeDocumentClass();
3329         paramsToDialog();
3330         changed();
3331 }
3332
3333
3334 void GuiDocument::updateModuleInfo()
3335 {
3336         selectionManager->update();
3337
3338         //Module description
3339         bool const focus_on_selected = selectionManager->selectedFocused();
3340         QAbstractItemView * lv;
3341         bool category = false;
3342         if (focus_on_selected) {
3343                 lv = modulesModule->selectedLV;
3344                 category = true;
3345         } else
3346                 lv = modulesModule->availableLV;
3347         if (lv->selectionModel()->selectedIndexes().isEmpty()) {
3348                 modulesModule->infoML->document()->clear();
3349                 return;
3350         }
3351         QModelIndex const & idx = lv->selectionModel()->currentIndex();
3352
3353         if (!idx.isValid())
3354                 return;
3355
3356         if (!focus_on_selected
3357             && modules_av_model_.itemFromIndex(idx)->hasChildren()) {
3358                 // This is a category header
3359                 modulesModule->infoML->document()->clear();
3360                 return;
3361         }
3362
3363         string const modName = focus_on_selected ?
3364                                 modules_sel_model_.getIDString(idx.row())
3365                               : fromqstr(modules_av_model_.data(idx, Qt::UserRole).toString());
3366         docstring desc = getModuleDescription(modName);
3367
3368         LayoutModuleList const & provmods = bp_.baseClass()->providedModules();
3369         if (std::find(provmods.begin(), provmods.end(), modName) != provmods.end()) {
3370                 if (!desc.empty())
3371                         desc += "\n";
3372                 desc += _("Module provided by document class.");
3373         }
3374
3375         if (category) {
3376                 docstring cat = getModuleCategory(modName);
3377                 if (!cat.empty()) {
3378                         if (!desc.empty())
3379                                 desc += "\n";
3380                         desc += bformat(_("<p><b>Category:</b> %1$s.</p>"),
3381                                         translateIfPossible(cat));
3382                 }
3383         }
3384
3385         vector<string> pkglist = getPackageList(modName);
3386         docstring pkgdesc = formatStrVec(pkglist, _("and"));
3387         if (!pkgdesc.empty()) {
3388                 if (!desc.empty())
3389                         desc += "\n";
3390                 desc += bformat(_("<p><b>Package(s) required:</b> %1$s.</p>"), pkgdesc);
3391         }
3392
3393         pkglist = getRequiredList(modName);
3394         if (!pkglist.empty()) {
3395                 vector<string> const reqdescs = idsToNames(pkglist);
3396                 pkgdesc = formatStrVec(reqdescs, _("or"));
3397                 if (!desc.empty())
3398                         desc += "\n";
3399                 desc += bformat(_("<p><b>Modules required:</b> %1$s.</p>"), pkgdesc);
3400         }
3401
3402         pkglist = getExcludedList(modName);
3403         if (!pkglist.empty()) {
3404                 vector<string> const reqdescs = idsToNames(pkglist);
3405                 pkgdesc = formatStrVec(reqdescs, _( "and"));
3406                 if (!desc.empty())
3407                         desc += "\n";
3408                 desc += bformat(_("<p><b>Modules excluded:</b> %1$s.</p>"), pkgdesc);
3409         }
3410
3411         if (!desc.empty())
3412                 desc += "\n";
3413         desc += bformat(_("<p><b>Filename:</b> <tt>%1$s.module</tt>.</p>"), from_utf8(modName));
3414
3415         if (!isModuleAvailable(modName)) {
3416                 if (!desc.empty())
3417                         desc += "\n";
3418                 desc += _("<p><font color=red><b>WARNING: Some required packages are unavailable!</b></font></p>");
3419         }
3420
3421         modulesModule->infoML->document()->setHtml(toqstr(desc));
3422 }
3423
3424
3425 void GuiDocument::updateNumbering()
3426 {
3427         DocumentClass const & tclass = documentClass();
3428
3429         numberingModule->tocTW->setUpdatesEnabled(false);
3430         numberingModule->tocTW->clear();
3431
3432         int const depth = numberingModule->depthSL->value();
3433         int const toc = numberingModule->tocSL->value();
3434         QString const no = qt_("No");
3435         QString const yes = qt_("Yes");
3436         QTreeWidgetItem * item = nullptr;
3437
3438         DocumentClass::const_iterator lit = tclass.begin();
3439         DocumentClass::const_iterator len = tclass.end();
3440         for (; lit != len; ++lit) {
3441                 int const toclevel = lit->toclevel;
3442                 if (toclevel != Layout::NOT_IN_TOC && !lit->counter.empty()) {
3443                         item = new QTreeWidgetItem(numberingModule->tocTW);
3444                         item->setText(0, toqstr(translateIfPossible(lit->name())));
3445                         item->setText(1, (toclevel <= depth) ? yes : no);
3446                         item->setText(2, (toclevel <= toc) ? yes : no);
3447                 }
3448         }
3449
3450         numberingModule->tocTW->setUpdatesEnabled(true);
3451         numberingModule->tocTW->update();
3452 }
3453
3454
3455 void GuiDocument::getTableStyles()
3456 {
3457         // We look for lyx files in the subdirectory dir of
3458         //   1) user_lyxdir
3459         //   2) build_lyxdir (if not empty)
3460         //   3) system_lyxdir
3461         // in this order. Files with a given sub-hierarchy will
3462         // only be listed once.
3463         // We also consider i18n subdirectories and store them separately.
3464         QStringList dirs;
3465
3466         // The three locations to look at.
3467         string const user = addPath(package().user_support().absFileName(), "tabletemplates");
3468         string const build = addPath(package().build_support().absFileName(), "tabletemplates");
3469         string const system = addPath(package().system_support().absFileName(), "tabletemplates");
3470
3471         dirs << toqstr(user)
3472              << toqstr(build)
3473              << toqstr(system);
3474
3475         for (int i = 0; i < dirs.size(); ++i) {
3476                 QString const & dir = dirs.at(i);
3477                 QDirIterator it(dir, QDir::Files, QDirIterator::Subdirectories);
3478                 while (it.hasNext()) {
3479                         QString fn = QFileInfo(it.next()).fileName();
3480                         if (!fn.endsWith(".lyx") || fn.contains("_1x"))
3481                                 continue;
3482                         QString data = fn.left(fn.lastIndexOf(".lyx"));
3483                         QString guiname = data;
3484                         guiname = toqstr(translateIfPossible(qstring_to_ucs4(guiname.replace('_', ' '))));
3485                         QString relpath = toqstr(makeRelPath(qstring_to_ucs4(fn),
3486                                                              qstring_to_ucs4(dir)));
3487                         if (textLayoutModule->tableStyleCO->findData(data) == -1)
3488                                 textLayoutModule->tableStyleCO->addItem(guiname, data);
3489                 }
3490         }
3491 }
3492
3493
3494 void GuiDocument::updateDefaultFormat()
3495 {
3496         if (!bufferview())
3497                 return;
3498         // make a copy in order to consider unapplied changes
3499         BufferParams param_copy = buffer().params();
3500         param_copy.useNonTeXFonts = fontModule->osFontsCB->isChecked();
3501         int const idx = latexModule->classCO->currentIndex();
3502         if (idx >= 0) {
3503                 string const classname = fromqstr(latexModule->classCO->getData(idx));
3504                 param_copy.setBaseClass(classname, buffer().layoutPos());
3505                 param_copy.makeDocumentClass(true);
3506         }
3507         outputModule->defaultFormatCO->blockSignals(true);
3508         outputModule->defaultFormatCO->clear();
3509         outputModule->defaultFormatCO->addItem(qt_("Default"),
3510                                 QVariant(QString("default")));
3511         FormatList const & formats =
3512                                 param_copy.exportableFormats(true);
3513         for (Format const * f : formats)
3514                 outputModule->defaultFormatCO->addItem
3515                         (toqstr(translateIfPossible(f->prettyname())),
3516                          QVariant(toqstr(f->name())));
3517         outputModule->defaultFormatCO->blockSignals(false);
3518 }
3519
3520
3521 bool GuiDocument::isChildIncluded(string const & child)
3522 {
3523         if (includeonlys_.empty())
3524                 return false;
3525         return (std::find(includeonlys_.begin(),
3526                           includeonlys_.end(), child) != includeonlys_.end());
3527 }
3528
3529
3530 void GuiDocument::applyView()
3531 {
3532         // auto-validate local layout
3533         if (!localLayout->isValid()) {
3534                 localLayout->validate();
3535                 if (!localLayout->isValid()) {
3536                         setApplyStopped(true);
3537                         docPS->setCurrentPanel(N_("Local Layout"));
3538                         return;
3539                 }
3540         }
3541
3542         // preamble
3543         preambleModule->apply(bp_);
3544         localLayout->apply(bp_);
3545
3546         // date
3547         bp_.suppress_date = latexModule->suppressDateCB->isChecked();
3548         bp_.use_refstyle  = latexModule->refstyleCB->isChecked();
3549
3550         // biblio
3551         string const engine =
3552                 fromqstr(biblioModule->citeEngineCO->itemData(
3553                                 biblioModule->citeEngineCO->currentIndex()).toString());
3554         bp_.setCiteEngine(engine);
3555
3556         CiteEngineType const style = CiteEngineType(biblioModule->citeStyleCO->itemData(
3557                 biblioModule->citeStyleCO->currentIndex()).toInt());
3558         if (theCiteEnginesList[engine]->hasEngineType(style))
3559                 bp_.setCiteEngineType(style);
3560         else
3561                 bp_.setCiteEngineType(ENGINE_TYPE_DEFAULT);
3562
3563         bp_.splitbib(biblioModule->bibtopicCB->isChecked());
3564
3565         bp_.multibib = fromqstr(biblioModule->bibunitsCO->itemData(
3566                                 biblioModule->bibunitsCO->currentIndex()).toString());
3567
3568         bp_.setDefaultBiblioStyle(fromqstr(biblioModule->defaultBiblioCO->currentText()));
3569
3570         bp_.biblatex_bibstyle = fromqstr(biblioModule->biblatexBbxCO->currentText());
3571         bp_.biblatex_citestyle = fromqstr(biblioModule->biblatexCbxCO->currentText());
3572         bp_.biblio_opts = fromqstr(biblioModule->citePackageOptionsLE->text());
3573
3574         string const bibtex_command =
3575                 fromqstr(biblioModule->bibtexCO->itemData(
3576                         biblioModule->bibtexCO->currentIndex()).toString());
3577         string const bibtex_options =
3578                 fromqstr(biblioModule->bibtexOptionsLE->text());
3579         if (bibtex_command == "default" || bibtex_options.empty())
3580                 bp_.bibtex_command = bibtex_command;
3581         else
3582                 bp_.bibtex_command = bibtex_command + " " + bibtex_options;
3583
3584         if (biblioChanged_) {
3585                 buffer().invalidateBibinfoCache();
3586                 buffer().removeBiblioTempFiles();
3587         }
3588
3589         // Indices
3590         indicesModule->apply(bp_);
3591
3592         // language & quotes
3593         switch (langModule->encodingCO->currentIndex()) {
3594                 case EncodingSets::unicode: {
3595                         if (!fontModule->osFontsCB->isChecked())
3596                                 bp_.inputenc = fromqstr(langModule->unicodeEncodingCO->itemData(
3597                                         langModule->unicodeEncodingCO->currentIndex()).toString());
3598                         break;
3599                 }
3600                 case EncodingSets::legacy: {
3601                         bp_.inputenc = "auto-legacy";
3602                         bp_.inputenc = fromqstr(langModule->autoEncodingCO->itemData(
3603                                 langModule->autoEncodingCO->currentIndex()).toString());
3604                         break;
3605                 }
3606                 case EncodingSets::custom: {
3607                         bp_.inputenc = fromqstr(langModule->customEncodingCO->itemData(
3608                                 langModule->customEncodingCO->currentIndex()).toString());
3609                         break;
3610                 }
3611                 default:
3612                         // this should never happen
3613                         bp_.inputenc = "utf8";
3614         }
3615         bp_.quotes_style = QuoteStyle(langModule->quoteStyleCO->itemData(
3616                 langModule->quoteStyleCO->currentIndex()).toInt());
3617         bp_.dynamic_quotes = langModule->dynamicQuotesCB->isChecked();
3618
3619         QString const langname = langModule->languageCO->itemData(
3620                 langModule->languageCO->currentIndex()).toString();
3621         Language const * newlang = lyx::languages.getLanguage(fromqstr(langname));
3622         Cursor & cur = const_cast<BufferView *>(bufferview())->cursor();
3623         // If current cursor language was the document language, then update it too.
3624         if (cur.current_font.language() == bp_.language) {
3625                 cur.current_font.setLanguage(newlang);
3626                 cur.real_current_font.setLanguage(newlang);
3627         }
3628         bp_.language = newlang;
3629
3630         QString const pack = langModule->languagePackageCO->itemData(
3631                 langModule->languagePackageCO->currentIndex()).toString();
3632         if (pack == "custom")
3633                 bp_.lang_package =
3634                         fromqstr(langModule->languagePackageLE->text());
3635         else
3636                 bp_.lang_package = fromqstr(pack);
3637
3638         //color
3639         bp_.backgroundcolor = set_backgroundcolor;
3640         bp_.isbackgroundcolor = is_backgroundcolor;
3641         bp_.fontcolor = set_fontcolor;
3642         bp_.isfontcolor = is_fontcolor;
3643         bp_.notefontcolor = set_notefontcolor;
3644         bp_.isnotefontcolor = is_notefontcolor;
3645         if (is_notefontcolor) {
3646                 // Set information used in statusbar (#12130)
3647                 lcolor.setColor("notefontcolor", lyx::X11hexname(set_notefontcolor));
3648                 lcolor.setGUIName("notefontcolor", N_("greyedout inset text"));
3649         }
3650         bp_.boxbgcolor = set_boxbgcolor;
3651         bp_.isboxbgcolor = is_boxbgcolor;
3652
3653         // numbering
3654         if (bp_.documentClass().hasTocLevels()) {
3655                 bp_.tocdepth = numberingModule->tocSL->value();
3656                 bp_.secnumdepth = numberingModule->depthSL->value();
3657         }
3658         bp_.use_lineno = numberingModule->linenoCB->isChecked();
3659         bp_.lineno_opts = fromqstr(numberingModule->linenoLE->text());
3660
3661         // bullets
3662         bp_.user_defined_bullet(0) = bulletsModule->bullet(0);
3663         bp_.user_defined_bullet(1) = bulletsModule->bullet(1);
3664         bp_.user_defined_bullet(2) = bulletsModule->bullet(2);
3665         bp_.user_defined_bullet(3) = bulletsModule->bullet(3);
3666
3667         // packages
3668         bp_.graphics_driver =
3669                 tex_graphics[latexModule->psdriverCO->currentIndex()];
3670
3671         // text layout
3672         int idx = latexModule->classCO->currentIndex();
3673         if (idx >= 0) {
3674                 string const classname = fromqstr(latexModule->classCO->getData(idx));
3675                 bp_.setBaseClass(classname, buffer().layoutPos());
3676         }
3677
3678         // Modules
3679         modulesToParams(bp_);
3680
3681         // Math
3682         map<string, string> const & packages = BufferParams::auto_packages();
3683         for (map<string, string>::const_iterator it = packages.begin();
3684              it != packages.end(); ++it) {
3685                 QTableWidgetItem * item = mathsModule->packagesTW->findItems(toqstr(it->first), Qt::MatchExactly)[0];
3686                 if (!item)
3687                         continue;
3688                 int row = mathsModule->packagesTW->row(item);
3689
3690                 QRadioButton * rb =
3691                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 1)->layout()->itemAt(0)->widget();
3692                 if (rb->isChecked()) {
3693                         bp_.use_package(it->first, BufferParams::package_auto);
3694                         continue;
3695                 }
3696                 rb = (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 2)->layout()->itemAt(0)->widget();
3697                 if (rb->isChecked()) {
3698                         bp_.use_package(it->first, BufferParams::package_on);
3699                         continue;
3700                 }
3701                 rb = (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 3)->layout()->itemAt(0)->widget();
3702                 if (rb->isChecked())
3703                         bp_.use_package(it->first, BufferParams::package_off);
3704         }
3705         // if math is indented
3706         bp_.is_math_indent = mathsModule->MathIndentCB->isChecked();
3707         if (bp_.is_math_indent) {
3708                 // if formulas are indented
3709                 if (mathsModule->MathIndentCO->itemData(mathsModule->MathIndentCO->currentIndex()) == "custom") {
3710                         Length mathindent(widgetsToLength(mathsModule->MathIndentLE,
3711                                                           mathsModule->MathIndentLengthCO));
3712                         bp_.setMathIndent(mathindent);
3713                 } else
3714                         // default
3715                         bp_.setMathIndent(Length());
3716         }
3717         switch (mathsModule->MathNumberingPosCO->currentIndex()) {
3718                 case 0:
3719                         bp_.math_numbering_side = BufferParams::LEFT;
3720                         break;
3721                 case 1:
3722                         bp_.math_numbering_side = BufferParams::DEFAULT;
3723                         break;
3724                 case 2:
3725                         bp_.math_numbering_side = BufferParams::RIGHT;
3726                         break;
3727                 default:
3728                         // this should never happen
3729                         bp_.math_numbering_side = BufferParams::DEFAULT;
3730                         break;
3731         }
3732
3733         // Page Layout
3734         if (pageLayoutModule->pagestyleCO->currentIndex() == 0)
3735                 bp_.pagestyle = "default";
3736         else {
3737                 QString style_gui = pageLayoutModule->pagestyleCO->currentText();
3738                 for (size_t i = 0; i != pagestyles.size(); ++i)
3739                         if (pagestyles[i].second == style_gui)
3740                                 bp_.pagestyle = pagestyles[i].first;
3741         }
3742
3743         // Text Layout
3744         switch (textLayoutModule->lspacingCO->currentIndex()) {
3745         case 0:
3746                 bp_.spacing().set(Spacing::Single);
3747                 break;
3748         case 1:
3749                 bp_.spacing().set(Spacing::Onehalf);
3750                 break;
3751         case 2:
3752                 bp_.spacing().set(Spacing::Double);
3753                 break;
3754         case 3: {
3755                 string s = widgetToDoubleStr(textLayoutModule->lspacingLE);
3756                 if (s.empty())
3757                         bp_.spacing().set(Spacing::Single);
3758                 else
3759                         bp_.spacing().set(Spacing::Other, s);
3760                 break;
3761                 }
3762         }
3763
3764         if (textLayoutModule->twoColumnCB->isChecked())
3765                 bp_.columns = 2;
3766         else
3767                 bp_.columns = 1;
3768
3769         bp_.justification = textLayoutModule->justCB->isChecked();
3770
3771         if (textLayoutModule->indentRB->isChecked()) {
3772                 // if paragraphs are separated by an indentation
3773                 bp_.paragraph_separation = BufferParams::ParagraphIndentSeparation;
3774                 if (textLayoutModule->indentCO->itemData(textLayoutModule->indentCO->currentIndex()) == "custom") {
3775                         Length parindent(widgetsToLength(textLayoutModule->indentLE,
3776                                                          textLayoutModule->indentLengthCO));
3777                         bp_.setParIndent(parindent);
3778                 } else
3779                         // default
3780                         bp_.setParIndent(Length());
3781         } else {
3782                 // if paragraphs are separated by a skip
3783                 bp_.paragraph_separation = BufferParams::ParagraphSkipSeparation;
3784                 VSpace::VSpaceKind spacekind =
3785                         VSpace::VSpaceKind(textLayoutModule->skipCO->itemData(textLayoutModule->skipCO->currentIndex()).toInt());
3786                 switch (spacekind) {
3787                 case VSpace::SMALLSKIP:
3788                 case VSpace::MEDSKIP:
3789                 case VSpace::BIGSKIP:
3790                 case VSpace::HALFLINE:
3791                 case VSpace::FULLLINE:
3792                         bp_.setDefSkip(VSpace(spacekind));
3793                         break;
3794                 case VSpace::LENGTH: {
3795                         VSpace vs = VSpace(
3796                                 widgetsToLength(textLayoutModule->skipLE,
3797                                 textLayoutModule->skipLengthCO)
3798                                 );
3799                         bp_.setDefSkip(vs);
3800                         break;
3801                 }
3802                 default:
3803                         // this should never happen
3804                         bp_.setDefSkip(VSpace(VSpace::MEDSKIP));
3805                         break;
3806                 }
3807         }
3808         bp_.tablestyle = fromqstr(textLayoutModule->tableStyleCO->itemData(
3809                                       textLayoutModule->tableStyleCO->currentIndex()).toString());
3810
3811         bp_.options =
3812                 fromqstr(latexModule->optionsLE->text());
3813
3814         bp_.use_default_options =
3815                 latexModule->defaultOptionsCB->isChecked();
3816
3817         if (latexModule->childDocGB->isChecked())
3818                 bp_.master =
3819                         fromqstr(latexModule->childDocLE->text());
3820         else
3821                 bp_.master = string();
3822
3823         // Master/Child
3824         bp_.clearIncludedChildren();
3825         updateIncludeonlys();
3826         if (masterChildModule->includeonlyRB->isChecked()) {
3827                 list<string>::const_iterator it = includeonlys_.begin();
3828                 for (; it != includeonlys_.end() ; ++it) {
3829                         bp_.addIncludedChildren(*it);
3830                 }
3831         }
3832         if (masterChildModule->maintainCRNoneRB->isChecked())
3833                 bp_.maintain_unincluded_children =
3834                         BufferParams::CM_None;
3835         else if (masterChildModule->maintainCRMostlyRB->isChecked())
3836                 bp_.maintain_unincluded_children =
3837                         BufferParams::CM_Mostly;
3838         else
3839                 bp_.maintain_unincluded_children =
3840                         BufferParams::CM_Strict;
3841         updateIncludeonlyDisplay();
3842
3843         // Float Settings
3844         bp_.float_placement = floatModule->getPlacement();
3845         bp_.float_alignment = floatModule->getAlignment();
3846
3847         // Listings
3848         // text should have passed validation
3849         idx = listingsModule->packageCO->currentIndex();
3850         bp_.use_minted = string(lst_packages[idx]) == "Minted";
3851         bp_.listings_params =
3852                 InsetListingsParams(fromqstr(listingsModule->listingsED->toPlainText())).params();
3853
3854         // Formats
3855         bp_.default_output_format = fromqstr(outputModule->defaultFormatCO->itemData(
3856                 outputModule->defaultFormatCO->currentIndex()).toString());
3857
3858         bool const nontexfonts = fontModule->osFontsCB->isChecked();
3859         bp_.useNonTeXFonts = nontexfonts;
3860
3861         bp_.shell_escape = outputModule->shellescapeCB->isChecked();
3862         if (!bp_.shell_escape)
3863             theSession().shellescapeFiles().remove(buffer().absFileName());
3864         else if (!theSession().shellescapeFiles().find(buffer().absFileName()))
3865             theSession().shellescapeFiles().insert(buffer().absFileName());
3866         Buffer & buf = const_cast<Buffer &>(buffer());
3867         buf.params().shell_escape = bp_.shell_escape;
3868
3869         bp_.output_sync = outputModule->outputsyncCB->isChecked();
3870
3871         bp_.output_sync_macro = fromqstr(outputModule->synccustomCB->currentText());
3872
3873         int mathfmt = outputModule->mathoutCB->currentIndex();
3874         if (mathfmt == -1)
3875                 mathfmt = 0;
3876         BufferParams::MathOutput const mo =
3877                 static_cast<BufferParams::MathOutput>(mathfmt);
3878         bp_.html_math_output = mo;
3879         bp_.html_be_strict = outputModule->strictCB->isChecked();
3880         bp_.html_css_as_file = outputModule->cssCB->isChecked();
3881         bp_.html_math_img_scale = outputModule->mathimgSB->value();
3882         bp_.display_pixel_ratio = theGuiApp()->pixelRatio();
3883
3884         int tablefmt = outputModule->tableoutCB->currentIndex();
3885         if (tablefmt == -1)
3886                 tablefmt = 0;
3887         auto const to = static_cast<BufferParams::TableOutput>(tablefmt);
3888         bp_.docbook_table_output = to;
3889
3890         int mathmlprefix = outputModule->mathmlprefixCB->currentIndex();
3891         if (mathmlprefix == -1)
3892                 mathmlprefix = 0;
3893         auto const mp = static_cast<BufferParams::MathMLNameSpacePrefix>(mathmlprefix);
3894         bp_.docbook_mathml_prefix = mp;
3895
3896         bp_.save_transient_properties =
3897                 outputModule->saveTransientPropertiesCB->isChecked();
3898         bp_.postpone_fragile_content =
3899                 outputModule->postponeFragileCB->isChecked();
3900
3901         // fonts
3902         bp_.fonts_roman[nontexfonts] =
3903                 fromqstr(fontModule->fontsRomanCO->
3904                         getData(fontModule->fontsRomanCO->currentIndex()));
3905         bp_.fonts_roman[!nontexfonts] = fromqstr(fontModule->font_roman);
3906         bp_.font_roman_opts = fromqstr(fontModule->fontspecRomanLE->text());
3907
3908         bp_.fonts_sans[nontexfonts] =
3909                 fromqstr(fontModule->fontsSansCO->
3910                         getData(fontModule->fontsSansCO->currentIndex()));
3911         bp_.fonts_sans[!nontexfonts] = fromqstr(fontModule->font_sans);
3912         bp_.font_sans_opts = fromqstr(fontModule->fontspecSansLE->text());
3913
3914         bp_.fonts_typewriter[nontexfonts] =
3915                 fromqstr(fontModule->fontsTypewriterCO->
3916                         getData(fontModule->fontsTypewriterCO->currentIndex()));
3917         bp_.fonts_typewriter[!nontexfonts] = fromqstr(fontModule->font_typewriter);
3918         bp_.font_typewriter_opts = fromqstr(fontModule->fontspecTypewriterLE->text());
3919
3920         bp_.fonts_math[nontexfonts] =
3921                 fromqstr(fontModule->fontsMathCO->
3922                         itemData(fontModule->fontsMathCO->currentIndex()).toString());
3923         bp_.fonts_math[!nontexfonts] = fromqstr(fontModule->font_math);
3924
3925         QString const fontenc =
3926                 fontModule->fontencCO->itemData(fontModule->fontencCO->currentIndex()).toString();
3927         if (fontenc == "custom")
3928                 bp_.fontenc = fromqstr(fontModule->fontencLE->text());
3929         else
3930                 bp_.fontenc = fromqstr(fontenc);
3931
3932         bp_.fonts_cjk =
3933                 fromqstr(fontModule->cjkFontLE->text());
3934
3935         bp_.use_microtype = fontModule->microtypeCB->isChecked();
3936         bp_.use_dash_ligatures = !fontModule->dashesCB->isChecked();
3937
3938         bp_.fonts_sans_scale[nontexfonts] = fontModule->scaleSansSB->value();
3939         bp_.fonts_sans_scale[!nontexfonts] = fontModule->font_sf_scale;
3940
3941         bp_.fonts_typewriter_scale[nontexfonts] = fontModule->scaleTypewriterSB->value();
3942         bp_.fonts_typewriter_scale[!nontexfonts] = fontModule->font_tt_scale;
3943
3944         bp_.fonts_expert_sc = fontModule->fontScCB->isChecked();
3945
3946         bp_.fonts_roman_osf = fontModule->fontOsfCB->isChecked();
3947         bp_.fonts_sans_osf = fontModule->fontSansOsfCB->isChecked();
3948         bp_.fonts_typewriter_osf = fontModule->fontTypewriterOsfCB->isChecked();
3949
3950         bp_.fonts_default_family = GuiDocument::fontfamilies[
3951                 fontModule->fontsDefaultCO->currentIndex()];
3952
3953         if (fontModule->fontsizeCO->currentIndex() == 0)
3954                 bp_.fontsize = "default";
3955         else
3956                 bp_.fontsize =
3957                         fromqstr(fontModule->fontsizeCO->currentText());
3958
3959         // paper
3960         bp_.papersize = PAPER_SIZE(
3961                 pageLayoutModule->papersizeCO->currentIndex());
3962
3963         bp_.paperwidth = widgetsToLength(pageLayoutModule->paperwidthLE,
3964                 pageLayoutModule->paperwidthUnitCO);
3965
3966         bp_.paperheight = widgetsToLength(pageLayoutModule->paperheightLE,
3967                 pageLayoutModule->paperheightUnitCO);
3968
3969         if (pageLayoutModule->facingPagesCB->isChecked())
3970                 bp_.sides = TwoSides;
3971         else
3972                 bp_.sides = OneSide;
3973
3974         if (pageLayoutModule->landscapeRB->isChecked())
3975                 bp_.orientation = ORIENTATION_LANDSCAPE;
3976         else
3977                 bp_.orientation = ORIENTATION_PORTRAIT;
3978
3979         // margins
3980         bp_.use_geometry = !marginsModule->marginCB->isChecked();
3981
3982         Ui::MarginsUi const * m = marginsModule;
3983
3984         bp_.leftmargin = widgetsToLength(m->innerLE, m->innerUnit);
3985         bp_.topmargin = widgetsToLength(m->topLE, m->topUnit);
3986         bp_.rightmargin = widgetsToLength(m->outerLE, m->outerUnit);
3987         bp_.bottommargin = widgetsToLength(m->bottomLE, m->bottomUnit);
3988         bp_.headheight = widgetsToLength(m->headheightLE, m->headheightUnit);
3989         bp_.headsep = widgetsToLength(m->headsepLE, m->headsepUnit);
3990         bp_.footskip = widgetsToLength(m->footskipLE, m->footskipUnit);
3991         bp_.columnsep = widgetsToLength(m->columnsepLE, m->columnsepUnit);
3992
3993         // branches
3994         branchesModule->apply(bp_);
3995
3996         // PDF support
3997         PDFOptions & pdf = bp_.pdfoptions();
3998         pdf.use_hyperref = pdfSupportModule->use_hyperrefGB->isChecked();
3999         pdf.title = fromqstr(pdfSupportModule->titleLE->text());
4000         pdf.author = fromqstr(pdfSupportModule->authorLE->text());
4001         pdf.subject = fromqstr(pdfSupportModule->subjectLE->text());
4002         pdf.keywords = fromqstr(pdfSupportModule->keywordsLE->text());
4003
4004         pdf.bookmarks = pdfSupportModule->bookmarksGB->isChecked();
4005         pdf.bookmarksnumbered = pdfSupportModule->bookmarksnumberedCB->isChecked();
4006         pdf.bookmarksopen = pdfSupportModule->bookmarksopenGB->isChecked();
4007         pdf.bookmarksopenlevel = pdfSupportModule->bookmarksopenlevelSB->value();
4008
4009         pdf.breaklinks = pdfSupportModule->breaklinksCB->isChecked();
4010         pdf.pdfborder = pdfSupportModule->pdfborderCB->isChecked();
4011         pdf.pdfusetitle = pdfSupportModule->pdfusetitleCB->isChecked();
4012         pdf.colorlinks = pdfSupportModule->colorlinksCB->isChecked();
4013         pdf.backref =
4014                 backref_opts[pdfSupportModule->backrefCO->currentIndex()];
4015         if (pdfSupportModule->fullscreenCB->isChecked())
4016                 pdf.pagemode = pdf.pagemode_fullscreen;
4017         else
4018                 pdf.pagemode.clear();
4019         pdf.quoted_options = pdf.quoted_options_check(
4020                                 fromqstr(pdfSupportModule->optionsTE->toPlainText()));
4021         bp_.document_metadata = qstring_to_ucs4(pdfSupportModule->metadataTE->toPlainText()
4022                                                 .trimmed().replace(QRegularExpression("\n+"), "\n"));
4023
4024         // change tracking
4025         bp_.track_changes = changesModule->trackChangesCB->isChecked();
4026         bp_.output_changes = changesModule->outputChangesCB->isChecked();
4027         bool const cb_switched_off = (bp_.change_bars
4028                                       && !changesModule->changeBarsCB->isChecked());
4029         bp_.change_bars = changesModule->changeBarsCB->isChecked();
4030         if (cb_switched_off)
4031                 // if change bars have been switched off,
4032                 // we need to ditch the aux file
4033                 buffer().requireFreshStart(true);
4034
4035         // reset trackers
4036         nonModuleChanged_ = false;
4037         shellescapeChanged_ = false;
4038 }
4039
4040
4041 void GuiDocument::paramsToDialog()
4042 {
4043         // set the default unit
4044         Length::UNIT const default_unit = Length::defaultUnit();
4045
4046         // preamble
4047         preambleModule->update(bp_, id());
4048         localLayout->update(bp_, id());
4049
4050         // date
4051         latexModule->suppressDateCB->setChecked(bp_.suppress_date);
4052         latexModule->refstyleCB->setChecked(bp_.use_refstyle);
4053
4054         // biblio
4055         string const cite_engine = bp_.citeEngine();
4056
4057         biblioModule->citeEngineCO->setCurrentIndex(
4058                 biblioModule->citeEngineCO->findData(toqstr(cite_engine)));
4059
4060         updateEngineType(documentClass().opt_enginetype(),
4061                 bp_.citeEngineType());
4062
4063         checkPossibleCiteEngines();
4064
4065         biblioModule->citeStyleCO->setCurrentIndex(
4066                 biblioModule->citeStyleCO->findData(bp_.citeEngineType()));
4067
4068         biblioModule->bibtopicCB->setChecked(bp_.splitbib());
4069
4070         biblioModule->bibunitsCO->clear();
4071         biblioModule->bibunitsCO->addItem(qt_("No"), QString());
4072         if (documentClass().hasLaTeXLayout("part"))
4073                 biblioModule->bibunitsCO->addItem(qt_("per part"), toqstr("part"));
4074         if (documentClass().hasLaTeXLayout("chapter"))
4075                 biblioModule->bibunitsCO->addItem(qt_("per chapter"), toqstr("chapter"));
4076         if (documentClass().hasLaTeXLayout("section"))
4077                 biblioModule->bibunitsCO->addItem(qt_("per section"), toqstr("section"));
4078         if (documentClass().hasLaTeXLayout("subsection"))
4079                 biblioModule->bibunitsCO->addItem(qt_("per subsection"), toqstr("subsection"));
4080         biblioModule->bibunitsCO->addItem(qt_("per child document"), toqstr("child"));
4081
4082         int const mbpos = biblioModule->bibunitsCO->findData(toqstr(bp_.multibib));
4083         if (mbpos != -1)
4084                 biblioModule->bibunitsCO->setCurrentIndex(mbpos);
4085         else
4086                 biblioModule->bibunitsCO->setCurrentIndex(0);
4087
4088         updateEngineDependends();
4089
4090         if (isBiblatex()) {
4091                 updateDefaultBiblio(bp_.biblatex_bibstyle, "bbx");
4092                 updateDefaultBiblio(bp_.biblatex_citestyle, "cbx");
4093         } else
4094                 updateDefaultBiblio(bp_.defaultBiblioStyle());
4095
4096         biblioModule->citePackageOptionsLE->setText(toqstr(bp_.biblio_opts));
4097
4098         string command;
4099         string options =
4100                 split(bp_.bibtex_command, command, ' ');
4101
4102         int bpos = biblioModule->bibtexCO->findData(toqstr(command));
4103         if (bpos == -1) {
4104                 // We add and set the unknown compiler, indicating that it is unavailable
4105                 // to assure document compilation and for security reasons, a fallback
4106                 // will be used on document processing stage
4107                 biblioModule->bibtexCO->addItem(toqstr(bformat(_("%1$s (not available)"),
4108                                                         from_utf8(command))), toqstr(command));
4109                 bpos = biblioModule->bibtexCO->findData(toqstr(command));
4110         }
4111         biblioModule->bibtexCO->setCurrentIndex(bpos);
4112         biblioModule->bibtexOptionsLE->setText(toqstr(options).trimmed());
4113         biblioModule->bibtexOptionsLE->setEnabled(
4114                 biblioModule->bibtexCO->currentIndex() != 0);
4115
4116         biblioChanged_ = false;
4117
4118         // indices
4119         // We may be called when there is no Buffer, e.g., when
4120         // the last view has just been closed.
4121         bool const isReadOnly = isBufferAvailable() ? buffer().isReadonly() : false;
4122         indicesModule->update(bp_, isReadOnly);
4123
4124         // language & quotes
4125         int const pos = langModule->languageCO->findData(toqstr(
4126                 bp_.language->lang()));
4127         langModule->languageCO->setCurrentIndex(pos);
4128
4129         updateQuoteStyles();
4130
4131         langModule->quoteStyleCO->setCurrentIndex(
4132                 langModule->quoteStyleCO->findData(static_cast<int>(bp_.quotes_style)));
4133         langModule->dynamicQuotesCB->setChecked(bp_.dynamic_quotes);
4134
4135         // LaTeX input encoding: set after the fonts (see below)
4136
4137         int p = langModule->languagePackageCO->findData(toqstr(bp_.lang_package));
4138         if (p == -1) {
4139                 langModule->languagePackageCO->setCurrentIndex(
4140                           langModule->languagePackageCO->findData("custom"));
4141                 langModule->languagePackageLE->setText(toqstr(bp_.lang_package));
4142         } else {
4143                 langModule->languagePackageCO->setCurrentIndex(p);
4144                 langModule->languagePackageLE->clear();
4145         }
4146
4147         //color
4148         if (bp_.isfontcolor) {
4149                 colorModule->mainTextCF->setStyleSheet(
4150                         colorFrameStyleSheet(rgb2qcolor(bp_.fontcolor)));
4151                 colorModule->mainTextCF->setVisible(true);
4152         } else
4153                 colorModule->mainTextCF->setVisible(false);
4154         set_fontcolor = bp_.fontcolor;
4155         is_fontcolor = bp_.isfontcolor;
4156
4157         colorModule->noteFontCF->setStyleSheet(
4158                 colorFrameStyleSheet(rgb2qcolor(bp_.notefontcolor)));
4159         set_notefontcolor = bp_.notefontcolor;
4160         is_notefontcolor = bp_.isnotefontcolor;
4161
4162         if (bp_.isbackgroundcolor) {
4163                 colorModule->pageBackgroundCF->setStyleSheet(
4164                         colorFrameStyleSheet(rgb2qcolor(bp_.backgroundcolor)));
4165                 colorModule->pageBackgroundCF->setVisible(true);
4166         } else
4167                 colorModule->pageBackgroundCF->setVisible(false);
4168         set_backgroundcolor = bp_.backgroundcolor;
4169         is_backgroundcolor = bp_.isbackgroundcolor;
4170
4171         colorModule->boxBackgroundCF->setStyleSheet(
4172                 colorFrameStyleSheet(rgb2qcolor(bp_.boxbgcolor)));
4173         set_boxbgcolor = bp_.boxbgcolor;
4174         is_boxbgcolor = bp_.isboxbgcolor;
4175
4176         // numbering
4177         int const min_toclevel = documentClass().min_toclevel();
4178         int const max_toclevel = documentClass().max_toclevel();
4179         if (documentClass().hasTocLevels()) {
4180                 numberingModule->setEnabled(true);
4181                 numberingModule->depthSL->setMinimum(min_toclevel - 1);
4182                 numberingModule->depthSL->setMaximum(max_toclevel);
4183                 numberingModule->depthSL->setValue(bp_.secnumdepth);
4184                 numberingModule->tocSL->setMaximum(min_toclevel - 1);
4185                 numberingModule->tocSL->setMaximum(max_toclevel);
4186                 numberingModule->tocSL->setValue(bp_.tocdepth);
4187                 updateNumbering();
4188         } else {
4189                 numberingModule->setEnabled(false);
4190                 numberingModule->tocTW->clear();
4191         }
4192
4193         numberingModule->linenoCB->setChecked(bp_.use_lineno);
4194         numberingModule->linenoLE->setEnabled(bp_.use_lineno);
4195         numberingModule->linenoLA->setEnabled(bp_.use_lineno);
4196         numberingModule->linenoLE->setText(toqstr(bp_.lineno_opts));
4197
4198         // bullets
4199         bulletsModule->setBullet(0, bp_.user_defined_bullet(0));
4200         bulletsModule->setBullet(1, bp_.user_defined_bullet(1));
4201         bulletsModule->setBullet(2, bp_.user_defined_bullet(2));
4202         bulletsModule->setBullet(3, bp_.user_defined_bullet(3));
4203         bulletsModule->init();
4204
4205         // packages
4206         int nitem = findToken(tex_graphics, bp_.graphics_driver);
4207         if (nitem >= 0)
4208                 latexModule->psdriverCO->setCurrentIndex(nitem);
4209         updateModuleInfo();
4210
4211         // math
4212         mathsModule->MathIndentCB->setChecked(bp_.is_math_indent);
4213         if (bp_.is_math_indent) {
4214                 Length const mathindent = bp_.getMathIndent();
4215                 int indent = 0;
4216                 if (!mathindent.empty()) {
4217                         lengthToWidgets(mathsModule->MathIndentLE,
4218                                         mathsModule->MathIndentLengthCO,
4219                                         mathindent, default_unit);
4220                         indent = 1;
4221                 }
4222                 mathsModule->MathIndentCO->setCurrentIndex(indent);
4223                 enableMathIndent(indent);
4224         }
4225         switch(bp_.math_numbering_side) {
4226         case BufferParams::LEFT:
4227                 mathsModule->MathNumberingPosCO->setCurrentIndex(0);
4228                 break;
4229         case BufferParams::DEFAULT:
4230                 mathsModule->MathNumberingPosCO->setCurrentIndex(1);
4231                 break;
4232         case BufferParams::RIGHT:
4233                 mathsModule->MathNumberingPosCO->setCurrentIndex(2);
4234         }
4235
4236         map<string, string> const & packages = BufferParams::auto_packages();
4237         for (map<string, string>::const_iterator it = packages.begin();
4238              it != packages.end(); ++it) {
4239                 QTableWidgetItem * item = mathsModule->packagesTW->findItems(toqstr(it->first), Qt::MatchExactly)[0];
4240                 if (!item)
4241                         continue;
4242                 int row = mathsModule->packagesTW->row(item);
4243                 switch (bp_.use_package(it->first)) {
4244                         case BufferParams::package_off: {
4245                                 QRadioButton * rb =
4246                                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 3)->layout()->itemAt(0)->widget();
4247                                 rb->setChecked(true);
4248                                 break;
4249                         }
4250                         case BufferParams::package_on: {
4251                                 QRadioButton * rb =
4252                                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 2)->layout()->itemAt(0)->widget();
4253                                 rb->setChecked(true);
4254                                 break;
4255                         }
4256                         case BufferParams::package_auto: {
4257                                 QRadioButton * rb =
4258                                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 1)->layout()->itemAt(0)->widget();
4259                                 rb->setChecked(true);
4260                                 break;
4261                         }
4262                 }
4263         }
4264
4265         switch (bp_.spacing().getSpace()) {
4266                 case Spacing::Other: nitem = 3; break;
4267                 case Spacing::Double: nitem = 2; break;
4268                 case Spacing::Onehalf: nitem = 1; break;
4269                 case Spacing::Default: case Spacing::Single: nitem = 0; break;
4270         }
4271
4272         // text layout
4273         string const & layoutID = bp_.baseClassID();
4274         setLayoutComboByIDString(layoutID);
4275
4276         updatePagestyle(documentClass().opt_pagestyle(),
4277                                  bp_.pagestyle);
4278
4279         textLayoutModule->lspacingCO->setCurrentIndex(nitem);
4280         if (bp_.spacing().getSpace() == Spacing::Other) {
4281                 doubleToWidget(textLayoutModule->lspacingLE,
4282                         bp_.spacing().getValueAsString());
4283         }
4284         setLSpacing(nitem);
4285         int ts = textLayoutModule->tableStyleCO->findData(toqstr(bp_.tablestyle));
4286         if (ts != -1)
4287                 textLayoutModule->tableStyleCO->setCurrentIndex(ts);
4288
4289         if (bp_.paragraph_separation == BufferParams::ParagraphIndentSeparation) {
4290                 textLayoutModule->indentRB->setChecked(true);
4291                 string parindent = bp_.getParIndent().asString();
4292                 QString indent = toqstr("default");
4293                 if (!parindent.empty()) {
4294                         lengthToWidgets(textLayoutModule->indentLE,
4295                                         textLayoutModule->indentLengthCO,
4296                                         parindent, default_unit);
4297                         indent = toqstr("custom");
4298                 }
4299                 textLayoutModule->indentCO->setCurrentIndex(textLayoutModule->indentCO->findData(indent));
4300                 setIndent(textLayoutModule->indentCO->currentIndex());
4301         } else {
4302                 textLayoutModule->skipRB->setChecked(true);
4303                 VSpace::VSpaceKind skip = bp_.getDefSkip().kind();
4304                 textLayoutModule->skipCO->setCurrentIndex(textLayoutModule->skipCO->findData(skip));
4305                 if (skip == VSpace::LENGTH) {
4306                         string const length = bp_.getDefSkip().asLyXCommand();
4307                         lengthToWidgets(textLayoutModule->skipLE,
4308                                 textLayoutModule->skipLengthCO,
4309                                 length, default_unit);
4310                 }
4311                 setSkip(textLayoutModule->skipCO->currentIndex());
4312         }
4313
4314         textLayoutModule->twoColumnCB->setChecked(
4315                 bp_.columns == 2);
4316         textLayoutModule->justCB->setChecked(bp_.justification);
4317
4318         if (!bp_.options.empty()) {
4319                 latexModule->optionsLE->setText(
4320                         toqstr(bp_.options));
4321         } else {
4322                 latexModule->optionsLE->setText(QString());
4323         }
4324
4325         // latex
4326         latexModule->defaultOptionsCB->setChecked(
4327                         bp_.use_default_options);
4328         updateSelectedModules();
4329         selectionManager->updateProvidedModules(
4330                         bp_.baseClass()->providedModules());
4331         selectionManager->updateExcludedModules(
4332                         bp_.baseClass()->excludedModules());
4333
4334         if (!documentClass().options().empty()) {
4335                 latexModule->defaultOptionsLE->setText(
4336                         toqstr(documentClass().options()));
4337         } else {
4338                 latexModule->defaultOptionsLE->setText(
4339                         toqstr(_("[No options predefined]")));
4340         }
4341
4342         latexModule->defaultOptionsLE->setEnabled(
4343                 bp_.use_default_options
4344                 && !documentClass().options().empty());
4345
4346         latexModule->defaultOptionsCB->setEnabled(
4347                 !documentClass().options().empty());
4348
4349         if (!bp_.master.empty()) {
4350                 latexModule->childDocGB->setChecked(true);
4351                 latexModule->childDocLE->setText(
4352                         toqstr(bp_.master));
4353         } else {
4354                 latexModule->childDocLE->setText(QString());
4355                 latexModule->childDocGB->setChecked(false);
4356         }
4357
4358         // Master/Child
4359         if (!bufferview() || !buffer().hasChildren()) {
4360                 masterChildModule->childrenTW->clear();
4361                 includeonlys_.clear();
4362                 docPS->showPanel("Child Documents", false);
4363                 if (docPS->isCurrentPanel("Child Documents"))
4364                         docPS->setCurrentPanel("Document Class");
4365         } else {
4366                 docPS->showPanel("Child Documents", true);
4367                 masterChildModule->setEnabled(true);
4368                 includeonlys_ = bp_.getIncludedChildren();
4369                 updateIncludeonlys();
4370                 updateIncludeonlyDisplay();
4371         }
4372         switch (bp_.maintain_unincluded_children) {
4373         case BufferParams::CM_None:
4374                 masterChildModule->maintainCRNoneRB->setChecked(true);
4375                 break;
4376         case BufferParams::CM_Mostly:
4377                 masterChildModule->maintainCRMostlyRB->setChecked(true);
4378                 break;
4379         case BufferParams::CM_Strict:
4380         default:
4381                 masterChildModule->maintainCRStrictRB->setChecked(true);
4382                 break;
4383         }
4384
4385         // Float Settings
4386         floatModule->setPlacement(bp_.float_placement);
4387         floatModule->setAlignment(bp_.float_alignment);
4388
4389         // ListingsSettings
4390         // break listings_params to multiple lines
4391         string lstparams =
4392                 InsetListingsParams(bp_.listings_params).separatedParams();
4393         listingsModule->listingsED->setPlainText(toqstr(lstparams));
4394         int nn = findToken(lst_packages, bp_.use_minted ? "Minted" : "Listings");
4395         if (nn >= 0)
4396                 listingsModule->packageCO->setCurrentIndex(nn);
4397
4398         // Fonts
4399         // some languages only work with Polyglossia (which requires non-TeX fonts)
4400         Language const * lang = lyx::languages.getLanguage(
4401                 fromqstr(langModule->languageCO->itemData(
4402                         langModule->languageCO->currentIndex()).toString()));
4403         bool const need_fontspec =
4404                 lang->babel().empty() && !lang->polyglossia().empty()
4405                 && lang->required() != "CJK" && lang->required() != "japanese";
4406         bool const os_fonts_available =
4407                 bp_.baseClass()->outputType() == lyx::LATEX
4408                 && LaTeXFeatures::isAvailable("fontspec");
4409         fontModule->osFontsCB->setEnabled(os_fonts_available && !need_fontspec);
4410         fontModule->osFontsCB->setChecked(
4411                 (os_fonts_available && bp_.useNonTeXFonts) || need_fontspec);
4412         updateFontsize(documentClass().opt_fontsize(),
4413                         bp_.fontsize);
4414
4415         QString font = toqstr(bp_.fontsRoman());
4416         bool foundfont = fontModule->fontsRomanCO->set(font, false);
4417         if (!foundfont) {
4418                 fontModule->fontsRomanCO->addItemSort(font, font + qt_(" (not installed)"),
4419                                                       qt_("Uninstalled used fonts"),
4420                                                       qt_("This font is not installed and won't be used in output"),
4421                                                       false, false, false, true);
4422                 fontModule->fontsRomanCO->set(font);
4423         }
4424         fontModule->font_roman = toqstr(bp_.fonts_roman[!bp_.useNonTeXFonts]);
4425
4426         font = toqstr(bp_.fontsSans());
4427         foundfont = fontModule->fontsSansCO->set(font, false);
4428         if (!foundfont) {
4429                 fontModule->fontsSansCO->addItemSort(font, font + qt_(" (not installed)"),
4430                                                      qt_("Uninstalled used fonts"),
4431                                                      qt_("This font is not installed and won't be used in output"),
4432                                                      false, false, false, true);
4433                 fontModule->fontsSansCO->set(font);
4434         }
4435         fontModule->font_sans = toqstr(bp_.fonts_sans[!bp_.useNonTeXFonts]);
4436
4437         font = toqstr(bp_.fontsTypewriter());
4438         foundfont = fontModule->fontsTypewriterCO->set(font, false);
4439         if (!foundfont) {
4440                 fontModule->fontsTypewriterCO->addItemSort(font, font + qt_(" (not installed)"),
4441                                                            qt_("Uninstalled used fonts"),
4442                                                            qt_("This font is not installed and won't be used in output"),
4443                                                            false, false, false, true);
4444                 fontModule->fontsTypewriterCO->set(font);
4445         }
4446         fontModule->font_typewriter = toqstr(bp_.fonts_typewriter[!bp_.useNonTeXFonts]);
4447
4448         font = toqstr(bp_.fontsMath());
4449         int mpos = fontModule->fontsMathCO->findData(font);
4450         if (mpos == -1) {
4451                 mpos = fontModule->fontsMathCO->count();
4452                 fontModule->fontsMathCO->addItem(font + qt_(" (not installed)"), font);
4453         }
4454         fontModule->fontsMathCO->setCurrentIndex(mpos);
4455         fontModule->font_math = toqstr(bp_.fonts_math[!bp_.useNonTeXFonts]);
4456
4457         if (bp_.useNonTeXFonts && os_fonts_available) {
4458                 fontModule->fontencLA->setEnabled(false);
4459                 fontModule->fontencCO->setEnabled(false);
4460                 fontModule->fontencLE->setEnabled(false);
4461         } else {
4462                 fontModule->fontencLA->setEnabled(true);
4463                 fontModule->fontencCO->setEnabled(true);
4464                 fontModule->fontencLE->setEnabled(true);
4465                 romanChanged(fontModule->fontsRomanCO->currentIndex());
4466                 sansChanged(fontModule->fontsSansCO->currentIndex());
4467                 ttChanged(fontModule->fontsTypewriterCO->currentIndex());
4468         }
4469
4470         if (!bp_.fonts_cjk.empty())
4471                 fontModule->cjkFontLE->setText(
4472                         toqstr(bp_.fonts_cjk));
4473         else
4474                 fontModule->cjkFontLE->setText(QString());
4475
4476         fontModule->microtypeCB->setChecked(bp_.use_microtype);
4477         fontModule->dashesCB->setChecked(!bp_.use_dash_ligatures);
4478
4479         fontModule->fontScCB->setChecked(bp_.fonts_expert_sc);
4480         fontModule->fontOsfCB->setChecked(bp_.fonts_roman_osf);
4481         fontModule->fontSansOsfCB->setChecked(bp_.fonts_sans_osf);
4482         fontModule->fontTypewriterOsfCB->setChecked(bp_.fonts_typewriter_osf);
4483         fontModule->scaleSansSB->setValue(bp_.fontsSansScale());
4484         fontModule->font_sf_scale = bp_.fonts_sans_scale[!bp_.useNonTeXFonts];
4485         fontModule->scaleTypewriterSB->setValue(bp_.fontsTypewriterScale());
4486         fontModule->font_tt_scale = bp_.fonts_typewriter_scale[!bp_.useNonTeXFonts];
4487         if (!bp_.font_roman_opts.empty())
4488                 fontModule->fontspecRomanLE->setText(
4489                         toqstr(bp_.font_roman_opts));
4490         else
4491                 fontModule->fontspecRomanLE->setText(QString());
4492         if (!bp_.font_sans_opts.empty())
4493                 fontModule->fontspecSansLE->setText(
4494                         toqstr(bp_.font_sans_opts));
4495         else
4496                 fontModule->fontspecSansLE->setText(QString());
4497         if (!bp_.font_typewriter_opts.empty())
4498                 fontModule->fontspecTypewriterLE->setText(
4499                         toqstr(bp_.font_typewriter_opts));
4500         else
4501                 fontModule->fontspecTypewriterLE->setText(QString());
4502
4503         nn = findToken(GuiDocument::fontfamilies, bp_.fonts_default_family);
4504         if (nn >= 0)
4505                 fontModule->fontsDefaultCO->setCurrentIndex(nn);
4506
4507         if (bp_.fontenc == "auto" || bp_.fontenc == "default") {
4508                 fontModule->fontencCO->setCurrentIndex(
4509                         fontModule->fontencCO->findData(toqstr(bp_.fontenc)));
4510                 fontModule->fontencLE->setEnabled(false);
4511         } else {
4512                 fontModule->fontencCO->setCurrentIndex(
4513                                         fontModule->fontencCO->findData("custom"));
4514                 fontModule->fontencLE->setText(toqstr(bp_.fontenc));
4515         }
4516
4517         // LaTeX input encoding
4518         // Set after fonts because non-tex fonts override "\inputencoding".
4519         inputencodingToDialog();
4520
4521         // Formats
4522         // This must be set _after_ fonts since updateDefaultFormat()
4523         // checks osFontsCB settings.
4524         // update combobox with formats
4525         updateDefaultFormat();
4526         int index = outputModule->defaultFormatCO->findData(toqstr(
4527                 bp_.default_output_format));
4528         // set to default if format is not found
4529         if (index == -1)
4530                 index = 0;
4531         outputModule->defaultFormatCO->setCurrentIndex(index);
4532
4533         outputModule->shellescapeCB->setChecked(bp_.shell_escape);
4534         outputModule->outputsyncCB->setChecked(bp_.output_sync);
4535         outputModule->synccustomCB->setEditText(toqstr(bp_.output_sync_macro));
4536         outputModule->synccustomCB->setEnabled(bp_.output_sync);
4537         outputModule->synccustomLA->setEnabled(bp_.output_sync);
4538
4539         outputModule->mathimgSB->setValue(bp_.html_math_img_scale);
4540         outputModule->mathoutCB->setCurrentIndex(bp_.html_math_output);
4541         outputModule->strictCB->setChecked(bp_.html_be_strict);
4542         outputModule->cssCB->setChecked(bp_.html_css_as_file);
4543
4544         outputModule->tableoutCB->setCurrentIndex(bp_.docbook_table_output);
4545         outputModule->mathmlprefixCB->setCurrentIndex(bp_.docbook_mathml_prefix);
4546
4547         outputModule->saveTransientPropertiesCB
4548                 ->setChecked(bp_.save_transient_properties);
4549         outputModule->postponeFragileCB
4550                 ->setChecked(bp_.postpone_fragile_content);
4551
4552         // paper
4553         bool const extern_geometry =
4554                 documentClass().provides("geometry");
4555         int const psize = bp_.papersize;
4556         pageLayoutModule->papersizeCO->setCurrentIndex(psize);
4557         setCustomPapersize(!extern_geometry && psize == 1);
4558         pageLayoutModule->papersizeCO->setEnabled(!extern_geometry);
4559
4560         bool const landscape =
4561                 bp_.orientation == ORIENTATION_LANDSCAPE;
4562         pageLayoutModule->landscapeRB->setChecked(landscape);
4563         pageLayoutModule->portraitRB->setChecked(!landscape);
4564         pageLayoutModule->landscapeRB->setEnabled(!extern_geometry);
4565         pageLayoutModule->portraitRB->setEnabled(!extern_geometry);
4566
4567         pageLayoutModule->facingPagesCB->setChecked(
4568                 bp_.sides == TwoSides);
4569
4570         lengthToWidgets(pageLayoutModule->paperwidthLE,
4571                 pageLayoutModule->paperwidthUnitCO, bp_.paperwidth, default_unit);
4572         lengthToWidgets(pageLayoutModule->paperheightLE,
4573                 pageLayoutModule->paperheightUnitCO, bp_.paperheight, default_unit);
4574
4575         // margins
4576         Ui::MarginsUi * m = marginsModule;
4577
4578         setMargins();
4579
4580         lengthToWidgets(m->topLE, m->topUnit,
4581                 bp_.topmargin, default_unit);
4582
4583         lengthToWidgets(m->bottomLE, m->bottomUnit,
4584                 bp_.bottommargin, default_unit);
4585
4586         lengthToWidgets(m->innerLE, m->innerUnit,
4587                 bp_.leftmargin, default_unit);
4588
4589         lengthToWidgets(m->outerLE, m->outerUnit,
4590                 bp_.rightmargin, default_unit);
4591
4592         lengthToWidgets(m->headheightLE, m->headheightUnit,
4593                 bp_.headheight, default_unit);
4594
4595         lengthToWidgets(m->headsepLE, m->headsepUnit,
4596                 bp_.headsep, default_unit);
4597
4598         lengthToWidgets(m->footskipLE, m->footskipUnit,
4599                 bp_.footskip, default_unit);
4600
4601         lengthToWidgets(m->columnsepLE, m->columnsepUnit,
4602                 bp_.columnsep, default_unit);
4603
4604         // branches
4605         updateUnknownBranches();
4606         branchesModule->update(bp_);
4607
4608         // PDF support
4609         PDFOptions const & pdf = bp_.pdfoptions();
4610         pdfSupportModule->use_hyperrefGB->setChecked(pdf.use_hyperref);
4611         if (bp_.documentClass().provides("hyperref"))
4612                 pdfSupportModule->use_hyperrefGB->setTitle(qt_("C&ustomize Hyperref Options"));
4613         else
4614                 pdfSupportModule->use_hyperrefGB->setTitle(qt_("&Use Hyperref Support"));
4615         pdfSupportModule->titleLE->setText(toqstr(pdf.title));
4616         pdfSupportModule->authorLE->setText(toqstr(pdf.author));
4617         pdfSupportModule->subjectLE->setText(toqstr(pdf.subject));
4618         pdfSupportModule->keywordsLE->setText(toqstr(pdf.keywords));
4619
4620         pdfSupportModule->bookmarksGB->setChecked(pdf.bookmarks);
4621         pdfSupportModule->bookmarksnumberedCB->setChecked(pdf.bookmarksnumbered);
4622         pdfSupportModule->bookmarksopenGB->setChecked(pdf.bookmarksopen);
4623
4624         pdfSupportModule->bookmarksopenlevelSB->setValue(pdf.bookmarksopenlevel);
4625         pdfSupportModule->bookmarksopenlevelSB->setEnabled(pdf.bookmarksopen);
4626         pdfSupportModule->bookmarksopenlevelLA->setEnabled(pdf.bookmarksopen);
4627
4628         pdfSupportModule->breaklinksCB->setChecked(pdf.breaklinks);
4629         pdfSupportModule->pdfborderCB->setChecked(pdf.pdfborder);
4630         pdfSupportModule->pdfusetitleCB->setChecked(pdf.pdfusetitle);
4631         pdfSupportModule->colorlinksCB->setChecked(pdf.colorlinks);
4632
4633         nn = findToken(backref_opts, pdf.backref);
4634         if (nn >= 0)
4635                 pdfSupportModule->backrefCO->setCurrentIndex(nn);
4636
4637         pdfSupportModule->fullscreenCB->setChecked
4638                 (pdf.pagemode == pdf.pagemode_fullscreen);
4639
4640         pdfSupportModule->optionsTE->setPlainText(
4641                 toqstr(pdf.quoted_options));
4642
4643         pdfSupportModule->metadataTE->setPlainText(
4644                 toqstr(rtrim(bp_.document_metadata, "\n")));
4645
4646         // change tracking
4647         changesModule->trackChangesCB->setChecked(bp_.track_changes);
4648         changesModule->outputChangesCB->setChecked(bp_.output_changes);
4649         changesModule->changeBarsCB->setChecked(bp_.change_bars);
4650         changesModule->changeBarsCB->setEnabled(bp_.output_changes);
4651
4652         // Make sure that the bc is in the INITIAL state
4653         if (bc().policy().buttonStatus(ButtonPolicy::RESTORE))
4654                 bc().restore();
4655
4656         // clear changed branches cache
4657         changedBranches_.clear();
4658
4659         // re-initiate module filter
4660         if (!filter_->text().isEmpty())
4661                 moduleFilterPressed();
4662
4663         // reset trackers
4664         nonModuleChanged_ = false;
4665         shellescapeChanged_ = false;
4666 }
4667
4668
4669 void GuiDocument::saveDocDefault()
4670 {
4671         // we have to apply the params first
4672         applyView();
4673         saveAsDefault();
4674 }
4675
4676
4677 void GuiDocument::updateAvailableModules()
4678 {
4679         modules_av_model_.clear();
4680         list<modInfoStruct> modInfoList = getModuleInfo();
4681         // Sort names according to the locale
4682         modInfoList.sort([](modInfoStruct const & a, modInfoStruct const & b) {
4683                         return 0 < b.name.localeAwareCompare(a.name);
4684                 });
4685         QIcon user_icon(guiApp ? guiApp->getScaledPixmap("images/", "lyxfiles-user")
4686                                : getPixmap("images/", "lyxfiles-user", "svgz,png"));
4687         QIcon system_icon(guiApp ? guiApp->getScaledPixmap("images/", "lyxfiles-system")
4688                                  : getPixmap("images/", "lyxfiles-system", "svgz,png"));
4689         int i = 0;
4690         QFont catfont;
4691         catfont.setBold(true);
4692         QBrush unavbrush;
4693         unavbrush.setColor(Qt::gray);
4694         for (modInfoStruct const & m : modInfoList) {
4695                 QStandardItem * item = new QStandardItem();
4696                 QStandardItem * catItem;
4697                 QString const catname = m.category;
4698                 QList<QStandardItem *> fcats = modules_av_model_.findItems(catname, Qt::MatchExactly);
4699                 if (!fcats.empty())
4700                         catItem = fcats.first();
4701                 else {
4702                         catItem = new QStandardItem();
4703                         catItem->setText(catname);
4704                         catItem->setFont(catfont);
4705                         modules_av_model_.insertRow(i, catItem);
4706                         ++i;
4707                 }
4708                 item->setEditable(false);
4709                 catItem->setEditable(false);
4710                 item->setData(m.name, Qt::DisplayRole);
4711                 if (m.missingreqs)
4712                         item->setForeground(unavbrush);
4713                 item->setData(toqstr(m.id), Qt::UserRole);
4714                 item->setData(m.description, Qt::ToolTipRole);
4715                 if (m.local)
4716                         item->setIcon(user_icon);
4717                 else
4718                         item->setIcon(system_icon);
4719                 catItem->appendRow(item);
4720         }
4721         modules_av_model_.sort(0);
4722 }
4723
4724
4725 void GuiDocument::updateSelectedModules()
4726 {
4727         modules_sel_model_.clear();
4728         list<modInfoStruct> const selModList = getSelectedModules();
4729         int i = 0;
4730         for (modInfoStruct const & m : selModList) {
4731                 modules_sel_model_.insertRow(i, m.name, m.id, m.description);
4732                 ++i;
4733         }
4734 }
4735
4736
4737 void GuiDocument::updateIncludeonlyDisplay()
4738 {
4739         if (includeonlys_.empty()) {
4740                 masterChildModule->includeallRB->setChecked(true);
4741                 masterChildModule->childrenTW->setEnabled(false);
4742                 masterChildModule->maintainGB->setEnabled(false);
4743         } else {
4744                 masterChildModule->includeonlyRB->setChecked(true);
4745                 masterChildModule->childrenTW->setEnabled(true);
4746                 masterChildModule->maintainGB->setEnabled(true);
4747         }
4748 }
4749
4750
4751 void GuiDocument::updateIncludeonlys(bool const cleanup)
4752 {
4753         masterChildModule->childrenTW->clear();
4754         QString const no = qt_("No");
4755         QString const yes = qt_("Yes");
4756
4757         ListOfBuffers children = buffer().getChildren();
4758         ListOfBuffers::const_iterator it  = children.begin();
4759         ListOfBuffers::const_iterator end = children.end();
4760         bool has_unincluded = false;
4761         bool all_unincluded = true;
4762         for (; it != end; ++it) {
4763                 QTreeWidgetItem * item = new QTreeWidgetItem(masterChildModule->childrenTW);
4764                 // FIXME Unicode
4765                 string const name =
4766                         to_utf8(makeRelPath(from_utf8((*it)->fileName().absFileName()),
4767                                                         from_utf8(buffer().filePath())));
4768                 item->setText(0, toqstr(name));
4769                 item->setText(1, isChildIncluded(name) ? yes : no);
4770                 if (!isChildIncluded(name))
4771                         has_unincluded = true;
4772                 else
4773                         all_unincluded = false;
4774         }
4775         // Both if all children are included and if none is included
4776         // is equal to "include all" (i.e., omit \includeonly).
4777         if (cleanup && (!has_unincluded || all_unincluded))
4778                 includeonlys_.clear();
4779 }
4780
4781
4782 bool GuiDocument::isBiblatex() const
4783 {
4784         QString const engine =
4785                 biblioModule->citeEngineCO->itemData(
4786                                 biblioModule->citeEngineCO->currentIndex()).toString();
4787
4788         // this can happen if the cite engine is unknown, which can happen
4789         // if one is using a file that came from someone else, etc. in that
4790         // case, we crash if we proceed.
4791         if (engine.isEmpty())
4792             return false;
4793
4794         return theCiteEnginesList[fromqstr(engine)]->getCiteFramework() == "biblatex";
4795 }
4796
4797
4798 void GuiDocument::updateDefaultBiblio(string const & style,
4799                                       string const & which)
4800 {
4801         QString const bibstyle = toqstr(style);
4802         biblioModule->defaultBiblioCO->clear();
4803
4804         int item_nr = -1;
4805
4806         if (isBiblatex()) {
4807                 if (which != "cbx") {
4808                         // First the bbx styles
4809                         biblioModule->biblatexBbxCO->clear();
4810                         QStringList str = texFileList("bbxFiles.lst");
4811                         // test whether we have a valid list, otherwise run rescan
4812                         if (str.isEmpty()) {
4813                                 rescanTexStyles("bbx");
4814                                 str = texFileList("bbxFiles.lst");
4815                         }
4816                         for (int i = 0; i != str.size(); ++i)
4817                                 str[i] = onlyFileName(str[i]);
4818                         // sort on filename only (no path)
4819                         str.sort();
4820
4821                         for (int i = 0; i != str.count(); ++i) {
4822                                 QString item = changeExtension(str[i], "");
4823                                 if (item == bibstyle)
4824                                         item_nr = i;
4825                                 biblioModule->biblatexBbxCO->addItem(item);
4826                         }
4827
4828                         if (item_nr == -1 && !bibstyle.isEmpty()) {
4829                                 biblioModule->biblatexBbxCO->addItem(bibstyle);
4830                                 item_nr = biblioModule->biblatexBbxCO->count() - 1;
4831                         }
4832
4833                         if (item_nr != -1)
4834                                 biblioModule->biblatexBbxCO->setCurrentIndex(item_nr);
4835                         else
4836                                 biblioModule->biblatexBbxCO->clearEditText();
4837                 }
4838
4839                 if (which != "bbx") {
4840                         // now the cbx styles
4841                         biblioModule->biblatexCbxCO->clear();
4842                         QStringList str = texFileList("cbxFiles.lst");
4843                         // test whether we have a valid list, otherwise run rescan
4844                         if (str.isEmpty()) {
4845                                 rescanTexStyles("cbx");
4846                                 str = texFileList("cbxFiles.lst");
4847                         }
4848                         for (int i = 0; i != str.size(); ++i)
4849                                 str[i] = onlyFileName(str[i]);
4850                         // sort on filename only (no path)
4851                         str.sort();
4852
4853                         for (int i = 0; i != str.count(); ++i) {
4854                                 QString item = changeExtension(str[i], "");
4855                                 if (item == bibstyle)
4856                                         item_nr = i;
4857                                 biblioModule->biblatexCbxCO->addItem(item);
4858                         }
4859
4860                         if (item_nr == -1 && !bibstyle.isEmpty()) {
4861                                 biblioModule->biblatexCbxCO->addItem(bibstyle);
4862                                 item_nr = biblioModule->biblatexCbxCO->count() - 1;
4863                         }
4864
4865                         if (item_nr != -1)
4866                                 biblioModule->biblatexCbxCO->setCurrentIndex(item_nr);
4867                         else
4868                                 biblioModule->biblatexCbxCO->clearEditText();
4869                 }
4870         } else {// BibTeX
4871                 biblioModule->biblatexBbxCO->clear();
4872                 biblioModule->biblatexCbxCO->clear();
4873                 QStringList str = texFileList("bstFiles.lst");
4874                 // test whether we have a valid list, otherwise run rescan
4875                 if (str.isEmpty()) {
4876                         rescanTexStyles("bst");
4877                         str = texFileList("bstFiles.lst");
4878                 }
4879                 for (int i = 0; i != str.size(); ++i)
4880                         str[i] = onlyFileName(str[i]);
4881                 // sort on filename only (no path)
4882                 str.sort();
4883
4884                 for (int i = 0; i != str.count(); ++i) {
4885                         QString item = changeExtension(str[i], "");
4886                         if (item == bibstyle)
4887                                 item_nr = i;
4888                         biblioModule->defaultBiblioCO->addItem(item);
4889                 }
4890
4891                 if (item_nr == -1 && !bibstyle.isEmpty()) {
4892                         biblioModule->defaultBiblioCO->addItem(bibstyle);
4893                         item_nr = biblioModule->defaultBiblioCO->count() - 1;
4894                 }
4895
4896                 if (item_nr != -1)
4897                         biblioModule->defaultBiblioCO->setCurrentIndex(item_nr);
4898                 else
4899                         biblioModule->defaultBiblioCO->clearEditText();
4900         }
4901
4902         updateResetDefaultBiblio();
4903 }
4904
4905
4906 void GuiDocument::updateResetDefaultBiblio()
4907 {
4908         QString const engine =
4909                 biblioModule->citeEngineCO->itemData(
4910                                 biblioModule->citeEngineCO->currentIndex()).toString();
4911         CiteEngineType const cet =
4912                 CiteEngineType(biblioModule->citeStyleCO->itemData(
4913                                                           biblioModule->citeStyleCO->currentIndex()).toInt());
4914
4915         string const defbib = theCiteEnginesList[fromqstr(engine)]->getDefaultBiblio(cet);
4916         if (isBiblatex()) {
4917                 QString const bbx = biblioModule->biblatexBbxCO->currentText();
4918                 QString const cbx = biblioModule->biblatexCbxCO->currentText();
4919                 biblioModule->resetCbxPB->setEnabled(defbib != fromqstr(cbx));
4920                 biblioModule->resetBbxPB->setEnabled(defbib != fromqstr(bbx));
4921                 biblioModule->matchBbxPB->setEnabled(bbx != cbx && !cbx.isEmpty()
4922                         && biblioModule->biblatexBbxCO->findText(cbx) != -1);
4923         } else
4924                 biblioModule->resetDefaultBiblioPB->setEnabled(
4925                         defbib != fromqstr(biblioModule->defaultBiblioCO->currentText()));
4926 }
4927
4928
4929 void GuiDocument::matchBiblatexStyles()
4930 {
4931         updateDefaultBiblio(fromqstr(biblioModule->biblatexCbxCO->currentText()), "bbx");
4932         biblioChanged();
4933 }
4934
4935
4936 void GuiDocument::updateContents()
4937 {
4938         // Nothing to do here as the document settings is not cursor dependent.
4939         return;
4940 }
4941
4942
4943 void GuiDocument::useClassDefaults()
4944 {
4945         if (buttonBox->button(QDialogButtonBox::Apply)->isEnabled()) {
4946                 int const ret = Alert::prompt(_("Unapplied changes"),
4947                                 _("Some changes in the dialog were not yet applied.\n"
4948                                   "If you do not apply now, they will be lost after this action."),
4949                                 1, 1, _("&Apply"), _("&Dismiss"));
4950                 if (ret == 0)
4951                         applyView();
4952         }
4953
4954         int idx = latexModule->classCO->currentIndex();
4955         string const classname = fromqstr(latexModule->classCO->getData(idx));
4956         if (!bp_.setBaseClass(classname, buffer().layoutPos())) {
4957                 Alert::error(_("Error"), _("Unable to set document class."));
4958                 return;
4959         }
4960         bp_.useClassDefaults();
4961         paramsToDialog();
4962         changed();
4963 }
4964
4965
4966 void GuiDocument::setLayoutComboByIDString(string const & idString)
4967 {
4968         if (!latexModule->classCO->set(toqstr(idString)))
4969                 Alert::warning(_("Can't set layout!"),
4970                         bformat(_("Unable to set layout for ID: %1$s"), from_utf8(idString)));
4971 }
4972
4973
4974 bool GuiDocument::isValid()
4975 {
4976         bool const listings_valid = validateListingsParameters().isEmpty();
4977         bool const local_layout_valid = !localLayout->editing();
4978         bool const preamble_valid = !preambleModule->editing();
4979
4980         docPS->markPanelValid(N_("Listings[[inset]]"), listings_valid);
4981         docPS->markPanelValid(N_("Local Layout"), local_layout_valid && localLayout->isValid());
4982         docPS->markPanelValid(N_("LaTeX Preamble"), preamble_valid);
4983         
4984         return listings_valid && local_layout_valid && preamble_valid;
4985 }
4986
4987
4988 char const * const GuiDocument::fontfamilies[5] = {
4989         "default", "rmdefault", "sfdefault", "ttdefault", ""
4990 };
4991
4992
4993 char const * GuiDocument::fontfamilies_gui[5] = {
4994         N_("Default"), N_("Roman"), N_("Sans Serif"), N_("Typewriter"), ""
4995 };
4996
4997
4998 bool GuiDocument::initialiseParams(string const &)
4999 {
5000         BufferView const * view = bufferview();
5001         if (!view) {
5002                 bp_ = BufferParams();
5003                 paramsToDialog();
5004                 return true;
5005         }
5006         prev_buffer_filename_ = view->buffer().absFileName();
5007         bp_ = view->buffer().params();
5008         loadModuleInfo();
5009         updateAvailableModules();
5010         //FIXME It'd be nice to make sure here that the selected
5011         //modules are consistent: That required modules are actually
5012         //selected, and that we don't have conflicts. If so, we could
5013         //at least pop up a warning.
5014         paramsToDialog();
5015         return true;
5016 }
5017
5018
5019 void GuiDocument::clearParams()
5020 {
5021         bp_ = BufferParams();
5022 }
5023
5024
5025 BufferId GuiDocument::id() const
5026 {
5027         BufferView const * const view = bufferview();
5028         return view? &view->buffer() : nullptr;
5029 }
5030
5031
5032 list<GuiDocument::modInfoStruct> const & GuiDocument::getModuleInfo()
5033 {
5034         return moduleNames_;
5035 }
5036
5037
5038 list<GuiDocument::modInfoStruct> const
5039 GuiDocument::makeModuleInfo(LayoutModuleList const & mods)
5040 {
5041         list<modInfoStruct> mInfo;
5042         for (string const & name : mods) {
5043                 modInfoStruct m;
5044                 LyXModule const * const mod = theModuleList[name];
5045                 if (mod)
5046                         m = modInfo(*mod);
5047                 else {
5048                         m.id = name;
5049                         m.name = toqstr(name + " (") + qt_("Not Found") + toqstr(")");
5050                         m.local = false;
5051                         m.missingreqs = true;
5052                 }
5053                 mInfo.push_back(m);
5054         }
5055         return mInfo;
5056 }
5057
5058
5059 list<GuiDocument::modInfoStruct> const GuiDocument::getSelectedModules()
5060 {
5061         return makeModuleInfo(params().getModules());
5062 }
5063
5064
5065 list<GuiDocument::modInfoStruct> const GuiDocument::getProvidedModules()
5066 {
5067         return makeModuleInfo(params().baseClass()->providedModules());
5068 }
5069
5070
5071 DocumentClass const & GuiDocument::documentClass() const
5072 {
5073         return bp_.documentClass();
5074 }
5075
5076
5077 static void dispatch_bufferparams(Dialog const & dialog,
5078         BufferParams const & bp, FuncCode lfun, Buffer const * buf)
5079 {
5080         ostringstream ss;
5081         ss << "\\begin_header\n";
5082         bp.writeFile(ss, buf);
5083         ss << "\\end_header\n";
5084         dialog.dispatch(FuncRequest(lfun, ss.str()));
5085 }
5086
5087
5088 void GuiDocument::dispatchParams()
5089 {
5090         // We need a non-const buffer object.
5091         Buffer & buf = const_cast<BufferView *>(bufferview())->buffer();
5092         // There may be several undo records; group them (bug #8998)
5093         // This handles undo groups automagically
5094         UndoGroupHelper ugh(&buf);
5095
5096         // This must come first so that a language change is correctly noticed
5097         setLanguage();
5098
5099         // We need to load the master before we formally update the params,
5100         // since otherwise we run updateBuffer, etc, before the child's master
5101         // has been set.
5102         if (!params().master.empty()) {
5103                 FileName const master_file = support::makeAbsPath(params().master,
5104                            support::onlyPath(buffer().absFileName()));
5105                 if (isLyXFileName(master_file.absFileName())) {
5106                         Buffer * master = checkAndLoadLyXFile(master_file, true);
5107                         if (master) {
5108                                 if (master->isChild(const_cast<Buffer *>(&buffer())))
5109                                         const_cast<Buffer &>(buffer()).setParent(master);
5110                                 else
5111                                         Alert::warning(_("Assigned master does not include this file"),
5112                                                 bformat(_("You must include this file in the document\n"
5113                                                           "'%1$s' in order to use the master document\n"
5114                                                           "feature."), from_utf8(params().master)));
5115                         } else
5116                                 Alert::warning(_("Could not load master"),
5117                                                 bformat(_("The master document '%1$s'\n"
5118                                                            "could not be loaded."),
5119                                                            from_utf8(params().master)));
5120                 }
5121         }
5122
5123         // Apply the BufferParams. Note that this will set the base class
5124         // and then update the buffer's layout.
5125         dispatch_bufferparams(*this, params(), LFUN_BUFFER_PARAMS_APPLY, &buffer());
5126
5127         // Generate the colours requested by each new branch.
5128         BranchList & branchlist = params().branchlist();
5129         if (!branchlist.empty()) {
5130                 BranchList::const_iterator it = branchlist.begin();
5131                 BranchList::const_iterator const end = branchlist.end();
5132                 for (; it != end; ++it) {
5133                         docstring const & current_branch = it->branch();
5134                         Branch const * branch = branchlist.find(current_branch);
5135                         string const bcolor = branch->color();
5136                         RGBColor rgbcol;
5137                         if (bcolor.size() == 7 && bcolor[0] == '#')
5138                                 rgbcol = lyx::rgbFromHexName(bcolor);
5139                         else
5140                                 guiApp->getRgbColor(lcolor.getFromLyXName(bcolor), rgbcol);
5141                         string const x11hexname = X11hexname(rgbcol);
5142                         // display the new color
5143                         docstring const str = current_branch + ' ' + from_ascii(x11hexname);
5144                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
5145                 }
5146         }
5147         // rename branches in the document
5148         executeBranchRenaming();
5149         // and clear changed branches cache
5150         changedBranches_.clear();
5151
5152         // Generate the colours requested by indices.
5153         IndicesList & indiceslist = params().indiceslist();
5154         if (!indiceslist.empty()) {
5155                 IndicesList::const_iterator it = indiceslist.begin();
5156                 IndicesList::const_iterator const end = indiceslist.end();
5157                 for (; it != end; ++it) {
5158                         docstring const & current_index = it->shortcut();
5159                         Index const * index = indiceslist.findShortcut(current_index);
5160                         string const x11hexname = X11hexname(index->color());
5161                         // display the new color
5162                         docstring const str = current_index + ' ' + from_ascii(x11hexname);
5163                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
5164                 }
5165         }
5166         // FIXME LFUN
5167         // If we used an LFUN, we would not need these two lines:
5168         BufferView * bv = const_cast<BufferView *>(bufferview());
5169         bv->processUpdateFlags(Update::Force | Update::FitCursor);
5170 }
5171
5172
5173 void GuiDocument::setLanguage() const
5174 {
5175         Language const * const newL = bp_.language;
5176         if (buffer().params().language == newL)
5177                 return;
5178
5179         string const & lang_name = newL->lang();
5180         dispatch(FuncRequest(LFUN_BUFFER_LANGUAGE, lang_name));
5181 }
5182
5183
5184 void GuiDocument::saveAsDefault() const
5185 {
5186         dispatch_bufferparams(*this, params(), LFUN_BUFFER_SAVE_AS_DEFAULT, &buffer());
5187 }
5188
5189
5190 bool GuiDocument::providesOSF(QString const & font) const
5191 {
5192         if (fontModule->osFontsCB->isChecked())
5193                 // FIXME: we should check if the fonts really
5194                 // have OSF support. But how?
5195                 return font != "default";
5196         return theLaTeXFonts().getLaTeXFont(
5197                                 qstring_to_ucs4(font)).providesOSF(ot1(),
5198                                                                    completeFontset(),
5199                                                                    noMathFont());
5200 }
5201
5202
5203 bool GuiDocument::providesSC(QString const & font) const
5204 {
5205         if (fontModule->osFontsCB->isChecked())
5206                 return false;
5207         return theLaTeXFonts().getLaTeXFont(
5208                                 qstring_to_ucs4(font)).providesSC(ot1(),
5209                                                                   completeFontset(),
5210                                                                   noMathFont());
5211 }
5212
5213
5214 bool GuiDocument::providesScale(QString const & font) const
5215 {
5216         if (fontModule->osFontsCB->isChecked())
5217                 return font != "default";
5218         return theLaTeXFonts().getLaTeXFont(
5219                                 qstring_to_ucs4(font)).providesScale(ot1(),
5220                                                                      completeFontset(),
5221                                                                      noMathFont());
5222 }
5223
5224
5225 bool GuiDocument::providesExtraOpts(QString const & font) const
5226 {
5227         if (fontModule->osFontsCB->isChecked())
5228                 return font != "default";
5229         return theLaTeXFonts().getLaTeXFont(
5230                                 qstring_to_ucs4(font)).providesMoreOptions(ot1(),
5231                                                                      completeFontset(),
5232                                                                      noMathFont());
5233 }
5234
5235
5236 bool GuiDocument::providesNoMath(QString const & font) const
5237 {
5238         if (fontModule->osFontsCB->isChecked())
5239                 return false;
5240         return theLaTeXFonts().getLaTeXFont(
5241                                 qstring_to_ucs4(font)).providesNoMath(ot1(),
5242                                                                       completeFontset());
5243 }
5244
5245
5246 bool GuiDocument::hasMonolithicExpertSet(QString const & font) const
5247 {
5248         if (fontModule->osFontsCB->isChecked())
5249                 return false;
5250         return theLaTeXFonts().getLaTeXFont(
5251                                 qstring_to_ucs4(font)).hasMonolithicExpertSet(ot1(),
5252                                                                               completeFontset(),
5253                                                                               noMathFont());
5254 }
5255
5256
5257 //static
5258 GuiDocument::modInfoStruct GuiDocument::modInfo(LyXModule const & mod)
5259 {
5260         // FIXME Unicode: docstrings would be better for these parameters but this
5261         // change requires a lot of others
5262         modInfoStruct m;
5263         m.id = mod.getID();
5264         QString const guiname = toqstr(translateIfPossible(from_utf8(mod.getName())));
5265         m.missingreqs = !isModuleAvailable(mod.getID());
5266         if (m.missingreqs) {
5267                 m.name = qt_("%1 (missing req.)").arg(guiname);
5268         } else
5269                 m.name = guiname;
5270         m.category = mod.category().empty() ? qt_("Miscellaneous")
5271                                             : toqstr(translateIfPossible(from_utf8(mod.category())));
5272         QString desc = toqstr(translateIfPossible(from_utf8(mod.getDescription())));
5273         // Find the first sentence of the description
5274         QTextBoundaryFinder bf(QTextBoundaryFinder::Sentence, desc);
5275         int pos = bf.toNextBoundary();
5276         if (pos > 0)
5277                 desc.truncate(pos);
5278         m.local = mod.isLocal();
5279         QString const mtype = m.local ? qt_("personal module") : qt_("distributed module");
5280         QString modulename = qt_("<b>Module name:</b> <i>%1</i> (%2)").arg(toqstr(m.id)).arg(mtype);
5281         // Tooltip is the desc followed by the module name and the type
5282         m.description = QString("%1%2")
5283                 .arg(desc.isEmpty() ? QString() : QString("<p>%1</p>").arg(desc),
5284                      modulename);
5285         if (m.missingreqs)
5286                 m.description += QString("<p>%1</p>").arg(qt_("<b>Note:</b> Some requirements for this module are missing!"));
5287         return m;
5288 }
5289
5290
5291 void GuiDocument::loadModuleInfo()
5292 {
5293         moduleNames_.clear();
5294         for (LyXModule const & mod : theModuleList)
5295                 moduleNames_.push_back(modInfo(mod));
5296 }
5297
5298
5299 void GuiDocument::updateUnknownBranches()
5300 {
5301         if (!bufferview())
5302                 return;
5303         list<docstring> used_branches;
5304         buffer().getUsedBranches(used_branches);
5305         list<docstring>::const_iterator it = used_branches.begin();
5306         QStringList unknown_branches;
5307         for (; it != used_branches.end() ; ++it) {
5308                 if (!buffer().params().branchlist().find(*it))
5309                         unknown_branches.append(toqstr(*it));
5310         }
5311         branchesModule->setUnknownBranches(unknown_branches);
5312 }
5313
5314
5315 void GuiDocument::branchesRename(docstring const & oldname, docstring const & newname)
5316 {
5317         map<docstring, docstring>::iterator it = changedBranches_.begin();
5318         for (; it != changedBranches_.end() ; ++it) {
5319                 if (it->second == oldname) {
5320                         // branch has already been renamed
5321                         it->second = newname;
5322                         return;
5323                 }
5324         }
5325         // store new name
5326         changedBranches_[oldname] = newname;
5327 }
5328
5329
5330 void GuiDocument::executeBranchRenaming() const
5331 {
5332         map<docstring, docstring>::const_iterator it = changedBranches_.begin();
5333         for (; it != changedBranches_.end() ; ++it) {
5334                 docstring const arg = '"' + it->first + '"' + " " + '"' + it->second + '"';
5335                 dispatch(FuncRequest(LFUN_BRANCHES_RENAME, arg));
5336         }
5337 }
5338
5339
5340 void GuiDocument::allPackagesAuto()
5341 {
5342         allPackages(1);
5343 }
5344
5345
5346 void GuiDocument::allPackagesAlways()
5347 {
5348         allPackages(2);
5349 }
5350
5351
5352 void GuiDocument::allPackagesNot()
5353 {
5354         allPackages(3);
5355 }
5356
5357
5358 void GuiDocument::allPackages(int col)
5359 {
5360         for (int row = 0; row < mathsModule->packagesTW->rowCount(); ++row) {
5361                 QRadioButton * rb =
5362                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, col)->layout()->itemAt(0)->widget();
5363                 rb->setChecked(true);
5364         }
5365 }
5366
5367
5368 void GuiDocument::linenoToggled(bool on)
5369 {
5370         numberingModule->linenoLE->setEnabled(on);
5371         numberingModule->linenoLA->setEnabled(on);
5372 }
5373
5374
5375 void GuiDocument::outputChangesToggled(bool on)
5376 {
5377         changesModule->changeBarsCB->setEnabled(on);
5378         change_adaptor();
5379 }
5380
5381 void GuiDocument::setOutputSync(bool on)
5382 {
5383         outputModule->synccustomCB->setEnabled(on);
5384         outputModule->synccustomLA->setEnabled(on);
5385         change_adaptor();
5386 }
5387
5388
5389 } // namespace frontend
5390 } // namespace lyx
5391
5392 #include "moc_GuiDocument.cpp"