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