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