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