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