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