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