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