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