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