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