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