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