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