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