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