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