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