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