]> git.lyx.org Git - features.git/blob - src/frontends/qt/GuiDocument.cpp
typo
[features.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 (std::string(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         int nn = 0;
3113
3114         for (int n = 0; !token(items, '|', n).empty(); ++n) {
3115                 nn += 1;
3116                 string style = token(items, '|', n);
3117                 engine_types_.push_back(style);
3118         }
3119
3120         updateCiteStyles(engine_types_, sel);
3121 }
3122
3123
3124 namespace {
3125         // FIXME unicode
3126         // both of these should take a vector<docstring>
3127
3128         // This is an insanely complicated attempt to make this sort of thing
3129         // work with RTL languages.
3130         docstring formatStrVec(vector<string> const & v, docstring const & s)
3131         {
3132                 //this mess formats the list as "v[0], v[1], ..., [s] v[n]"
3133                 if (v.empty())
3134                         return docstring();
3135                 if (v.size() == 1)
3136                         return translateIfPossible(from_utf8(v[0]));
3137                 if (v.size() == 2) {
3138                         docstring retval = _("%1$s and %2$s");
3139                         retval = subst(retval, _("and"), s);
3140                         return bformat(retval, translateIfPossible(from_utf8(v[0])),
3141                                        translateIfPossible(from_utf8(v[1])));
3142                 }
3143                 // The idea here is to format all but the last two items...
3144                 int const vSize = v.size();
3145                 docstring t2 = _("%1$s, %2$s");
3146                 docstring retval = translateIfPossible(from_utf8(v[0]));
3147                 for (int i = 1; i < vSize - 2; ++i)
3148                         retval = bformat(t2, retval, translateIfPossible(from_utf8(v[i])));
3149                 //...and then to  plug them, and the last two, into this schema
3150                 docstring t = _("%1$s, %2$s, and %3$s");
3151                 t = subst(t, _("and"), s);
3152                 return bformat(t, retval, translateIfPossible(from_utf8(v[vSize - 2])),
3153                                translateIfPossible(from_utf8(v[vSize - 1])));
3154         }
3155
3156         vector<string> idsToNames(vector<string> const & idList)
3157         {
3158                 vector<string> retval;
3159                 vector<string>::const_iterator it  = idList.begin();
3160                 vector<string>::const_iterator end = idList.end();
3161                 for (; it != end; ++it) {
3162                         LyXModule const * const mod = theModuleList[*it];
3163                         if (!mod)
3164                                 retval.push_back(to_utf8(bformat(_("%1$s (unavailable)"),
3165                                                 translateIfPossible(from_utf8(*it)))));
3166                         else
3167                                 retval.push_back(mod->getName());
3168                 }
3169                 return retval;
3170         }
3171 } // end anonymous namespace
3172
3173
3174 void GuiDocument::modulesToParams(BufferParams & bp)
3175 {
3176         // update list of loaded modules
3177         bp.clearLayoutModules();
3178         int const srows = modules_sel_model_.rowCount();
3179         for (int i = 0; i < srows; ++i)
3180                 bp.addLayoutModule(modules_sel_model_.getIDString(i));
3181         updateSelectedModules();
3182
3183         // update the list of removed modules
3184         bp.clearRemovedModules();
3185         LayoutModuleList const & reqmods = bp.baseClass()->defaultModules();
3186         list<string>::const_iterator rit = reqmods.begin();
3187         list<string>::const_iterator ren = reqmods.end();
3188
3189         // check each of the default modules
3190         for (; rit != ren; ++rit) {
3191                 list<string>::const_iterator mit = bp.getModules().begin();
3192                 list<string>::const_iterator men = bp.getModules().end();
3193                 bool found = false;
3194                 for (; mit != men; ++mit) {
3195                         if (*rit == *mit) {
3196                                 found = true;
3197                                 break;
3198                         }
3199                 }
3200                 if (!found) {
3201                         // the module isn't present so must have been removed by the user
3202                         bp.addRemovedModule(*rit);
3203                 }
3204         }
3205 }
3206
3207 void GuiDocument::modulesChanged()
3208 {
3209         modulesToParams(bp_);
3210
3211         if (buttonBox->button(QDialogButtonBox::Apply)->isEnabled()
3212             && (nonModuleChanged_ || shellescapeChanged_)) {
3213                 int const ret = Alert::prompt(_("Unapplied changes"),
3214                                 _("Some changes in the dialog were not yet applied.\n"
3215                                 "If you do not apply now, they will be lost after this action."),
3216                                 1, 1, _("&Apply"), _("&Dismiss"));
3217                 if (ret == 0)
3218                         applyView();
3219         }
3220
3221         modulesChanged_ = true;
3222         bp_.makeDocumentClass();
3223         paramsToDialog();
3224         changed();
3225 }
3226
3227
3228 void GuiDocument::updateModuleInfo()
3229 {
3230         selectionManager->update();
3231
3232         //Module description
3233         bool const focus_on_selected = selectionManager->selectedFocused();
3234         QAbstractItemView * lv;
3235         bool category = false;
3236         if (focus_on_selected) {
3237                 lv = modulesModule->selectedLV;
3238                 category = true;
3239         } else
3240                 lv = modulesModule->availableLV;
3241         if (lv->selectionModel()->selectedIndexes().isEmpty()) {
3242                 modulesModule->infoML->document()->clear();
3243                 return;
3244         }
3245         QModelIndex const & idx = lv->selectionModel()->currentIndex();
3246
3247         if (!focus_on_selected
3248             && modules_av_model_.itemFromIndex(idx)->hasChildren()) {
3249                 // This is a category header
3250                 modulesModule->infoML->document()->clear();
3251                 return;
3252         }
3253
3254         string const modName = focus_on_selected ?
3255                                 modules_sel_model_.getIDString(idx.row())
3256                               : fromqstr(modules_av_model_.data(idx, Qt::UserRole).toString());
3257         docstring desc = getModuleDescription(modName);
3258
3259         LayoutModuleList const & provmods = bp_.baseClass()->providedModules();
3260         if (std::find(provmods.begin(), provmods.end(), modName) != provmods.end()) {
3261                 if (!desc.empty())
3262                         desc += "\n";
3263                 desc += _("Module provided by document class.");
3264         }
3265
3266         if (category) {
3267                 docstring cat = getModuleCategory(modName);
3268                 if (!cat.empty()) {
3269                         if (!desc.empty())
3270                                 desc += "\n";
3271                         desc += bformat(_("<p><b>Category:</b> %1$s.</p>"),
3272                                         translateIfPossible(cat));
3273                 }
3274         }
3275
3276         vector<string> pkglist = getPackageList(modName);
3277         docstring pkgdesc = formatStrVec(pkglist, _("and"));
3278         if (!pkgdesc.empty()) {
3279                 if (!desc.empty())
3280                         desc += "\n";
3281                 desc += bformat(_("<p><b>Package(s) required:</b> %1$s.</p>"), pkgdesc);
3282         }
3283
3284         pkglist = getRequiredList(modName);
3285         if (!pkglist.empty()) {
3286                 vector<string> const reqdescs = idsToNames(pkglist);
3287                 pkgdesc = formatStrVec(reqdescs, _("or"));
3288                 if (!desc.empty())
3289                         desc += "\n";
3290                 desc += bformat(_("<p><b>Modules required:</b> %1$s.</p>"), pkgdesc);
3291         }
3292
3293         pkglist = getExcludedList(modName);
3294         if (!pkglist.empty()) {
3295                 vector<string> const reqdescs = idsToNames(pkglist);
3296                 pkgdesc = formatStrVec(reqdescs, _( "and"));
3297                 if (!desc.empty())
3298                         desc += "\n";
3299                 desc += bformat(_("<p><b>Modules excluded:</b> %1$s.</p>"), pkgdesc);
3300         }
3301
3302         if (!desc.empty())
3303                 desc += "\n";
3304         desc += bformat(_("<p><b>Filename:</b> <tt>%1$s.module</tt>.</p>"), from_utf8(modName));
3305
3306         if (!isModuleAvailable(modName)) {
3307                 if (!desc.empty())
3308                         desc += "\n";
3309                 desc += _("<p><font color=red><b>WARNING: Some required packages are unavailable!</b></font></p>");
3310         }
3311
3312         modulesModule->infoML->document()->setHtml(toqstr(desc));
3313 }
3314
3315
3316 void GuiDocument::updateNumbering()
3317 {
3318         DocumentClass const & tclass = documentClass();
3319
3320         numberingModule->tocTW->setUpdatesEnabled(false);
3321         numberingModule->tocTW->clear();
3322
3323         int const depth = numberingModule->depthSL->value();
3324         int const toc = numberingModule->tocSL->value();
3325         QString const no = qt_("No");
3326         QString const yes = qt_("Yes");
3327         QTreeWidgetItem * item = nullptr;
3328
3329         DocumentClass::const_iterator lit = tclass.begin();
3330         DocumentClass::const_iterator len = tclass.end();
3331         for (; lit != len; ++lit) {
3332                 int const toclevel = lit->toclevel;
3333                 if (toclevel != Layout::NOT_IN_TOC && !lit->counter.empty()) {
3334                         item = new QTreeWidgetItem(numberingModule->tocTW);
3335                         item->setText(0, toqstr(translateIfPossible(lit->name())));
3336                         item->setText(1, (toclevel <= depth) ? yes : no);
3337                         item->setText(2, (toclevel <= toc) ? yes : no);
3338                 }
3339         }
3340
3341         numberingModule->tocTW->setUpdatesEnabled(true);
3342         numberingModule->tocTW->update();
3343 }
3344
3345
3346 void GuiDocument::getTableStyles()
3347 {
3348         // We look for lyx files in the subdirectory dir of
3349         //   1) user_lyxdir
3350         //   2) build_lyxdir (if not empty)
3351         //   3) system_lyxdir
3352         // in this order. Files with a given sub-hierarchy will
3353         // only be listed once.
3354         // We also consider i18n subdirectories and store them separately.
3355         QStringList dirs;
3356
3357         // The three locations to look at.
3358         string const user = addPath(package().user_support().absFileName(), "tabletemplates");
3359         string const build = addPath(package().build_support().absFileName(), "tabletemplates");
3360         string const system = addPath(package().system_support().absFileName(), "tabletemplates");
3361
3362         dirs << toqstr(user)
3363              << toqstr(build)
3364              << toqstr(system);
3365
3366         for (int i = 0; i < dirs.size(); ++i) {
3367                 QString const & dir = dirs.at(i);
3368                 QDirIterator it(dir, QDir::Files, QDirIterator::Subdirectories);
3369                 while (it.hasNext()) {
3370                         QString fn = QFileInfo(it.next()).fileName();
3371                         if (!fn.endsWith(".lyx") || fn.contains("_1x"))
3372                                 continue;
3373                         QString data = fn.left(fn.lastIndexOf(".lyx"));
3374                         QString guiname = data;
3375                         guiname = toqstr(translateIfPossible(qstring_to_ucs4(guiname.replace('_', ' '))));
3376                         QString relpath = toqstr(makeRelPath(qstring_to_ucs4(fn),
3377                                                              qstring_to_ucs4(dir)));
3378                         if (textLayoutModule->tableStyleCO->findData(data) == -1)
3379                                 textLayoutModule->tableStyleCO->addItem(guiname, data);
3380                 }
3381         }
3382 }
3383
3384
3385 void GuiDocument::updateDefaultFormat()
3386 {
3387         if (!bufferview())
3388                 return;
3389         // make a copy in order to consider unapplied changes
3390         BufferParams param_copy = buffer().params();
3391         param_copy.useNonTeXFonts = fontModule->osFontsCB->isChecked();
3392         int const idx = latexModule->classCO->currentIndex();
3393         if (idx >= 0) {
3394                 string const classname = fromqstr(latexModule->classCO->getData(idx));
3395                 param_copy.setBaseClass(classname, buffer().layoutPos());
3396                 param_copy.makeDocumentClass(true);
3397         }
3398         outputModule->defaultFormatCO->blockSignals(true);
3399         outputModule->defaultFormatCO->clear();
3400         outputModule->defaultFormatCO->addItem(qt_("Default"),
3401                                 QVariant(QString("default")));
3402         FormatList const & formats =
3403                                 param_copy.exportableFormats(true);
3404         for (Format const * f : formats)
3405                 outputModule->defaultFormatCO->addItem
3406                         (toqstr(translateIfPossible(f->prettyname())),
3407                          QVariant(toqstr(f->name())));
3408         outputModule->defaultFormatCO->blockSignals(false);
3409 }
3410
3411
3412 bool GuiDocument::isChildIncluded(string const & child)
3413 {
3414         if (includeonlys_.empty())
3415                 return false;
3416         return (std::find(includeonlys_.begin(),
3417                           includeonlys_.end(), child) != includeonlys_.end());
3418 }
3419
3420
3421 void GuiDocument::applyView()
3422 {
3423         // preamble
3424         preambleModule->apply(bp_);
3425         localLayout->apply(bp_);
3426
3427         // date
3428         bp_.suppress_date = latexModule->suppressDateCB->isChecked();
3429         bp_.use_refstyle  = latexModule->refstyleCB->isChecked();
3430
3431         // biblio
3432         string const engine =
3433                 fromqstr(biblioModule->citeEngineCO->itemData(
3434                                 biblioModule->citeEngineCO->currentIndex()).toString());
3435         bp_.setCiteEngine(engine);
3436
3437         CiteEngineType const style = CiteEngineType(biblioModule->citeStyleCO->itemData(
3438                 biblioModule->citeStyleCO->currentIndex()).toInt());
3439         if (theCiteEnginesList[engine]->hasEngineType(style))
3440                 bp_.setCiteEngineType(style);
3441         else
3442                 bp_.setCiteEngineType(ENGINE_TYPE_DEFAULT);
3443
3444         bp_.splitbib(biblioModule->bibtopicCB->isChecked());
3445
3446         bp_.multibib = fromqstr(biblioModule->bibunitsCO->itemData(
3447                                 biblioModule->bibunitsCO->currentIndex()).toString());
3448
3449         bp_.setDefaultBiblioStyle(fromqstr(biblioModule->defaultBiblioCO->currentText()));
3450
3451         bp_.biblatex_bibstyle = fromqstr(biblioModule->biblatexBbxCO->currentText());
3452         bp_.biblatex_citestyle = fromqstr(biblioModule->biblatexCbxCO->currentText());
3453         bp_.biblio_opts = fromqstr(biblioModule->citePackageOptionsLE->text());
3454
3455         string const bibtex_command =
3456                 fromqstr(biblioModule->bibtexCO->itemData(
3457                         biblioModule->bibtexCO->currentIndex()).toString());
3458         string const bibtex_options =
3459                 fromqstr(biblioModule->bibtexOptionsLE->text());
3460         if (bibtex_command == "default" || bibtex_options.empty())
3461                 bp_.bibtex_command = bibtex_command;
3462         else
3463                 bp_.bibtex_command = bibtex_command + " " + bibtex_options;
3464
3465         if (biblioChanged_) {
3466                 buffer().invalidateBibinfoCache();
3467                 buffer().removeBiblioTempFiles();
3468         }
3469
3470         // Indices
3471         indicesModule->apply(bp_);
3472
3473         // language & quotes
3474         switch (langModule->encodingCO->currentIndex()) {
3475                 case EncodingSets::unicode: {
3476                         if (!fontModule->osFontsCB->isChecked())
3477                                 bp_.inputenc = fromqstr(langModule->unicodeEncodingCO->itemData(
3478                                         langModule->unicodeEncodingCO->currentIndex()).toString());
3479                         break;
3480                 }
3481                 case EncodingSets::legacy: {
3482                         bp_.inputenc = "auto-legacy";
3483                         bp_.inputenc = fromqstr(langModule->autoEncodingCO->itemData(
3484                                 langModule->autoEncodingCO->currentIndex()).toString());
3485                         break;
3486                 }
3487                 case EncodingSets::custom: {
3488                         bp_.inputenc = fromqstr(langModule->customEncodingCO->itemData(
3489                                 langModule->customEncodingCO->currentIndex()).toString());
3490                         break;
3491                 }
3492                 default:
3493                         // this should never happen
3494                         bp_.inputenc = "utf8";
3495         }
3496         bp_.quotes_style = QuoteStyle(langModule->quoteStyleCO->itemData(
3497                 langModule->quoteStyleCO->currentIndex()).toInt());
3498         bp_.dynamic_quotes = langModule->dynamicQuotesCB->isChecked();
3499
3500         QString const langname = langModule->languageCO->itemData(
3501                 langModule->languageCO->currentIndex()).toString();
3502         Language const * newlang = lyx::languages.getLanguage(fromqstr(langname));
3503         Cursor & cur = const_cast<BufferView *>(bufferview())->cursor();
3504         // If current cursor language was the document language, then update it too.
3505         if (cur.current_font.language() == bp_.language) {
3506                 cur.current_font.setLanguage(newlang);
3507                 cur.real_current_font.setLanguage(newlang);
3508         }
3509         bp_.language = newlang;
3510
3511         QString const pack = langModule->languagePackageCO->itemData(
3512                 langModule->languagePackageCO->currentIndex()).toString();
3513         if (pack == "custom")
3514                 bp_.lang_package =
3515                         fromqstr(langModule->languagePackageLE->text());
3516         else
3517                 bp_.lang_package = fromqstr(pack);
3518
3519         //color
3520         bp_.backgroundcolor = set_backgroundcolor;
3521         bp_.isbackgroundcolor = is_backgroundcolor;
3522         bp_.fontcolor = set_fontcolor;
3523         bp_.isfontcolor = is_fontcolor;
3524         bp_.notefontcolor = set_notefontcolor;
3525         bp_.isnotefontcolor = is_notefontcolor;
3526         if (is_notefontcolor) {
3527                 // Set information used in statusbar (#12130)
3528                 lcolor.setColor("notefontcolor", lyx::X11hexname(set_notefontcolor));
3529                 lcolor.setGUIName("notefontcolor", N_("greyedout inset text"));
3530         }
3531         bp_.boxbgcolor = set_boxbgcolor;
3532         bp_.isboxbgcolor = is_boxbgcolor;
3533
3534         // numbering
3535         if (bp_.documentClass().hasTocLevels()) {
3536                 bp_.tocdepth = numberingModule->tocSL->value();
3537                 bp_.secnumdepth = numberingModule->depthSL->value();
3538         }
3539         bp_.use_lineno = numberingModule->linenoCB->isChecked();
3540         bp_.lineno_opts = fromqstr(numberingModule->linenoLE->text());
3541
3542         // bullets
3543         bp_.user_defined_bullet(0) = bulletsModule->bullet(0);
3544         bp_.user_defined_bullet(1) = bulletsModule->bullet(1);
3545         bp_.user_defined_bullet(2) = bulletsModule->bullet(2);
3546         bp_.user_defined_bullet(3) = bulletsModule->bullet(3);
3547
3548         // packages
3549         bp_.graphics_driver =
3550                 tex_graphics[latexModule->psdriverCO->currentIndex()];
3551
3552         // text layout
3553         int idx = latexModule->classCO->currentIndex();
3554         if (idx >= 0) {
3555                 string const classname = fromqstr(latexModule->classCO->getData(idx));
3556                 bp_.setBaseClass(classname, buffer().layoutPos());
3557         }
3558
3559         // Modules
3560         modulesToParams(bp_);
3561
3562         // Math
3563         map<string, string> const & packages = BufferParams::auto_packages();
3564         for (map<string, string>::const_iterator it = packages.begin();
3565              it != packages.end(); ++it) {
3566                 QTableWidgetItem * item = mathsModule->packagesTW->findItems(toqstr(it->first), Qt::MatchExactly)[0];
3567                 if (!item)
3568                         continue;
3569                 int row = mathsModule->packagesTW->row(item);
3570
3571                 QRadioButton * rb =
3572                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 1)->layout()->itemAt(0)->widget();
3573                 if (rb->isChecked()) {
3574                         bp_.use_package(it->first, BufferParams::package_auto);
3575                         continue;
3576                 }
3577                 rb = (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 2)->layout()->itemAt(0)->widget();
3578                 if (rb->isChecked()) {
3579                         bp_.use_package(it->first, BufferParams::package_on);
3580                         continue;
3581                 }
3582                 rb = (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 3)->layout()->itemAt(0)->widget();
3583                 if (rb->isChecked())
3584                         bp_.use_package(it->first, BufferParams::package_off);
3585         }
3586         // if math is indented
3587         bp_.is_math_indent = mathsModule->MathIndentCB->isChecked();
3588         if (bp_.is_math_indent) {
3589                 // if formulas are indented
3590                 switch (mathsModule->MathIndentCO->currentIndex()) {
3591                 case 0:
3592                         bp_.setMathIndent(Length());
3593                         break;
3594                 case 1: {
3595                         Length mathindent(widgetsToLength(mathsModule->MathIndentLE,
3596                                                           mathsModule->MathIndentLengthCO));
3597                         bp_.setMathIndent(mathindent);
3598                         break;
3599                 }
3600                 default:
3601                         // this should never happen
3602                         bp_.setMathIndent(Length());
3603                         break;
3604                 }
3605         }
3606         switch (mathsModule->MathNumberingPosCO->currentIndex()) {
3607                 case 0:
3608                         bp_.math_numbering_side = BufferParams::LEFT;
3609                         break;
3610                 case 1:
3611                         bp_.math_numbering_side = BufferParams::DEFAULT;
3612                         break;
3613                 case 2:
3614                         bp_.math_numbering_side = BufferParams::RIGHT;
3615                         break;
3616                 default:
3617                         // this should never happen
3618                         bp_.math_numbering_side = BufferParams::DEFAULT;
3619                         break;
3620         }
3621
3622         // Page Layout
3623         if (pageLayoutModule->pagestyleCO->currentIndex() == 0)
3624                 bp_.pagestyle = "default";
3625         else {
3626                 QString style_gui = pageLayoutModule->pagestyleCO->currentText();
3627                 for (size_t i = 0; i != pagestyles.size(); ++i)
3628                         if (pagestyles[i].second == style_gui)
3629                                 bp_.pagestyle = pagestyles[i].first;
3630         }
3631
3632         // Text Layout
3633         switch (textLayoutModule->lspacingCO->currentIndex()) {
3634         case 0:
3635                 bp_.spacing().set(Spacing::Single);
3636                 break;
3637         case 1:
3638                 bp_.spacing().set(Spacing::Onehalf);
3639                 break;
3640         case 2:
3641                 bp_.spacing().set(Spacing::Double);
3642                 break;
3643         case 3: {
3644                 string s = widgetToDoubleStr(textLayoutModule->lspacingLE);
3645                 if (s.empty())
3646                         bp_.spacing().set(Spacing::Single);
3647                 else
3648                         bp_.spacing().set(Spacing::Other, s);
3649                 break;
3650                 }
3651         }
3652
3653         if (textLayoutModule->twoColumnCB->isChecked())
3654                 bp_.columns = 2;
3655         else
3656                 bp_.columns = 1;
3657
3658         bp_.justification = textLayoutModule->justCB->isChecked();
3659
3660         if (textLayoutModule->indentRB->isChecked()) {
3661                 // if paragraphs are separated by an indentation
3662                 bp_.paragraph_separation = BufferParams::ParagraphIndentSeparation;
3663                 switch (textLayoutModule->indentCO->currentIndex()) {
3664                 case 0:
3665                         bp_.setParIndent(Length());
3666                         break;
3667                 case 1: {
3668                         Length parindent(widgetsToLength(textLayoutModule->indentLE,
3669                                                          textLayoutModule->indentLengthCO));
3670                         bp_.setParIndent(parindent);
3671                         break;
3672                 }
3673                 default:
3674                         // this should never happen
3675                         bp_.setParIndent(Length());
3676                         break;
3677                 }
3678         } else {
3679                 // if paragraphs are separated by a skip
3680                 bp_.paragraph_separation = BufferParams::ParagraphSkipSeparation;
3681                 VSpace::VSpaceKind spacekind =
3682                         VSpace::VSpaceKind(textLayoutModule->skipCO->itemData(textLayoutModule->skipCO->currentIndex()).toInt());
3683                 switch (spacekind) {
3684                 case VSpace::SMALLSKIP:
3685                 case VSpace::MEDSKIP:
3686                 case VSpace::BIGSKIP:
3687                 case VSpace::HALFLINE:
3688                 case VSpace::FULLLINE:
3689                         bp_.setDefSkip(VSpace(spacekind));
3690                         break;
3691                 case VSpace::LENGTH: {
3692                         VSpace vs = VSpace(
3693                                 widgetsToLength(textLayoutModule->skipLE,
3694                                 textLayoutModule->skipLengthCO)
3695                                 );
3696                         bp_.setDefSkip(vs);
3697                         break;
3698                 }
3699                 default:
3700                         // this should never happen
3701                         bp_.setDefSkip(VSpace(VSpace::MEDSKIP));
3702                         break;
3703                 }
3704         }
3705         bp_.tablestyle = fromqstr(textLayoutModule->tableStyleCO->itemData(
3706                                       textLayoutModule->tableStyleCO->currentIndex()).toString());
3707
3708         bp_.options =
3709                 fromqstr(latexModule->optionsLE->text());
3710
3711         bp_.use_default_options =
3712                 latexModule->defaultOptionsCB->isChecked();
3713
3714         if (latexModule->childDocGB->isChecked())
3715                 bp_.master =
3716                         fromqstr(latexModule->childDocLE->text());
3717         else
3718                 bp_.master = string();
3719
3720         // Master/Child
3721         bp_.clearIncludedChildren();
3722         if (masterChildModule->includeonlyRB->isChecked()) {
3723                 list<string>::const_iterator it = includeonlys_.begin();
3724                 for (; it != includeonlys_.end() ; ++it) {
3725                         bp_.addIncludedChildren(*it);
3726                 }
3727         }
3728         if (masterChildModule->maintainCRNoneRB->isChecked())
3729                 bp_.maintain_unincluded_children =
3730                         BufferParams::CM_None;
3731         else if (masterChildModule->maintainCRMostlyRB->isChecked())
3732                 bp_.maintain_unincluded_children =
3733                         BufferParams::CM_Mostly;
3734         else
3735                 bp_.maintain_unincluded_children =
3736                         BufferParams::CM_Strict;
3737         updateIncludeonlyDisplay();
3738
3739         // Float Settings
3740         bp_.float_placement = floatModule->getPlacement();
3741         bp_.float_alignment = floatModule->getAlignment();
3742
3743         // Listings
3744         // text should have passed validation
3745         idx = listingsModule->packageCO->currentIndex();
3746         bp_.use_minted = string(lst_packages[idx]) == "Minted";
3747         bp_.listings_params =
3748                 InsetListingsParams(fromqstr(listingsModule->listingsED->toPlainText())).params();
3749
3750         // Formats
3751         bp_.default_output_format = fromqstr(outputModule->defaultFormatCO->itemData(
3752                 outputModule->defaultFormatCO->currentIndex()).toString());
3753
3754         bool const nontexfonts = fontModule->osFontsCB->isChecked();
3755         bp_.useNonTeXFonts = nontexfonts;
3756
3757         bp_.shell_escape = outputModule->shellescapeCB->isChecked();
3758         if (!bp_.shell_escape)
3759             theSession().shellescapeFiles().remove(buffer().absFileName());
3760         else if (!theSession().shellescapeFiles().find(buffer().absFileName()))
3761             theSession().shellescapeFiles().insert(buffer().absFileName());
3762         Buffer & buf = const_cast<Buffer &>(buffer());
3763         buf.params().shell_escape = bp_.shell_escape;
3764
3765         bp_.output_sync = outputModule->outputsyncCB->isChecked();
3766
3767         bp_.output_sync_macro = fromqstr(outputModule->synccustomCB->currentText());
3768
3769         int mathfmt = outputModule->mathoutCB->currentIndex();
3770         if (mathfmt == -1)
3771                 mathfmt = 0;
3772         BufferParams::MathOutput const mo =
3773                 static_cast<BufferParams::MathOutput>(mathfmt);
3774         bp_.html_math_output = mo;
3775         bp_.html_be_strict = outputModule->strictCB->isChecked();
3776         bp_.html_css_as_file = outputModule->cssCB->isChecked();
3777         bp_.html_math_img_scale = outputModule->mathimgSB->value();
3778         bp_.display_pixel_ratio = theGuiApp()->pixelRatio();
3779
3780         int tablefmt = outputModule->tableoutCB->currentIndex();
3781         if (tablefmt == -1)
3782                 tablefmt = 0;
3783         auto const to = static_cast<BufferParams::TableOutput>(tablefmt);
3784         bp_.docbook_table_output = to;
3785
3786         int mathmlprefix = outputModule->mathmlprefixCB->currentIndex();
3787         if (mathmlprefix == -1)
3788                 mathmlprefix = 0;
3789         auto const mp = static_cast<BufferParams::MathMLNameSpacePrefix>(mathmlprefix);
3790         bp_.docbook_mathml_prefix = mp;
3791
3792         bp_.save_transient_properties =
3793                 outputModule->saveTransientPropertiesCB->isChecked();
3794         bp_.postpone_fragile_content =
3795                 outputModule->postponeFragileCB->isChecked();
3796
3797         // fonts
3798         bp_.fonts_roman[nontexfonts] =
3799                 fromqstr(fontModule->fontsRomanCO->
3800                         itemData(fontModule->fontsRomanCO->currentIndex()).toString());
3801         bp_.fonts_roman[!nontexfonts] = fromqstr(fontModule->font_roman);
3802         bp_.font_roman_opts = fromqstr(fontModule->fontspecRomanLE->text());
3803
3804         bp_.fonts_sans[nontexfonts] =
3805                 fromqstr(fontModule->fontsSansCO->
3806                         itemData(fontModule->fontsSansCO->currentIndex()).toString());
3807         bp_.fonts_sans[!nontexfonts] = fromqstr(fontModule->font_sans);
3808         bp_.font_sans_opts = fromqstr(fontModule->fontspecSansLE->text());
3809
3810         bp_.fonts_typewriter[nontexfonts] =
3811                 fromqstr(fontModule->fontsTypewriterCO->
3812                         itemData(fontModule->fontsTypewriterCO->currentIndex()).toString());
3813         bp_.fonts_typewriter[!nontexfonts] = fromqstr(fontModule->font_typewriter);
3814         bp_.font_typewriter_opts = fromqstr(fontModule->fontspecTypewriterLE->text());
3815
3816         bp_.fonts_math[nontexfonts] =
3817                 fromqstr(fontModule->fontsMathCO->
3818                         itemData(fontModule->fontsMathCO->currentIndex()).toString());
3819         bp_.fonts_math[!nontexfonts] = fromqstr(fontModule->font_math);
3820
3821         QString const fontenc =
3822                 fontModule->fontencCO->itemData(fontModule->fontencCO->currentIndex()).toString();
3823         if (fontenc == "custom")
3824                 bp_.fontenc = fromqstr(fontModule->fontencLE->text());
3825         else
3826                 bp_.fontenc = fromqstr(fontenc);
3827
3828         bp_.fonts_cjk =
3829                 fromqstr(fontModule->cjkFontLE->text());
3830
3831         bp_.use_microtype = fontModule->microtypeCB->isChecked();
3832         bp_.use_dash_ligatures = !fontModule->dashesCB->isChecked();
3833
3834         bp_.fonts_sans_scale[nontexfonts] = fontModule->scaleSansSB->value();
3835         bp_.fonts_sans_scale[!nontexfonts] = fontModule->font_sf_scale;
3836
3837         bp_.fonts_typewriter_scale[nontexfonts] = fontModule->scaleTypewriterSB->value();
3838         bp_.fonts_typewriter_scale[!nontexfonts] = fontModule->font_tt_scale;
3839
3840         bp_.fonts_expert_sc = fontModule->fontScCB->isChecked();
3841
3842         bp_.fonts_roman_osf = fontModule->fontOsfCB->isChecked();
3843         bp_.fonts_sans_osf = fontModule->fontSansOsfCB->isChecked();
3844         bp_.fonts_typewriter_osf = fontModule->fontTypewriterOsfCB->isChecked();
3845
3846         if (nontexfonts)
3847                 bp_.fonts_default_family = "default";
3848         else
3849                 bp_.fonts_default_family = GuiDocument::fontfamilies[
3850                         fontModule->fontsDefaultCO->currentIndex()];
3851
3852         if (fontModule->fontsizeCO->currentIndex() == 0)
3853                 bp_.fontsize = "default";
3854         else
3855                 bp_.fontsize =
3856                         fromqstr(fontModule->fontsizeCO->currentText());
3857
3858         // paper
3859         bp_.papersize = PAPER_SIZE(
3860                 pageLayoutModule->papersizeCO->currentIndex());
3861
3862         bp_.paperwidth = widgetsToLength(pageLayoutModule->paperwidthLE,
3863                 pageLayoutModule->paperwidthUnitCO);
3864
3865         bp_.paperheight = widgetsToLength(pageLayoutModule->paperheightLE,
3866                 pageLayoutModule->paperheightUnitCO);
3867
3868         if (pageLayoutModule->facingPagesCB->isChecked())
3869                 bp_.sides = TwoSides;
3870         else
3871                 bp_.sides = OneSide;
3872
3873         if (pageLayoutModule->landscapeRB->isChecked())
3874                 bp_.orientation = ORIENTATION_LANDSCAPE;
3875         else
3876                 bp_.orientation = ORIENTATION_PORTRAIT;
3877
3878         // margins
3879         bp_.use_geometry = !marginsModule->marginCB->isChecked();
3880
3881         Ui::MarginsUi const * m = marginsModule;
3882
3883         bp_.leftmargin = widgetsToLength(m->innerLE, m->innerUnit);
3884         bp_.topmargin = widgetsToLength(m->topLE, m->topUnit);
3885         bp_.rightmargin = widgetsToLength(m->outerLE, m->outerUnit);
3886         bp_.bottommargin = widgetsToLength(m->bottomLE, m->bottomUnit);
3887         bp_.headheight = widgetsToLength(m->headheightLE, m->headheightUnit);
3888         bp_.headsep = widgetsToLength(m->headsepLE, m->headsepUnit);
3889         bp_.footskip = widgetsToLength(m->footskipLE, m->footskipUnit);
3890         bp_.columnsep = widgetsToLength(m->columnsepLE, m->columnsepUnit);
3891
3892         // branches
3893         branchesModule->apply(bp_);
3894
3895         // PDF support
3896         PDFOptions & pdf = bp_.pdfoptions();
3897         pdf.use_hyperref = pdfSupportModule->use_hyperrefGB->isChecked();
3898         pdf.title = fromqstr(pdfSupportModule->titleLE->text());
3899         pdf.author = fromqstr(pdfSupportModule->authorLE->text());
3900         pdf.subject = fromqstr(pdfSupportModule->subjectLE->text());
3901         pdf.keywords = fromqstr(pdfSupportModule->keywordsLE->text());
3902
3903         pdf.bookmarks = pdfSupportModule->bookmarksGB->isChecked();
3904         pdf.bookmarksnumbered = pdfSupportModule->bookmarksnumberedCB->isChecked();
3905         pdf.bookmarksopen = pdfSupportModule->bookmarksopenGB->isChecked();
3906         pdf.bookmarksopenlevel = pdfSupportModule->bookmarksopenlevelSB->value();
3907
3908         pdf.breaklinks = pdfSupportModule->breaklinksCB->isChecked();
3909         pdf.pdfborder = pdfSupportModule->pdfborderCB->isChecked();
3910         pdf.pdfusetitle = pdfSupportModule->pdfusetitleCB->isChecked();
3911         pdf.colorlinks = pdfSupportModule->colorlinksCB->isChecked();
3912         pdf.backref =
3913                 backref_opts[pdfSupportModule->backrefCO->currentIndex()];
3914         if (pdfSupportModule->fullscreenCB->isChecked())
3915                 pdf.pagemode = pdf.pagemode_fullscreen;
3916         else
3917                 pdf.pagemode.clear();
3918         pdf.quoted_options = pdf.quoted_options_check(
3919                                 fromqstr(pdfSupportModule->optionsLE->text()));
3920
3921         // change tracking
3922         bp_.track_changes = changesModule->trackChangesCB->isChecked();
3923         bp_.output_changes = changesModule->outputChangesCB->isChecked();
3924         bool const cb_switched_off = (bp_.change_bars
3925                                       && !changesModule->changeBarsCB->isChecked());
3926         bp_.change_bars = changesModule->changeBarsCB->isChecked();
3927         if (cb_switched_off)
3928                 // if change bars have been switched off,
3929                 // we need to ditch the aux file
3930                 buffer().requireFreshStart(true);
3931
3932         // reset trackers
3933         nonModuleChanged_ = false;
3934         shellescapeChanged_ = false;
3935 }
3936
3937
3938 void GuiDocument::paramsToDialog()
3939 {
3940         // set the default unit
3941         Length::UNIT const default_unit = Length::defaultUnit();
3942
3943         // preamble
3944         preambleModule->update(bp_, id());
3945         localLayout->update(bp_, id());
3946
3947         // date
3948         latexModule->suppressDateCB->setChecked(bp_.suppress_date);
3949         latexModule->refstyleCB->setChecked(bp_.use_refstyle);
3950
3951         // biblio
3952         string const cite_engine = bp_.citeEngine();
3953
3954         biblioModule->citeEngineCO->setCurrentIndex(
3955                 biblioModule->citeEngineCO->findData(toqstr(cite_engine)));
3956
3957         updateEngineType(documentClass().opt_enginetype(),
3958                 bp_.citeEngineType());
3959
3960         checkPossibleCiteEngines();
3961
3962         biblioModule->citeStyleCO->setCurrentIndex(
3963                 biblioModule->citeStyleCO->findData(bp_.citeEngineType()));
3964
3965         biblioModule->bibtopicCB->setChecked(bp_.splitbib());
3966
3967         biblioModule->bibunitsCO->clear();
3968         biblioModule->bibunitsCO->addItem(qt_("No"), QString());
3969         if (documentClass().hasLaTeXLayout("part"))
3970                 biblioModule->bibunitsCO->addItem(qt_("per part"), toqstr("part"));
3971         if (documentClass().hasLaTeXLayout("chapter"))
3972                 biblioModule->bibunitsCO->addItem(qt_("per chapter"), toqstr("chapter"));
3973         if (documentClass().hasLaTeXLayout("section"))
3974                 biblioModule->bibunitsCO->addItem(qt_("per section"), toqstr("section"));
3975         if (documentClass().hasLaTeXLayout("subsection"))
3976                 biblioModule->bibunitsCO->addItem(qt_("per subsection"), toqstr("subsection"));
3977         biblioModule->bibunitsCO->addItem(qt_("per child document"), toqstr("child"));
3978
3979         int const mbpos = biblioModule->bibunitsCO->findData(toqstr(bp_.multibib));
3980         if (mbpos != -1)
3981                 biblioModule->bibunitsCO->setCurrentIndex(mbpos);
3982         else
3983                 biblioModule->bibunitsCO->setCurrentIndex(0);
3984
3985         updateEngineDependends();
3986
3987         if (isBiblatex()) {
3988                 updateDefaultBiblio(bp_.biblatex_bibstyle, "bbx");
3989                 updateDefaultBiblio(bp_.biblatex_citestyle, "cbx");
3990         } else
3991                 updateDefaultBiblio(bp_.defaultBiblioStyle());
3992
3993         biblioModule->citePackageOptionsLE->setText(toqstr(bp_.biblio_opts));
3994
3995         string command;
3996         string options =
3997                 split(bp_.bibtex_command, command, ' ');
3998
3999         int const bpos = biblioModule->bibtexCO->findData(toqstr(command));
4000         if (bpos != -1) {
4001                 biblioModule->bibtexCO->setCurrentIndex(bpos);
4002                 biblioModule->bibtexOptionsLE->setText(toqstr(options).trimmed());
4003         } else {
4004                 // We reset to default if we do not know the specified compiler
4005                 // This is for security reasons
4006                 biblioModule->bibtexCO->setCurrentIndex(
4007                         biblioModule->bibtexCO->findData(toqstr("default")));
4008                 biblioModule->bibtexOptionsLE->clear();
4009         }
4010         biblioModule->bibtexOptionsLE->setEnabled(
4011                 biblioModule->bibtexCO->currentIndex() != 0);
4012
4013         biblioChanged_ = false;
4014
4015         // indices
4016         // We may be called when there is no Buffer, e.g., when
4017         // the last view has just been closed.
4018         bool const isReadOnly = isBufferAvailable() ? buffer().isReadonly() : false;
4019         indicesModule->update(bp_, isReadOnly);
4020
4021         // language & quotes
4022         int const pos = langModule->languageCO->findData(toqstr(
4023                 bp_.language->lang()));
4024         langModule->languageCO->setCurrentIndex(pos);
4025
4026         updateQuoteStyles();
4027
4028         langModule->quoteStyleCO->setCurrentIndex(
4029                 langModule->quoteStyleCO->findData(static_cast<int>(bp_.quotes_style)));
4030         langModule->dynamicQuotesCB->setChecked(bp_.dynamic_quotes);
4031
4032         // LaTeX input encoding: set after the fonts (see below)
4033
4034         int p = langModule->languagePackageCO->findData(toqstr(bp_.lang_package));
4035         if (p == -1) {
4036                 langModule->languagePackageCO->setCurrentIndex(
4037                           langModule->languagePackageCO->findData("custom"));
4038                 langModule->languagePackageLE->setText(toqstr(bp_.lang_package));
4039         } else {
4040                 langModule->languagePackageCO->setCurrentIndex(p);
4041                 langModule->languagePackageLE->clear();
4042         }
4043
4044         //color
4045         if (bp_.isfontcolor) {
4046                 colorModule->fontColorPB->setStyleSheet(
4047                         colorButtonStyleSheet(rgb2qcolor(bp_.fontcolor)));
4048         }
4049         set_fontcolor = bp_.fontcolor;
4050         is_fontcolor = bp_.isfontcolor;
4051
4052         colorModule->noteFontColorPB->setStyleSheet(
4053                 colorButtonStyleSheet(rgb2qcolor(bp_.notefontcolor)));
4054         set_notefontcolor = bp_.notefontcolor;
4055         is_notefontcolor = bp_.isnotefontcolor;
4056
4057         if (bp_.isbackgroundcolor) {
4058                 colorModule->backgroundPB->setStyleSheet(
4059                         colorButtonStyleSheet(rgb2qcolor(bp_.backgroundcolor)));
4060         }
4061         set_backgroundcolor = bp_.backgroundcolor;
4062         is_backgroundcolor = bp_.isbackgroundcolor;
4063
4064         colorModule->boxBackgroundPB->setStyleSheet(
4065                 colorButtonStyleSheet(rgb2qcolor(bp_.boxbgcolor)));
4066         set_boxbgcolor = bp_.boxbgcolor;
4067         is_boxbgcolor = bp_.isboxbgcolor;
4068
4069         // numbering
4070         int const min_toclevel = documentClass().min_toclevel();
4071         int const max_toclevel = documentClass().max_toclevel();
4072         if (documentClass().hasTocLevels()) {
4073                 numberingModule->setEnabled(true);
4074                 numberingModule->depthSL->setMinimum(min_toclevel - 1);
4075                 numberingModule->depthSL->setMaximum(max_toclevel);
4076                 numberingModule->depthSL->setValue(bp_.secnumdepth);
4077                 numberingModule->tocSL->setMaximum(min_toclevel - 1);
4078                 numberingModule->tocSL->setMaximum(max_toclevel);
4079                 numberingModule->tocSL->setValue(bp_.tocdepth);
4080                 updateNumbering();
4081         } else {
4082                 numberingModule->setEnabled(false);
4083                 numberingModule->tocTW->clear();
4084         }
4085
4086         numberingModule->linenoCB->setChecked(bp_.use_lineno);
4087         numberingModule->linenoLE->setEnabled(bp_.use_lineno);
4088         numberingModule->linenoLA->setEnabled(bp_.use_lineno);
4089         numberingModule->linenoLE->setText(toqstr(bp_.lineno_opts));
4090
4091         // bullets
4092         bulletsModule->setBullet(0, bp_.user_defined_bullet(0));
4093         bulletsModule->setBullet(1, bp_.user_defined_bullet(1));
4094         bulletsModule->setBullet(2, bp_.user_defined_bullet(2));
4095         bulletsModule->setBullet(3, bp_.user_defined_bullet(3));
4096         bulletsModule->init();
4097
4098         // packages
4099         int nitem = findToken(tex_graphics, bp_.graphics_driver);
4100         if (nitem >= 0)
4101                 latexModule->psdriverCO->setCurrentIndex(nitem);
4102         updateModuleInfo();
4103
4104         // math
4105         mathsModule->MathIndentCB->setChecked(bp_.is_math_indent);
4106         if (bp_.is_math_indent) {
4107                 Length const mathindent = bp_.getMathIndent();
4108                 int indent = 0;
4109                 if (!mathindent.empty()) {
4110                         lengthToWidgets(mathsModule->MathIndentLE,
4111                                         mathsModule->MathIndentLengthCO,
4112                                         mathindent, default_unit);
4113                         indent = 1;
4114                 }
4115                 mathsModule->MathIndentCO->setCurrentIndex(indent);
4116                 enableMathIndent(indent);
4117         }
4118         switch(bp_.math_numbering_side) {
4119         case BufferParams::LEFT:
4120                 mathsModule->MathNumberingPosCO->setCurrentIndex(0);
4121                 break;
4122         case BufferParams::DEFAULT:
4123                 mathsModule->MathNumberingPosCO->setCurrentIndex(1);
4124                 break;
4125         case BufferParams::RIGHT:
4126                 mathsModule->MathNumberingPosCO->setCurrentIndex(2);
4127         }
4128
4129         map<string, string> const & packages = BufferParams::auto_packages();
4130         for (map<string, string>::const_iterator it = packages.begin();
4131              it != packages.end(); ++it) {
4132                 QTableWidgetItem * item = mathsModule->packagesTW->findItems(toqstr(it->first), Qt::MatchExactly)[0];
4133                 if (!item)
4134                         continue;
4135                 int row = mathsModule->packagesTW->row(item);
4136                 switch (bp_.use_package(it->first)) {
4137                         case BufferParams::package_off: {
4138                                 QRadioButton * rb =
4139                                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 3)->layout()->itemAt(0)->widget();
4140                                 rb->setChecked(true);
4141                                 break;
4142                         }
4143                         case BufferParams::package_on: {
4144                                 QRadioButton * rb =
4145                                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 2)->layout()->itemAt(0)->widget();
4146                                 rb->setChecked(true);
4147                                 break;
4148                         }
4149                         case BufferParams::package_auto: {
4150                                 QRadioButton * rb =
4151                                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 1)->layout()->itemAt(0)->widget();
4152                                 rb->setChecked(true);
4153                                 break;
4154                         }
4155                 }
4156         }
4157
4158         switch (bp_.spacing().getSpace()) {
4159                 case Spacing::Other: nitem = 3; break;
4160                 case Spacing::Double: nitem = 2; break;
4161                 case Spacing::Onehalf: nitem = 1; break;
4162                 case Spacing::Default: case Spacing::Single: nitem = 0; break;
4163         }
4164
4165         // text layout
4166         string const & layoutID = bp_.baseClassID();
4167         setLayoutComboByIDString(layoutID);
4168
4169         updatePagestyle(documentClass().opt_pagestyle(),
4170                                  bp_.pagestyle);
4171
4172         textLayoutModule->lspacingCO->setCurrentIndex(nitem);
4173         if (bp_.spacing().getSpace() == Spacing::Other) {
4174                 doubleToWidget(textLayoutModule->lspacingLE,
4175                         bp_.spacing().getValueAsString());
4176         }
4177         setLSpacing(nitem);
4178         int ts = textLayoutModule->tableStyleCO->findData(toqstr(bp_.tablestyle));
4179         if (ts != -1)
4180                 textLayoutModule->tableStyleCO->setCurrentIndex(ts);
4181
4182         if (bp_.paragraph_separation == BufferParams::ParagraphIndentSeparation) {
4183                 textLayoutModule->indentRB->setChecked(true);
4184                 string parindent = bp_.getParIndent().asString();
4185                 int indent = 0;
4186                 if (!parindent.empty()) {
4187                         lengthToWidgets(textLayoutModule->indentLE,
4188                                         textLayoutModule->indentLengthCO,
4189                                         parindent, default_unit);
4190                         indent = 1;
4191                 }
4192                 textLayoutModule->indentCO->setCurrentIndex(indent);
4193                 setIndent(indent);
4194         } else {
4195                 textLayoutModule->skipRB->setChecked(true);
4196                 VSpace::VSpaceKind skip = bp_.getDefSkip().kind();
4197                 textLayoutModule->skipCO->setCurrentIndex(textLayoutModule->skipCO->findData(skip));
4198                 if (skip == VSpace::LENGTH) {
4199                         string const length = bp_.getDefSkip().asLyXCommand();
4200                         lengthToWidgets(textLayoutModule->skipLE,
4201                                 textLayoutModule->skipLengthCO,
4202                                 length, default_unit);
4203                 }
4204                 setSkip(textLayoutModule->skipCO->currentIndex());
4205         }
4206
4207         textLayoutModule->twoColumnCB->setChecked(
4208                 bp_.columns == 2);
4209         textLayoutModule->justCB->setChecked(bp_.justification);
4210
4211         if (!bp_.options.empty()) {
4212                 latexModule->optionsLE->setText(
4213                         toqstr(bp_.options));
4214         } else {
4215                 latexModule->optionsLE->setText(QString());
4216         }
4217
4218         // latex
4219         latexModule->defaultOptionsCB->setChecked(
4220                         bp_.use_default_options);
4221         updateSelectedModules();
4222         selectionManager->updateProvidedModules(
4223                         bp_.baseClass()->providedModules());
4224         selectionManager->updateExcludedModules(
4225                         bp_.baseClass()->excludedModules());
4226
4227         if (!documentClass().options().empty()) {
4228                 latexModule->defaultOptionsLE->setText(
4229                         toqstr(documentClass().options()));
4230         } else {
4231                 latexModule->defaultOptionsLE->setText(
4232                         toqstr(_("[No options predefined]")));
4233         }
4234
4235         latexModule->defaultOptionsLE->setEnabled(
4236                 bp_.use_default_options
4237                 && !documentClass().options().empty());
4238
4239         latexModule->defaultOptionsCB->setEnabled(
4240                 !documentClass().options().empty());
4241
4242         if (!bp_.master.empty()) {
4243                 latexModule->childDocGB->setChecked(true);
4244                 latexModule->childDocLE->setText(
4245                         toqstr(bp_.master));
4246         } else {
4247                 latexModule->childDocLE->setText(QString());
4248                 latexModule->childDocGB->setChecked(false);
4249         }
4250
4251         // Master/Child
4252         if (!bufferview() || !buffer().hasChildren()) {
4253                 masterChildModule->childrenTW->clear();
4254                 includeonlys_.clear();
4255                 docPS->showPanel("Child Documents", false);
4256                 if (docPS->isCurrentPanel("Child Documents"))
4257                         docPS->setCurrentPanel("Document Class");
4258         } else {
4259                 docPS->showPanel("Child Documents", true);
4260                 masterChildModule->setEnabled(true);
4261                 includeonlys_ = bp_.getIncludedChildren();
4262                 updateIncludeonlys();
4263                 updateIncludeonlyDisplay();
4264         }
4265         switch (bp_.maintain_unincluded_children) {
4266         case BufferParams::CM_None:
4267                 masterChildModule->maintainCRNoneRB->setChecked(true);
4268                 break;
4269         case BufferParams::CM_Mostly:
4270                 masterChildModule->maintainCRMostlyRB->setChecked(true);
4271                 break;
4272         case BufferParams::CM_Strict:
4273         default:
4274                 masterChildModule->maintainCRStrictRB->setChecked(true);
4275                 break;
4276         }
4277
4278         // Float Settings
4279         floatModule->setPlacement(bp_.float_placement);
4280         floatModule->setAlignment(bp_.float_alignment);
4281
4282         // ListingsSettings
4283         // break listings_params to multiple lines
4284         string lstparams =
4285                 InsetListingsParams(bp_.listings_params).separatedParams();
4286         listingsModule->listingsED->setPlainText(toqstr(lstparams));
4287         int nn = findToken(lst_packages, bp_.use_minted ? "Minted" : "Listings");
4288         if (nn >= 0)
4289                 listingsModule->packageCO->setCurrentIndex(nn);
4290
4291         // Fonts
4292         // some languages only work with Polyglossia (which requires non-TeX fonts)
4293         Language const * lang = lyx::languages.getLanguage(
4294                 fromqstr(langModule->languageCO->itemData(
4295                         langModule->languageCO->currentIndex()).toString()));
4296         bool const need_fontspec =
4297                 lang->babel().empty() && !lang->polyglossia().empty()
4298                 && lang->required() != "CJK" && lang->required() != "japanese";
4299         bool const os_fonts_available =
4300                 bp_.baseClass()->outputType() == lyx::LATEX
4301                 && LaTeXFeatures::isAvailable("fontspec");
4302         fontModule->osFontsCB->setEnabled(os_fonts_available && !need_fontspec);
4303         fontModule->osFontsCB->setChecked(
4304                 (os_fonts_available && bp_.useNonTeXFonts) || need_fontspec);
4305         updateFontsize(documentClass().opt_fontsize(),
4306                         bp_.fontsize);
4307
4308         QString font = toqstr(bp_.fontsRoman());
4309         int rpos = fontModule->fontsRomanCO->findData(font);
4310         if (rpos == -1) {
4311                 rpos = fontModule->fontsRomanCO->count();
4312                 fontModule->fontsRomanCO->addItem(font + qt_(" (not installed)"), font);
4313         }
4314         fontModule->fontsRomanCO->setCurrentIndex(rpos);
4315         fontModule->font_roman = toqstr(bp_.fonts_roman[!bp_.useNonTeXFonts]);
4316
4317         font = toqstr(bp_.fontsSans());
4318         int spos = fontModule->fontsSansCO->findData(font);
4319         if (spos == -1) {
4320                 spos = fontModule->fontsSansCO->count();
4321                 fontModule->fontsSansCO->addItem(font + qt_(" (not installed)"), font);
4322         }
4323         fontModule->fontsSansCO->setCurrentIndex(spos);
4324         fontModule->font_sans = toqstr(bp_.fonts_sans[!bp_.useNonTeXFonts]);
4325
4326         font = toqstr(bp_.fontsTypewriter());
4327         int tpos = fontModule->fontsTypewriterCO->findData(font);
4328         if (tpos == -1) {
4329                 tpos = fontModule->fontsTypewriterCO->count();
4330                 fontModule->fontsTypewriterCO->addItem(font + qt_(" (not installed)"), font);
4331         }
4332         fontModule->fontsTypewriterCO->setCurrentIndex(tpos);
4333         fontModule->font_typewriter = toqstr(bp_.fonts_typewriter[!bp_.useNonTeXFonts]);
4334
4335         font = toqstr(bp_.fontsMath());
4336         int mpos = fontModule->fontsMathCO->findData(font);
4337         if (mpos == -1) {
4338                 mpos = fontModule->fontsMathCO->count();
4339                 fontModule->fontsMathCO->addItem(font + qt_(" (not installed)"), font);
4340         }
4341         fontModule->fontsMathCO->setCurrentIndex(mpos);
4342         fontModule->font_math = toqstr(bp_.fonts_math[!bp_.useNonTeXFonts]);
4343
4344         if (bp_.useNonTeXFonts && os_fonts_available) {
4345                 fontModule->fontencLA->setEnabled(false);
4346                 fontModule->fontencCO->setEnabled(false);
4347                 fontModule->fontencLE->setEnabled(false);
4348         } else {
4349                 fontModule->fontencLA->setEnabled(true);
4350                 fontModule->fontencCO->setEnabled(true);
4351                 fontModule->fontencLE->setEnabled(true);
4352                 romanChanged(rpos);
4353                 sansChanged(spos);
4354                 ttChanged(tpos);
4355         }
4356
4357         if (!bp_.fonts_cjk.empty())
4358                 fontModule->cjkFontLE->setText(
4359                         toqstr(bp_.fonts_cjk));
4360         else
4361                 fontModule->cjkFontLE->setText(QString());
4362
4363         fontModule->microtypeCB->setChecked(bp_.use_microtype);
4364         fontModule->dashesCB->setChecked(!bp_.use_dash_ligatures);
4365
4366         fontModule->fontScCB->setChecked(bp_.fonts_expert_sc);
4367         fontModule->fontOsfCB->setChecked(bp_.fonts_roman_osf);
4368         fontModule->fontSansOsfCB->setChecked(bp_.fonts_sans_osf);
4369         fontModule->fontTypewriterOsfCB->setChecked(bp_.fonts_typewriter_osf);
4370         fontModule->scaleSansSB->setValue(bp_.fontsSansScale());
4371         fontModule->font_sf_scale = bp_.fonts_sans_scale[!bp_.useNonTeXFonts];
4372         fontModule->scaleTypewriterSB->setValue(bp_.fontsTypewriterScale());
4373         fontModule->font_tt_scale = bp_.fonts_typewriter_scale[!bp_.useNonTeXFonts];
4374         if (!bp_.font_roman_opts.empty())
4375                 fontModule->fontspecRomanLE->setText(
4376                         toqstr(bp_.font_roman_opts));
4377         else
4378                 fontModule->fontspecRomanLE->setText(QString());
4379         if (!bp_.font_sans_opts.empty())
4380                 fontModule->fontspecSansLE->setText(
4381                         toqstr(bp_.font_sans_opts));
4382         else
4383                 fontModule->fontspecSansLE->setText(QString());
4384         if (!bp_.font_typewriter_opts.empty())
4385                 fontModule->fontspecTypewriterLE->setText(
4386                         toqstr(bp_.font_typewriter_opts));
4387         else
4388                 fontModule->fontspecTypewriterLE->setText(QString());
4389
4390         nn = findToken(GuiDocument::fontfamilies, bp_.fonts_default_family);
4391         if (nn >= 0)
4392                 fontModule->fontsDefaultCO->setCurrentIndex(nn);
4393
4394         if (bp_.fontenc == "auto" || bp_.fontenc == "default") {
4395                 fontModule->fontencCO->setCurrentIndex(
4396                         fontModule->fontencCO->findData(toqstr(bp_.fontenc)));
4397                 fontModule->fontencLE->setEnabled(false);
4398         } else {
4399                 fontModule->fontencCO->setCurrentIndex(
4400                                         fontModule->fontencCO->findData("custom"));
4401                 fontModule->fontencLE->setText(toqstr(bp_.fontenc));
4402         }
4403
4404         // LaTeX input encoding
4405         // Set after fonts because non-tex fonts override "\inputencoding".
4406         inputencodingToDialog();
4407
4408         // Formats
4409         // This must be set _after_ fonts since updateDefaultFormat()
4410         // checks osFontsCB settings.
4411         // update combobox with formats
4412         updateDefaultFormat();
4413         int index = outputModule->defaultFormatCO->findData(toqstr(
4414                 bp_.default_output_format));
4415         // set to default if format is not found
4416         if (index == -1)
4417                 index = 0;
4418         outputModule->defaultFormatCO->setCurrentIndex(index);
4419
4420         outputModule->shellescapeCB->setChecked(bp_.shell_escape);
4421         outputModule->outputsyncCB->setChecked(bp_.output_sync);
4422         outputModule->synccustomCB->setEditText(toqstr(bp_.output_sync_macro));
4423         outputModule->synccustomCB->setEnabled(bp_.output_sync);
4424         outputModule->synccustomLA->setEnabled(bp_.output_sync);
4425
4426         outputModule->mathimgSB->setValue(bp_.html_math_img_scale);
4427         outputModule->mathoutCB->setCurrentIndex(bp_.html_math_output);
4428         outputModule->strictCB->setChecked(bp_.html_be_strict);
4429         outputModule->cssCB->setChecked(bp_.html_css_as_file);
4430
4431         outputModule->tableoutCB->setCurrentIndex(bp_.docbook_table_output);
4432         outputModule->mathmlprefixCB->setCurrentIndex(bp_.docbook_mathml_prefix);
4433
4434         outputModule->saveTransientPropertiesCB
4435                 ->setChecked(bp_.save_transient_properties);
4436         outputModule->postponeFragileCB
4437                 ->setChecked(bp_.postpone_fragile_content);
4438
4439         // paper
4440         bool const extern_geometry =
4441                 documentClass().provides("geometry");
4442         int const psize = bp_.papersize;
4443         pageLayoutModule->papersizeCO->setCurrentIndex(psize);
4444         setCustomPapersize(!extern_geometry && psize == 1);
4445         pageLayoutModule->papersizeCO->setEnabled(!extern_geometry);
4446
4447         bool const landscape =
4448                 bp_.orientation == ORIENTATION_LANDSCAPE;
4449         pageLayoutModule->landscapeRB->setChecked(landscape);
4450         pageLayoutModule->portraitRB->setChecked(!landscape);
4451         pageLayoutModule->landscapeRB->setEnabled(!extern_geometry);
4452         pageLayoutModule->portraitRB->setEnabled(!extern_geometry);
4453
4454         pageLayoutModule->facingPagesCB->setChecked(
4455                 bp_.sides == TwoSides);
4456
4457         lengthToWidgets(pageLayoutModule->paperwidthLE,
4458                 pageLayoutModule->paperwidthUnitCO, bp_.paperwidth, default_unit);
4459         lengthToWidgets(pageLayoutModule->paperheightLE,
4460                 pageLayoutModule->paperheightUnitCO, bp_.paperheight, default_unit);
4461
4462         // margins
4463         Ui::MarginsUi * m = marginsModule;
4464
4465         setMargins();
4466
4467         lengthToWidgets(m->topLE, m->topUnit,
4468                 bp_.topmargin, default_unit);
4469
4470         lengthToWidgets(m->bottomLE, m->bottomUnit,
4471                 bp_.bottommargin, default_unit);
4472
4473         lengthToWidgets(m->innerLE, m->innerUnit,
4474                 bp_.leftmargin, default_unit);
4475
4476         lengthToWidgets(m->outerLE, m->outerUnit,
4477                 bp_.rightmargin, default_unit);
4478
4479         lengthToWidgets(m->headheightLE, m->headheightUnit,
4480                 bp_.headheight, default_unit);
4481
4482         lengthToWidgets(m->headsepLE, m->headsepUnit,
4483                 bp_.headsep, default_unit);
4484
4485         lengthToWidgets(m->footskipLE, m->footskipUnit,
4486                 bp_.footskip, default_unit);
4487
4488         lengthToWidgets(m->columnsepLE, m->columnsepUnit,
4489                 bp_.columnsep, default_unit);
4490
4491         // branches
4492         updateUnknownBranches();
4493         branchesModule->update(bp_);
4494
4495         // PDF support
4496         PDFOptions const & pdf = bp_.pdfoptions();
4497         pdfSupportModule->use_hyperrefGB->setChecked(pdf.use_hyperref);
4498         if (bp_.documentClass().provides("hyperref"))
4499                 pdfSupportModule->use_hyperrefGB->setTitle(qt_("C&ustomize Hyperref Options"));
4500         else
4501                 pdfSupportModule->use_hyperrefGB->setTitle(qt_("&Use Hyperref Support"));
4502         pdfSupportModule->titleLE->setText(toqstr(pdf.title));
4503         pdfSupportModule->authorLE->setText(toqstr(pdf.author));
4504         pdfSupportModule->subjectLE->setText(toqstr(pdf.subject));
4505         pdfSupportModule->keywordsLE->setText(toqstr(pdf.keywords));
4506
4507         pdfSupportModule->bookmarksGB->setChecked(pdf.bookmarks);
4508         pdfSupportModule->bookmarksnumberedCB->setChecked(pdf.bookmarksnumbered);
4509         pdfSupportModule->bookmarksopenGB->setChecked(pdf.bookmarksopen);
4510
4511         pdfSupportModule->bookmarksopenlevelSB->setValue(pdf.bookmarksopenlevel);
4512         pdfSupportModule->bookmarksopenlevelSB->setEnabled(pdf.bookmarksopen);
4513         pdfSupportModule->bookmarksopenlevelLA->setEnabled(pdf.bookmarksopen);
4514
4515         pdfSupportModule->breaklinksCB->setChecked(pdf.breaklinks);
4516         pdfSupportModule->pdfborderCB->setChecked(pdf.pdfborder);
4517         pdfSupportModule->pdfusetitleCB->setChecked(pdf.pdfusetitle);
4518         pdfSupportModule->colorlinksCB->setChecked(pdf.colorlinks);
4519
4520         nn = findToken(backref_opts, pdf.backref);
4521         if (nn >= 0)
4522                 pdfSupportModule->backrefCO->setCurrentIndex(nn);
4523
4524         pdfSupportModule->fullscreenCB->setChecked
4525                 (pdf.pagemode == pdf.pagemode_fullscreen);
4526
4527         pdfSupportModule->optionsLE->setText(
4528                 toqstr(pdf.quoted_options));
4529
4530         // change tracking
4531         changesModule->trackChangesCB->setChecked(bp_.track_changes);
4532         changesModule->outputChangesCB->setChecked(bp_.output_changes);
4533         changesModule->changeBarsCB->setChecked(bp_.change_bars);
4534         changesModule->changeBarsCB->setEnabled(bp_.output_changes);
4535
4536         // Make sure that the bc is in the INITIAL state
4537         if (bc().policy().buttonStatus(ButtonPolicy::RESTORE))
4538                 bc().restore();
4539
4540         // clear changed branches cache
4541         changedBranches_.clear();
4542
4543         // re-initiate module filter
4544         if (!filter_->text().isEmpty())
4545                 moduleFilterPressed();
4546
4547         // reset trackers
4548         nonModuleChanged_ = false;
4549         shellescapeChanged_ = false;
4550 }
4551
4552
4553 void GuiDocument::saveDocDefault()
4554 {
4555         // we have to apply the params first
4556         applyView();
4557         saveAsDefault();
4558 }
4559
4560
4561 void GuiDocument::updateAvailableModules()
4562 {
4563         modules_av_model_.clear();
4564         list<modInfoStruct> modInfoList = getModuleInfo();
4565         // Sort names according to the locale
4566         modInfoList.sort([](modInfoStruct const & a, modInfoStruct const & b) {
4567                         return 0 < b.name.localeAwareCompare(a.name);
4568                 });
4569         QIcon user_icon(getPixmap("images/", "lyxfiles-user", "svgz,png"));
4570         QIcon system_icon(getPixmap("images/", "lyxfiles-system", "svgz,png"));
4571         int i = 0;
4572         QFont catfont;
4573         catfont.setBold(true);
4574         QBrush unavbrush;
4575         unavbrush.setColor(Qt::gray);
4576         for (modInfoStruct const & m : modInfoList) {
4577                 QStandardItem * item = new QStandardItem();
4578                 QStandardItem * catItem;
4579                 QString const catname = m.category;
4580                 QList<QStandardItem *> fcats = modules_av_model_.findItems(catname, Qt::MatchExactly);
4581                 if (!fcats.empty())
4582                         catItem = fcats.first();
4583                 else {
4584                         catItem = new QStandardItem();
4585                         catItem->setText(catname);
4586                         catItem->setFont(catfont);
4587                         modules_av_model_.insertRow(i, catItem);
4588                         ++i;
4589                 }
4590                 item->setEditable(false);
4591                 catItem->setEditable(false);
4592                 item->setData(m.name, Qt::DisplayRole);
4593                 if (m.missingreqs)
4594                         item->setForeground(unavbrush);
4595                 item->setData(toqstr(m.id), Qt::UserRole);
4596                 item->setData(m.description, Qt::ToolTipRole);
4597                 if (m.local)
4598                         item->setIcon(user_icon);
4599                 else
4600                         item->setIcon(system_icon);
4601                 catItem->appendRow(item);
4602         }
4603         modules_av_model_.sort(0);
4604 }
4605
4606
4607 void GuiDocument::updateSelectedModules()
4608 {
4609         modules_sel_model_.clear();
4610         list<modInfoStruct> const selModList = getSelectedModules();
4611         int i = 0;
4612         for (modInfoStruct const & m : selModList) {
4613                 modules_sel_model_.insertRow(i, m.name, m.id, m.description);
4614                 ++i;
4615         }
4616 }
4617
4618
4619 void GuiDocument::updateIncludeonlyDisplay()
4620 {
4621         if (includeonlys_.empty()) {
4622                 masterChildModule->includeallRB->setChecked(true);
4623                 masterChildModule->childrenTW->setEnabled(false);
4624                 masterChildModule->maintainGB->setEnabled(false);
4625         } else {
4626                 masterChildModule->includeonlyRB->setChecked(true);
4627                 masterChildModule->childrenTW->setEnabled(true);
4628                 masterChildModule->maintainGB->setEnabled(true);
4629         }
4630 }
4631
4632
4633 void GuiDocument::updateIncludeonlys()
4634 {
4635         masterChildModule->childrenTW->clear();
4636         QString const no = qt_("No");
4637         QString const yes = qt_("Yes");
4638
4639         ListOfBuffers children = buffer().getChildren();
4640         ListOfBuffers::const_iterator it  = children.begin();
4641         ListOfBuffers::const_iterator end = children.end();
4642         bool has_unincluded = false;
4643         bool all_unincluded = true;
4644         for (; it != end; ++it) {
4645                 QTreeWidgetItem * item = new QTreeWidgetItem(masterChildModule->childrenTW);
4646                 // FIXME Unicode
4647                 string const name =
4648                         to_utf8(makeRelPath(from_utf8((*it)->fileName().absFileName()),
4649                                                         from_utf8(buffer().filePath())));
4650                 item->setText(0, toqstr(name));
4651                 item->setText(1, isChildIncluded(name) ? yes : no);
4652                 if (!isChildIncluded(name))
4653                         has_unincluded = true;
4654                 else
4655                         all_unincluded = false;
4656         }
4657         // Both if all children are included and if none is included
4658         // is equal to "include all" (i.e., omit \includeonly).
4659         if (!has_unincluded || all_unincluded)
4660                 includeonlys_.clear();
4661 }
4662
4663
4664 bool GuiDocument::isBiblatex() const
4665 {
4666         QString const engine =
4667                 biblioModule->citeEngineCO->itemData(
4668                                 biblioModule->citeEngineCO->currentIndex()).toString();
4669
4670         // this can happen if the cite engine is unknown, which can happen
4671         // if one is using a file that came from someone else, etc. in that
4672         // case, we crash if we proceed.
4673         if (engine.isEmpty())
4674             return false;
4675
4676         return theCiteEnginesList[fromqstr(engine)]->getCiteFramework() == "biblatex";
4677 }
4678
4679
4680 void GuiDocument::updateDefaultBiblio(string const & style,
4681                                       string const & which)
4682 {
4683         QString const bibstyle = toqstr(style);
4684         biblioModule->defaultBiblioCO->clear();
4685
4686         int item_nr = -1;
4687
4688         if (isBiblatex()) {
4689                 if (which != "cbx") {
4690                         // First the bbx styles
4691                         biblioModule->biblatexBbxCO->clear();
4692                         QStringList str = texFileList("bbxFiles.lst");
4693                         // test whether we have a valid list, otherwise run rescan
4694                         if (str.isEmpty()) {
4695                                 rescanTexStyles("bbx");
4696                                 str = texFileList("bbxFiles.lst");
4697                         }
4698                         for (int i = 0; i != str.size(); ++i)
4699                                 str[i] = onlyFileName(str[i]);
4700                         // sort on filename only (no path)
4701                         str.sort();
4702
4703                         for (int i = 0; i != str.count(); ++i) {
4704                                 QString item = changeExtension(str[i], "");
4705                                 if (item == bibstyle)
4706                                         item_nr = i;
4707                                 biblioModule->biblatexBbxCO->addItem(item);
4708                         }
4709
4710                         if (item_nr == -1 && !bibstyle.isEmpty()) {
4711                                 biblioModule->biblatexBbxCO->addItem(bibstyle);
4712                                 item_nr = biblioModule->biblatexBbxCO->count() - 1;
4713                         }
4714
4715                         if (item_nr != -1)
4716                                 biblioModule->biblatexBbxCO->setCurrentIndex(item_nr);
4717                         else
4718                                 biblioModule->biblatexBbxCO->clearEditText();
4719                 }
4720
4721                 if (which != "bbx") {
4722                         // now the cbx styles
4723                         biblioModule->biblatexCbxCO->clear();
4724                         QStringList str = texFileList("cbxFiles.lst");
4725                         // test whether we have a valid list, otherwise run rescan
4726                         if (str.isEmpty()) {
4727                                 rescanTexStyles("cbx");
4728                                 str = texFileList("cbxFiles.lst");
4729                         }
4730                         for (int i = 0; i != str.size(); ++i)
4731                                 str[i] = onlyFileName(str[i]);
4732                         // sort on filename only (no path)
4733                         str.sort();
4734
4735                         for (int i = 0; i != str.count(); ++i) {
4736                                 QString item = changeExtension(str[i], "");
4737                                 if (item == bibstyle)
4738                                         item_nr = i;
4739                                 biblioModule->biblatexCbxCO->addItem(item);
4740                         }
4741
4742                         if (item_nr == -1 && !bibstyle.isEmpty()) {
4743                                 biblioModule->biblatexCbxCO->addItem(bibstyle);
4744                                 item_nr = biblioModule->biblatexCbxCO->count() - 1;
4745                         }
4746
4747                         if (item_nr != -1)
4748                                 biblioModule->biblatexCbxCO->setCurrentIndex(item_nr);
4749                         else
4750                                 biblioModule->biblatexCbxCO->clearEditText();
4751                 }
4752         } else {// BibTeX
4753                 biblioModule->biblatexBbxCO->clear();
4754                 biblioModule->biblatexCbxCO->clear();
4755                 QStringList str = texFileList("bstFiles.lst");
4756                 // test whether we have a valid list, otherwise run rescan
4757                 if (str.isEmpty()) {
4758                         rescanTexStyles("bst");
4759                         str = texFileList("bstFiles.lst");
4760                 }
4761                 for (int i = 0; i != str.size(); ++i)
4762                         str[i] = onlyFileName(str[i]);
4763                 // sort on filename only (no path)
4764                 str.sort();
4765
4766                 for (int i = 0; i != str.count(); ++i) {
4767                         QString item = changeExtension(str[i], "");
4768                         if (item == bibstyle)
4769                                 item_nr = i;
4770                         biblioModule->defaultBiblioCO->addItem(item);
4771                 }
4772
4773                 if (item_nr == -1 && !bibstyle.isEmpty()) {
4774                         biblioModule->defaultBiblioCO->addItem(bibstyle);
4775                         item_nr = biblioModule->defaultBiblioCO->count() - 1;
4776                 }
4777
4778                 if (item_nr != -1)
4779                         biblioModule->defaultBiblioCO->setCurrentIndex(item_nr);
4780                 else
4781                         biblioModule->defaultBiblioCO->clearEditText();
4782         }
4783
4784         updateResetDefaultBiblio();
4785 }
4786
4787
4788 void GuiDocument::updateResetDefaultBiblio()
4789 {
4790         QString const engine =
4791                 biblioModule->citeEngineCO->itemData(
4792                                 biblioModule->citeEngineCO->currentIndex()).toString();
4793         CiteEngineType const cet =
4794                 CiteEngineType(biblioModule->citeStyleCO->itemData(
4795                                                           biblioModule->citeStyleCO->currentIndex()).toInt());
4796
4797         string const defbib = theCiteEnginesList[fromqstr(engine)]->getDefaultBiblio(cet);
4798         if (isBiblatex()) {
4799                 QString const bbx = biblioModule->biblatexBbxCO->currentText();
4800                 QString const cbx = biblioModule->biblatexCbxCO->currentText();
4801                 biblioModule->resetCbxPB->setEnabled(defbib != fromqstr(cbx));
4802                 biblioModule->resetBbxPB->setEnabled(defbib != fromqstr(bbx));
4803                 biblioModule->matchBbxPB->setEnabled(bbx != cbx && !cbx.isEmpty()
4804                         && biblioModule->biblatexBbxCO->findText(cbx) != -1);
4805         } else
4806                 biblioModule->resetDefaultBiblioPB->setEnabled(
4807                         defbib != fromqstr(biblioModule->defaultBiblioCO->currentText()));
4808 }
4809
4810
4811 void GuiDocument::matchBiblatexStyles()
4812 {
4813         updateDefaultBiblio(fromqstr(biblioModule->biblatexCbxCO->currentText()), "bbx");
4814         biblioChanged();
4815 }
4816
4817
4818 void GuiDocument::updateContents()
4819 {
4820         // Nothing to do here as the document settings is not cursor dependent.
4821         return;
4822 }
4823
4824
4825 void GuiDocument::useClassDefaults()
4826 {
4827         if (buttonBox->button(QDialogButtonBox::Apply)->isEnabled()) {
4828                 int const ret = Alert::prompt(_("Unapplied changes"),
4829                                 _("Some changes in the dialog were not yet applied.\n"
4830                                   "If you do not apply now, they will be lost after this action."),
4831                                 1, 1, _("&Apply"), _("&Dismiss"));
4832                 if (ret == 0)
4833                         applyView();
4834         }
4835
4836         int idx = latexModule->classCO->currentIndex();
4837         string const classname = fromqstr(latexModule->classCO->getData(idx));
4838         if (!bp_.setBaseClass(classname, buffer().layoutPos())) {
4839                 Alert::error(_("Error"), _("Unable to set document class."));
4840                 return;
4841         }
4842         bp_.useClassDefaults();
4843         paramsToDialog();
4844         changed();
4845 }
4846
4847
4848 void GuiDocument::setLayoutComboByIDString(string const & idString)
4849 {
4850         if (!latexModule->classCO->set(toqstr(idString)))
4851                 Alert::warning(_("Can't set layout!"),
4852                         bformat(_("Unable to set layout for ID: %1$s"), from_utf8(idString)));
4853 }
4854
4855
4856 bool GuiDocument::isValid()
4857 {
4858         return
4859                 validateListingsParameters().isEmpty() &&
4860                 localLayout->isValid() &&
4861                 !localLayout->editing() &&
4862                 !preambleModule->editing() &&
4863                 (
4864                         // if we're asking for skips between paragraphs
4865                         !textLayoutModule->skipRB->isChecked() ||
4866                         // then either we haven't chosen custom
4867                         textLayoutModule->skipCO->currentIndex() != 3 ||
4868                         // or else a length has been given
4869                         !textLayoutModule->skipLE->text().isEmpty()
4870                 ) &&
4871                 (
4872                         // if we're asking for indentation
4873                         !textLayoutModule->indentRB->isChecked() ||
4874                         // then either we haven't chosen custom
4875                         textLayoutModule->indentCO->currentIndex() != 1 ||
4876                         // or else a length has been given
4877                         !textLayoutModule->indentLE->text().isEmpty()
4878                 ) &&
4879                 (
4880                         // if we're asking for math indentation
4881                         !mathsModule->MathIndentCB->isChecked() ||
4882                         // then either we haven't chosen custom
4883                         mathsModule->MathIndentCO->currentIndex() != 1 ||
4884                         // or else a length has been given
4885                         !mathsModule->MathIndentLE->text().isEmpty()
4886                 );
4887 }
4888
4889
4890 char const * const GuiDocument::fontfamilies[5] = {
4891         "default", "rmdefault", "sfdefault", "ttdefault", ""
4892 };
4893
4894
4895 char const * GuiDocument::fontfamilies_gui[5] = {
4896         N_("Default"), N_("Roman"), N_("Sans Serif"), N_("Typewriter"), ""
4897 };
4898
4899
4900 bool GuiDocument::initialiseParams(string const &)
4901 {
4902         BufferView const * view = bufferview();
4903         if (!view) {
4904                 bp_ = BufferParams();
4905                 paramsToDialog();
4906                 return true;
4907         }
4908         bp_ = view->buffer().params();
4909         loadModuleInfo();
4910         updateAvailableModules();
4911         //FIXME It'd be nice to make sure here that the selected
4912         //modules are consistent: That required modules are actually
4913         //selected, and that we don't have conflicts. If so, we could
4914         //at least pop up a warning.
4915         paramsToDialog();
4916         return true;
4917 }
4918
4919
4920 void GuiDocument::clearParams()
4921 {
4922         bp_ = BufferParams();
4923 }
4924
4925
4926 BufferId GuiDocument::id() const
4927 {
4928         BufferView const * const view = bufferview();
4929         return view? &view->buffer() : nullptr;
4930 }
4931
4932
4933 list<GuiDocument::modInfoStruct> const & GuiDocument::getModuleInfo()
4934 {
4935         return moduleNames_;
4936 }
4937
4938
4939 list<GuiDocument::modInfoStruct> const
4940 GuiDocument::makeModuleInfo(LayoutModuleList const & mods)
4941 {
4942         list<modInfoStruct> mInfo;
4943         for (string const & name : mods) {
4944                 modInfoStruct m;
4945                 LyXModule const * const mod = theModuleList[name];
4946                 if (mod)
4947                         m = modInfo(*mod);
4948                 else {
4949                         m.id = name;
4950                         m.name = toqstr(name + " (") + qt_("Not Found") + toqstr(")");
4951                         m.local = false;
4952                         m.missingreqs = true;
4953                 }
4954                 mInfo.push_back(m);
4955         }
4956         return mInfo;
4957 }
4958
4959
4960 list<GuiDocument::modInfoStruct> const GuiDocument::getSelectedModules()
4961 {
4962         return makeModuleInfo(params().getModules());
4963 }
4964
4965
4966 list<GuiDocument::modInfoStruct> const GuiDocument::getProvidedModules()
4967 {
4968         return makeModuleInfo(params().baseClass()->providedModules());
4969 }
4970
4971
4972 DocumentClass const & GuiDocument::documentClass() const
4973 {
4974         return bp_.documentClass();
4975 }
4976
4977
4978 static void dispatch_bufferparams(Dialog const & dialog,
4979         BufferParams const & bp, FuncCode lfun, Buffer const * buf)
4980 {
4981         ostringstream ss;
4982         ss << "\\begin_header\n";
4983         bp.writeFile(ss, buf);
4984         ss << "\\end_header\n";
4985         dialog.dispatch(FuncRequest(lfun, ss.str()));
4986 }
4987
4988
4989 void GuiDocument::dispatchParams()
4990 {
4991         // We need a non-const buffer object.
4992         Buffer & buf = const_cast<BufferView *>(bufferview())->buffer();
4993         // There may be several undo records; group them (bug #8998)
4994         // This handles undo groups automagically
4995         UndoGroupHelper ugh(&buf);
4996
4997         // This must come first so that a language change is correctly noticed
4998         setLanguage();
4999
5000         // We need to load the master before we formally update the params,
5001         // since otherwise we run updateBuffer, etc, before the child's master
5002         // has been set.
5003         if (!params().master.empty()) {
5004                 FileName const master_file = support::makeAbsPath(params().master,
5005                            support::onlyPath(buffer().absFileName()));
5006                 if (isLyXFileName(master_file.absFileName())) {
5007                         Buffer * master = checkAndLoadLyXFile(master_file, true);
5008                         if (master) {
5009                                 if (master->isChild(const_cast<Buffer *>(&buffer())))
5010                                         const_cast<Buffer &>(buffer()).setParent(master);
5011                                 else
5012                                         Alert::warning(_("Assigned master does not include this file"),
5013                                                 bformat(_("You must include this file in the document\n"
5014                                                           "'%1$s' in order to use the master document\n"
5015                                                           "feature."), from_utf8(params().master)));
5016                         } else
5017                                 Alert::warning(_("Could not load master"),
5018                                                 bformat(_("The master document '%1$s'\n"
5019                                                            "could not be loaded."),
5020                                                            from_utf8(params().master)));
5021                 }
5022         }
5023
5024         // Apply the BufferParams. Note that this will set the base class
5025         // and then update the buffer's layout.
5026         dispatch_bufferparams(*this, params(), LFUN_BUFFER_PARAMS_APPLY, &buffer());
5027
5028         // Generate the colours requested by each new branch.
5029         BranchList & branchlist = params().branchlist();
5030         if (!branchlist.empty()) {
5031                 BranchList::const_iterator it = branchlist.begin();
5032                 BranchList::const_iterator const end = branchlist.end();
5033                 for (; it != end; ++it) {
5034                         docstring const & current_branch = it->branch();
5035                         Branch const * branch = branchlist.find(current_branch);
5036                         string const bcolor = branch->color();
5037                         RGBColor rgbcol;
5038                         if (bcolor.size() == 7 && bcolor[0] == '#')
5039                                 rgbcol = lyx::rgbFromHexName(bcolor);
5040                         else
5041                                 guiApp->getRgbColor(lcolor.getFromLyXName(bcolor), rgbcol);
5042                         string const x11hexname = X11hexname(rgbcol);
5043                         // display the new color
5044                         docstring const str = current_branch + ' ' + from_ascii(x11hexname);
5045                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
5046                 }
5047         }
5048         // rename branches in the document
5049         executeBranchRenaming();
5050         // and clear changed branches cache
5051         changedBranches_.clear();
5052
5053         // Generate the colours requested by indices.
5054         IndicesList & indiceslist = params().indiceslist();
5055         if (!indiceslist.empty()) {
5056                 IndicesList::const_iterator it = indiceslist.begin();
5057                 IndicesList::const_iterator const end = indiceslist.end();
5058                 for (; it != end; ++it) {
5059                         docstring const & current_index = it->shortcut();
5060                         Index const * index = indiceslist.findShortcut(current_index);
5061                         string const x11hexname = X11hexname(index->color());
5062                         // display the new color
5063                         docstring const str = current_index + ' ' + from_ascii(x11hexname);
5064                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
5065                 }
5066         }
5067         // FIXME LFUN
5068         // If we used an LFUN, we would not need these two lines:
5069         BufferView * bv = const_cast<BufferView *>(bufferview());
5070         bv->processUpdateFlags(Update::Force | Update::FitCursor);
5071 }
5072
5073
5074 void GuiDocument::setLanguage() const
5075 {
5076         Language const * const newL = bp_.language;
5077         if (buffer().params().language == newL)
5078                 return;
5079
5080         string const & lang_name = newL->lang();
5081         dispatch(FuncRequest(LFUN_BUFFER_LANGUAGE, lang_name));
5082 }
5083
5084
5085 void GuiDocument::saveAsDefault() const
5086 {
5087         dispatch_bufferparams(*this, params(), LFUN_BUFFER_SAVE_AS_DEFAULT, &buffer());
5088 }
5089
5090
5091 bool GuiDocument::providesOSF(QString const & font) const
5092 {
5093         if (fontModule->osFontsCB->isChecked())
5094                 // FIXME: we should check if the fonts really
5095                 // have OSF support. But how?
5096                 return true;
5097         return theLaTeXFonts().getLaTeXFont(
5098                                 qstring_to_ucs4(font)).providesOSF(ot1(),
5099                                                                    completeFontset(),
5100                                                                    noMathFont());
5101 }
5102
5103
5104 bool GuiDocument::providesSC(QString const & font) const
5105 {
5106         if (fontModule->osFontsCB->isChecked())
5107                 return false;
5108         return theLaTeXFonts().getLaTeXFont(
5109                                 qstring_to_ucs4(font)).providesSC(ot1(),
5110                                                                   completeFontset(),
5111                                                                   noMathFont());
5112 }
5113
5114
5115 bool GuiDocument::providesScale(QString const & font) const
5116 {
5117         if (fontModule->osFontsCB->isChecked())
5118                 return true;
5119         return theLaTeXFonts().getLaTeXFont(
5120                                 qstring_to_ucs4(font)).providesScale(ot1(),
5121                                                                      completeFontset(),
5122                                                                      noMathFont());
5123 }
5124
5125
5126 bool GuiDocument::providesExtraOpts(QString const & font) const
5127 {
5128         if (fontModule->osFontsCB->isChecked())
5129                 return true;
5130         return theLaTeXFonts().getLaTeXFont(
5131                                 qstring_to_ucs4(font)).providesMoreOptions(ot1(),
5132                                                                      completeFontset(),
5133                                                                      noMathFont());
5134 }
5135
5136
5137 bool GuiDocument::providesNoMath(QString const & font) const
5138 {
5139         if (fontModule->osFontsCB->isChecked())
5140                 return false;
5141         return theLaTeXFonts().getLaTeXFont(
5142                                 qstring_to_ucs4(font)).providesNoMath(ot1(),
5143                                                                       completeFontset());
5144 }
5145
5146
5147 bool GuiDocument::hasMonolithicExpertSet(QString const & font) const
5148 {
5149         if (fontModule->osFontsCB->isChecked())
5150                 return false;
5151         return theLaTeXFonts().getLaTeXFont(
5152                                 qstring_to_ucs4(font)).hasMonolithicExpertSet(ot1(),
5153                                                                               completeFontset(),
5154                                                                               noMathFont());
5155 }
5156
5157
5158 //static
5159 GuiDocument::modInfoStruct GuiDocument::modInfo(LyXModule const & mod)
5160 {
5161         // FIXME Unicode: docstrings would be better for these parameters but this
5162         // change requires a lot of others
5163         modInfoStruct m;
5164         m.id = mod.getID();
5165         QString const guiname = toqstr(translateIfPossible(from_utf8(mod.getName())));
5166         m.missingreqs = !isModuleAvailable(mod.getID());
5167         if (m.missingreqs) {
5168                 m.name = QString(qt_("%1 (missing req.)")).arg(guiname);
5169         } else
5170                 m.name = guiname;
5171         m.category = mod.category().empty() ? qt_("Miscellaneous")
5172                                             : toqstr(translateIfPossible(from_utf8(mod.category())));
5173         QString desc = toqstr(translateIfPossible(from_utf8(mod.getDescription())));
5174         // Find the first sentence of the description
5175         QTextBoundaryFinder bf(QTextBoundaryFinder::Sentence, desc);
5176         int pos = bf.toNextBoundary();
5177         if (pos > 0)
5178                 desc.truncate(pos);
5179         m.local = mod.isLocal();
5180         QString const mtype = m.local ? qt_("personal module") : qt_("distributed module");
5181         QString modulename = QString(qt_("<b>Module name:</b> <i>%1</i> (%2)")).arg(toqstr(m.id)).arg(mtype);
5182         // Tooltip is the desc followed by the module name and the type
5183         m.description = QString("%1%2")
5184                 .arg(desc.isEmpty() ? QString() : QString("<p>%1</p>").arg(desc),
5185                      modulename);
5186         if (m.missingreqs)
5187                 m.description += QString("<p>%1</p>").arg(qt_("<b>Note:</b> Some requirements for this module are missing!"));
5188         return m;
5189 }
5190
5191
5192 void GuiDocument::loadModuleInfo()
5193 {
5194         moduleNames_.clear();
5195         for (LyXModule const & mod : theModuleList)
5196                 moduleNames_.push_back(modInfo(mod));
5197 }
5198
5199
5200 void GuiDocument::updateUnknownBranches()
5201 {
5202         if (!bufferview())
5203                 return;
5204         list<docstring> used_branches;
5205         buffer().getUsedBranches(used_branches);
5206         list<docstring>::const_iterator it = used_branches.begin();
5207         QStringList unknown_branches;
5208         for (; it != used_branches.end() ; ++it) {
5209                 if (!buffer().params().branchlist().find(*it))
5210                         unknown_branches.append(toqstr(*it));
5211         }
5212         branchesModule->setUnknownBranches(unknown_branches);
5213 }
5214
5215
5216 void GuiDocument::branchesRename(docstring const & oldname, docstring const & newname)
5217 {
5218         map<docstring, docstring>::iterator it = changedBranches_.begin();
5219         for (; it != changedBranches_.end() ; ++it) {
5220                 if (it->second == oldname) {
5221                         // branch has already been renamed
5222                         it->second = newname;
5223                         return;
5224                 }
5225         }
5226         // store new name
5227         changedBranches_[oldname] = newname;
5228 }
5229
5230
5231 void GuiDocument::executeBranchRenaming() const
5232 {
5233         map<docstring, docstring>::const_iterator it = changedBranches_.begin();
5234         for (; it != changedBranches_.end() ; ++it) {
5235                 docstring const arg = '"' + it->first + '"' + " " + '"' + it->second + '"';
5236                 dispatch(FuncRequest(LFUN_BRANCHES_RENAME, arg));
5237         }
5238 }
5239
5240
5241 void GuiDocument::allPackagesAuto()
5242 {
5243         allPackages(1);
5244 }
5245
5246
5247 void GuiDocument::allPackagesAlways()
5248 {
5249         allPackages(2);
5250 }
5251
5252
5253 void GuiDocument::allPackagesNot()
5254 {
5255         allPackages(3);
5256 }
5257
5258
5259 void GuiDocument::allPackages(int col)
5260 {
5261         for (int row = 0; row < mathsModule->packagesTW->rowCount(); ++row) {
5262                 QRadioButton * rb =
5263                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, col)->layout()->itemAt(0)->widget();
5264                 rb->setChecked(true);
5265         }
5266 }
5267
5268
5269 void GuiDocument::linenoToggled(bool on)
5270 {
5271         numberingModule->linenoLE->setEnabled(on);
5272         numberingModule->linenoLA->setEnabled(on);
5273 }
5274
5275
5276 void GuiDocument::outputChangesToggled(bool on)
5277 {
5278         changesModule->changeBarsCB->setEnabled(on);
5279         change_adaptor();
5280 }
5281
5282 void GuiDocument::setOutputSync(bool on)
5283 {
5284         outputModule->synccustomCB->setEnabled(on);
5285         outputModule->synccustomLA->setEnabled(on);
5286         change_adaptor();
5287 }
5288
5289
5290 } // namespace frontend
5291 } // namespace lyx
5292
5293 #include "moc_GuiDocument.cpp"