]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiDocument.cpp
GuiDocument: Further encoding GUI improvement
[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->noInputencCB, SIGNAL(clicked()),
941                 this, SLOT(change_adaptor()));
942         connect(langModule->quoteStyleCO, SIGNAL(activated(int)),
943                 this, SLOT(change_adaptor()));
944         connect(langModule->languagePackageCO, SIGNAL(activated(int)),
945                 this, SLOT(change_adaptor()));
946         connect(langModule->languagePackageLE, SIGNAL(textChanged(QString)),
947                 this, SLOT(change_adaptor()));
948         connect(langModule->languagePackageCO, SIGNAL(currentIndexChanged(int)),
949                 this, SLOT(languagePackageChanged(int)));
950         connect(langModule->dynamicQuotesCB, SIGNAL(clicked()),
951                 this, SLOT(change_adaptor()));
952
953         langModule->languagePackageLE->setValidator(new NoNewLineValidator(
954                 langModule->languagePackageLE));
955
956         QAbstractItemModel * language_model = guiApp->languageModel();
957         // FIXME: it would be nice if sorting was enabled/disabled via a checkbox.
958         language_model->sort(0);
959         langModule->languageCO->setModel(language_model);
960         langModule->languageCO->setModelColumn(0);
961
962         langModule->encodingCO->addItem(qt_("Unicode (utf8) [default]"), toqstr("utf8"));
963         langModule->encodingCO->addItem(qt_("Traditional (auto-selected)"),
964                                         toqstr("auto-legacy"));
965         langModule->encodingCO->addItem(qt_("ASCII"), toqstr("ascii"));
966         langModule->encodingCO->addItem(qt_("Custom"), toqstr("custom"));
967
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         langModule->noInputencCB->setEnabled(tex_fonts
2262                                              && langModule->encodingCO->currentIndex() < 2);
2263         if (!tex_fonts)
2264                 langModule->noInputencCB->setChecked(false);
2265
2266         fontModule->fontsDefaultCO->setEnabled(tex_fonts);
2267         fontModule->fontsDefaultLA->setEnabled(tex_fonts);
2268         fontModule->cjkFontLE->setEnabled(tex_fonts);
2269         fontModule->cjkFontLA->setEnabled(tex_fonts);
2270
2271         updateFontOptions();
2272
2273         fontModule->fontencLA->setEnabled(tex_fonts);
2274         fontModule->fontencCO->setEnabled(tex_fonts);
2275         if (!tex_fonts)
2276                 fontModule->fontencLE->setEnabled(false);
2277         else
2278                 fontencChanged(fontModule->fontencCO->currentIndex());
2279 }
2280
2281
2282 void GuiDocument::encodingSwitched(int i)
2283 {
2284         langModule->customEncodingCO->setEnabled(
2285                                 !fontModule->osFontsCB->isChecked()
2286                                 && langModule->encodingCO->itemData(i).toString() == "custom");
2287         langModule->noInputencCB->setEnabled(!fontModule->osFontsCB->isChecked()
2288                                              && langModule->encodingCO->currentIndex() < 2);
2289         if (!langModule->noInputencCB->isEnabled())
2290                 langModule->noInputencCB->setChecked(false);
2291
2292 }
2293
2294
2295 void GuiDocument::mathFontChanged(int)
2296 {
2297         updateFontOptions();
2298 }
2299
2300
2301 void GuiDocument::fontOsfToggled(bool state)
2302 {
2303         if (fontModule->osFontsCB->isChecked())
2304                 return;
2305         QString font = fontModule->fontsRomanCO->itemData(
2306                         fontModule->fontsRomanCO->currentIndex()).toString();
2307         if (hasMonolithicExpertSet(font))
2308                 fontModule->fontScCB->setChecked(state);
2309 }
2310
2311
2312 void GuiDocument::fontScToggled(bool state)
2313 {
2314         if (fontModule->osFontsCB->isChecked())
2315                 return;
2316         QString font = fontModule->fontsRomanCO->itemData(
2317                         fontModule->fontsRomanCO->currentIndex()).toString();
2318         if (hasMonolithicExpertSet(font))
2319                 fontModule->fontOsfCB->setChecked(state);
2320 }
2321
2322
2323 void GuiDocument::updateFontOptions()
2324 {
2325         bool const tex_fonts = !fontModule->osFontsCB->isChecked();
2326         QString font;
2327         if (tex_fonts)
2328                 font = fontModule->fontsSansCO->itemData(
2329                                 fontModule->fontsSansCO->currentIndex()).toString();
2330         bool scaleable = providesScale(font);
2331         fontModule->scaleSansSB->setEnabled(scaleable);
2332         fontModule->scaleSansLA->setEnabled(scaleable);
2333         if (tex_fonts)
2334                 font = fontModule->fontsTypewriterCO->itemData(
2335                                 fontModule->fontsTypewriterCO->currentIndex()).toString();
2336         scaleable = providesScale(font);
2337         fontModule->scaleTypewriterSB->setEnabled(scaleable);
2338         fontModule->scaleTypewriterLA->setEnabled(scaleable);
2339         if (tex_fonts)
2340                 font = fontModule->fontsRomanCO->itemData(
2341                                 fontModule->fontsRomanCO->currentIndex()).toString();
2342         fontModule->fontScCB->setEnabled(providesSC(font));
2343         fontModule->fontOsfCB->setEnabled(providesOSF(font));
2344         updateMathFonts(font);
2345 }
2346
2347
2348 void GuiDocument::updateFontsize(string const & items, string const & sel)
2349 {
2350         fontModule->fontsizeCO->clear();
2351         fontModule->fontsizeCO->addItem(qt_("Default"));
2352
2353         for (int n = 0; !token(items,'|',n).empty(); ++n)
2354                 fontModule->fontsizeCO->
2355                         addItem(toqstr(token(items,'|',n)));
2356
2357         for (int n = 0; n < fontModule->fontsizeCO->count(); ++n) {
2358                 if (fromqstr(fontModule->fontsizeCO->itemText(n)) == sel) {
2359                         fontModule->fontsizeCO->setCurrentIndex(n);
2360                         break;
2361                 }
2362         }
2363 }
2364
2365
2366 bool GuiDocument::ot1() const
2367 {
2368         QString const fontenc =
2369                 fontModule->fontencCO->itemData(fontModule->fontencCO->currentIndex()).toString();
2370         int const i = langModule->languageCO->currentIndex();
2371         if (i == -1)
2372                 return false;
2373         QString const langname = langModule->languageCO->itemData(i).toString();
2374         Language const * newlang = lyx::languages.getLanguage(fromqstr(langname));
2375         return (fontenc == "default"
2376                 || (fontenc == "auto" && newlang->fontenc(buffer().params()) == "OT1")
2377                 || (fontenc == "custom" && fontModule->fontencLE->text() == "OT1"));
2378 }
2379
2380
2381 bool GuiDocument::completeFontset() const
2382 {
2383         return (fontModule->fontsSansCO->itemData(
2384                         fontModule->fontsSansCO->currentIndex()).toString() == "default"
2385                 && fontModule->fontsSansCO->itemData(
2386                         fontModule->fontsTypewriterCO->currentIndex()).toString() == "default");
2387 }
2388
2389
2390 bool GuiDocument::noMathFont() const
2391 {
2392         return (fontModule->fontsMathCO->itemData(
2393                 fontModule->fontsMathCO->currentIndex()).toString() == "default");
2394 }
2395
2396
2397 void GuiDocument::updateTexFonts()
2398 {
2399         LaTeXFonts::TexFontMap texfontmap = theLaTeXFonts().getLaTeXFonts();
2400
2401         LaTeXFonts::TexFontMap::const_iterator it = texfontmap.begin();
2402         LaTeXFonts::TexFontMap::const_iterator end = texfontmap.end();
2403         for (; it != end; ++it) {
2404                 LaTeXFont lf = it->second;
2405                 if (lf.name().empty()) {
2406                         LYXERR0("Error: Unnamed font: " << it->first);
2407                         continue;
2408                 }
2409                 docstring const family = lf.family();
2410                 docstring guiname = translateIfPossible(lf.guiname());
2411                 if (!lf.available(ot1(), noMathFont()))
2412                         guiname += _(" (not installed)");
2413                 if (family == "rm")
2414                         rmfonts_.insert(toqstr(guiname), toqstr(it->first));
2415                 else if (family == "sf")
2416                         sffonts_.insert(toqstr(guiname), toqstr(it->first));
2417                 else if (family == "tt")
2418                         ttfonts_.insert(toqstr(guiname), toqstr(it->first));
2419                 else if (family == "math")
2420                         mathfonts_.insert(toqstr(guiname), toqstr(it->first));
2421         }
2422 }
2423
2424
2425 void GuiDocument::updateFontlist()
2426 {
2427         fontModule->fontsRomanCO->clear();
2428         fontModule->fontsSansCO->clear();
2429         fontModule->fontsTypewriterCO->clear();
2430         fontModule->fontsMathCO->clear();
2431
2432         // With fontspec (XeTeX, LuaTeX), we have access to all system fonts, but not the LaTeX fonts
2433         if (fontModule->osFontsCB->isChecked()) {
2434                 fontModule->fontsRomanCO->addItem(qt_("Default"), QString("default"));
2435                 fontModule->fontsSansCO->addItem(qt_("Default"), QString("default"));
2436                 fontModule->fontsTypewriterCO->addItem(qt_("Default"), QString("default"));
2437                 QString unimath = qt_("Non-TeX Fonts Default");
2438                 if (!LaTeXFeatures::isAvailable("unicode-math"))
2439                         unimath += qt_(" (not available)");
2440                 fontModule->fontsMathCO->addItem(qt_("Class Default (TeX Fonts)"), QString("auto"));
2441                 fontModule->fontsMathCO->addItem(unimath, QString("default"));
2442
2443                 QFontDatabase fontdb;
2444                 QStringList families(fontdb.families());
2445                 for (QStringList::Iterator it = families.begin(); it != families.end(); ++it) {
2446                         fontModule->fontsRomanCO->addItem(*it, *it);
2447                         fontModule->fontsSansCO->addItem(*it, *it);
2448                         fontModule->fontsTypewriterCO->addItem(*it, *it);
2449                 }
2450                 return;
2451         }
2452
2453         if (rmfonts_.empty())
2454                 updateTexFonts();
2455
2456         fontModule->fontsRomanCO->addItem(qt_("Default"), QString("default"));
2457         QMap<QString, QString>::const_iterator rmi = rmfonts_.constBegin();
2458         while (rmi != rmfonts_.constEnd()) {
2459                 fontModule->fontsRomanCO->addItem(rmi.key(), rmi.value());
2460                 ++rmi;
2461         }
2462
2463         fontModule->fontsSansCO->addItem(qt_("Default"), QString("default"));
2464         QMap<QString, QString>::const_iterator sfi = sffonts_.constBegin();
2465         while (sfi != sffonts_.constEnd()) {
2466                 fontModule->fontsSansCO->addItem(sfi.key(), sfi.value());
2467                 ++sfi;
2468         }
2469
2470         fontModule->fontsTypewriterCO->addItem(qt_("Default"), QString("default"));
2471         QMap<QString, QString>::const_iterator tti = ttfonts_.constBegin();
2472         while (tti != ttfonts_.constEnd()) {
2473                 fontModule->fontsTypewriterCO->addItem(tti.key(), tti.value());
2474                 ++tti;
2475         }
2476
2477         fontModule->fontsMathCO->addItem(qt_("Automatic"), QString("auto"));
2478         fontModule->fontsMathCO->addItem(qt_("Class Default"), QString("default"));
2479         QMap<QString, QString>::const_iterator mmi = mathfonts_.constBegin();
2480         while (mmi != mathfonts_.constEnd()) {
2481                 fontModule->fontsMathCO->addItem(mmi.key(), mmi.value());
2482                 ++mmi;
2483         }
2484 }
2485
2486
2487 void GuiDocument::fontencChanged(int item)
2488 {
2489         fontModule->fontencLE->setEnabled(
2490                 fontModule->fontencCO->itemData(item).toString() == "custom");
2491         // The availability of TeX fonts depends on the font encoding
2492         updateTexFonts();
2493         updateFontOptions();
2494 }
2495
2496
2497 void GuiDocument::updateMathFonts(QString const & rm)
2498 {
2499         if (fontModule->osFontsCB->isChecked())
2500                 return;
2501         QString const math =
2502                 fontModule->fontsMathCO->itemData(fontModule->fontsMathCO->currentIndex()).toString();
2503         int const i = fontModule->fontsMathCO->findData("default");
2504         if (providesNoMath(rm) && i == -1)
2505                 fontModule->fontsMathCO->insertItem(1, qt_("Class Default"), QString("default"));
2506         else if (!providesNoMath(rm) && i != -1) {
2507                 int const c = fontModule->fontsMathCO->currentIndex();
2508                 fontModule->fontsMathCO->removeItem(i);
2509                 if (c == i)
2510                         fontModule->fontsMathCO->setCurrentIndex(0);
2511         }
2512 }
2513
2514
2515 void GuiDocument::romanChanged(int item)
2516 {
2517         if (fontModule->osFontsCB->isChecked())
2518                 return;
2519         QString const font =
2520                 fontModule->fontsRomanCO->itemData(item).toString();
2521         fontModule->fontScCB->setEnabled(providesSC(font));
2522         fontModule->fontOsfCB->setEnabled(providesOSF(font));
2523         updateMathFonts(font);
2524 }
2525
2526
2527 void GuiDocument::sansChanged(int item)
2528 {
2529         if (fontModule->osFontsCB->isChecked())
2530                 return;
2531         QString const font =
2532                 fontModule->fontsSansCO->itemData(item).toString();
2533         bool scaleable = providesScale(font);
2534         fontModule->scaleSansSB->setEnabled(scaleable);
2535         fontModule->scaleSansLA->setEnabled(scaleable);
2536 }
2537
2538
2539 void GuiDocument::ttChanged(int item)
2540 {
2541         if (fontModule->osFontsCB->isChecked())
2542                 return;
2543         QString const font =
2544                 fontModule->fontsTypewriterCO->itemData(item).toString();
2545         bool scaleable = providesScale(font);
2546         fontModule->scaleTypewriterSB->setEnabled(scaleable);
2547         fontModule->scaleTypewriterLA->setEnabled(scaleable);
2548 }
2549
2550
2551 void GuiDocument::updatePagestyle(string const & items, string const & sel)
2552 {
2553         pagestyles.clear();
2554         pageLayoutModule->pagestyleCO->clear();
2555         pageLayoutModule->pagestyleCO->addItem(qt_("Default"));
2556
2557         for (int n = 0; !token(items, '|', n).empty(); ++n) {
2558                 string style = token(items, '|', n);
2559                 QString style_gui = qt_(style);
2560                 pagestyles.push_back(pair<string, QString>(style, style_gui));
2561                 pageLayoutModule->pagestyleCO->addItem(style_gui);
2562         }
2563
2564         if (sel == "default") {
2565                 pageLayoutModule->pagestyleCO->setCurrentIndex(0);
2566                 return;
2567         }
2568
2569         int nn = 0;
2570
2571         for (size_t i = 0; i < pagestyles.size(); ++i)
2572                 if (pagestyles[i].first == sel)
2573                         nn = pageLayoutModule->pagestyleCO->findText(pagestyles[i].second);
2574
2575         if (nn > 0)
2576                 pageLayoutModule->pagestyleCO->setCurrentIndex(nn);
2577 }
2578
2579
2580 void GuiDocument::browseLayout()
2581 {
2582         QString const label1 = qt_("Lay&outs");
2583         QString const dir1 = toqstr(lyxrc.document_path);
2584         QStringList const filter(qt_("LyX Layout (*.layout)"));
2585         QString file = browseRelToParent(QString(), bufferFilePath(),
2586                 qt_("Local layout file"), filter, false,
2587                 label1, dir1);
2588
2589         if (!file.endsWith(".layout"))
2590                 return;
2591
2592         FileName layoutFile = support::makeAbsPath(fromqstr(file),
2593                 fromqstr(bufferFilePath()));
2594
2595         int const ret = Alert::prompt(_("Local layout file"),
2596                 _("The layout file you have selected is a local layout\n"
2597                   "file, not one in the system or user directory.\n"
2598                   "Your document will not work with this layout if you\n"
2599                   "move the layout file to a different directory."),
2600                   1, 1, _("&Set Layout"), _("&Cancel"));
2601         if (ret == 1)
2602                 return;
2603
2604         // load the layout file
2605         LayoutFileList & bcl = LayoutFileList::get();
2606         string classname = layoutFile.onlyFileName();
2607         // this will update an existing layout if that layout has been loaded before.
2608         LayoutFileIndex name = support::onlyFileName(bcl.addLocalLayout(
2609                 classname.substr(0, classname.size() - 7),
2610                 layoutFile.onlyPath().absFileName()));
2611
2612         if (name.empty()) {
2613                 Alert::error(_("Error"),
2614                         _("Unable to read local layout file."));
2615                 return;
2616         }
2617
2618         const_cast<Buffer &>(buffer()).setLayoutPos(layoutFile.onlyPath().absFileName());
2619
2620         // do not trigger classChanged if there is no change.
2621         if (latexModule->classCO->currentText() == toqstr(name))
2622                 return;
2623
2624         // add to combo box
2625         bool const avail = latexModule->classCO->set(toqstr(name));
2626         if (!avail) {
2627                 LayoutFile const & tc = bcl[name];
2628                 docstring const guiname = translateIfPossible(from_utf8(tc.description()));
2629                 // tooltip sensu "KOMA-Script Article [Class 'scrartcl']"
2630                 QString tooltip = toqstr(bformat(_("%1$s [Class '%2$s']"), guiname, from_utf8(tc.latexname())));
2631                 tooltip += '\n' + qt_("This is a local layout file.");
2632                 latexModule->classCO->addItemSort(toqstr(tc.name()), toqstr(guiname),
2633                                                   toqstr(translateIfPossible(from_utf8(tc.category()))),
2634                                                   tooltip,
2635                                                   true, true, true, true);
2636                 latexModule->classCO->set(toqstr(name));
2637         }
2638
2639         classChanged();
2640 }
2641
2642
2643 void GuiDocument::browseMaster()
2644 {
2645         QString const title = qt_("Select master document");
2646         QString const dir1 = toqstr(lyxrc.document_path);
2647         QString const old = latexModule->childDocLE->text();
2648         QString const docpath = toqstr(support::onlyPath(buffer().absFileName()));
2649         QStringList const filter(qt_("LyX Files (*.lyx)"));
2650         QString file = browseRelToSub(old, docpath, title, filter, false,
2651                 qt_("D&ocuments"), toqstr(lyxrc.document_path));
2652
2653         if (!file.isEmpty())
2654                 latexModule->childDocLE->setText(file);
2655 }
2656
2657
2658 void GuiDocument::classChanged_adaptor()
2659 {
2660         const_cast<Buffer &>(buffer()).setLayoutPos(string());
2661         classChanged();
2662 }
2663
2664
2665 void GuiDocument::classChanged()
2666 {
2667         int idx = latexModule->classCO->currentIndex();
2668         if (idx < 0)
2669                 return;
2670         string const classname = fromqstr(latexModule->classCO->getData(idx));
2671
2672         if (buttonBox->button(QDialogButtonBox::Apply)->isEnabled()) {
2673                 int const ret = Alert::prompt(_("Unapplied changes"),
2674                                 _("Some changes in the dialog were not yet applied.\n"
2675                                 "If you do not apply now, they will be lost after this action."),
2676                                 1, 1, _("&Apply"), _("&Dismiss"));
2677                 if (ret == 0)
2678                         applyView();
2679         }
2680
2681         // We load the TextClass as soon as it is selected. This is
2682         // necessary so that other options in the dialog can be updated
2683         // according to the new class. Note, however, that, if you use
2684         // the scroll wheel when sitting on the combo box, we'll load a
2685         // lot of TextClass objects very quickly....
2686         if (!bp_.setBaseClass(classname, buffer().layoutPos())) {
2687                 Alert::error(_("Error"), _("Unable to set document class."));
2688                 return;
2689         }
2690         if (lyxrc.auto_reset_options)
2691                 bp_.useClassDefaults();
2692
2693         // With the introduction of modules came a distinction between the base
2694         // class and the document class. The former corresponds to the main layout
2695         // file; the latter is that plus the modules (or the document-specific layout,
2696         // or  whatever else there could be). Our parameters come from the document
2697         // class. So when we set the base class, we also need to recreate the document
2698         // class. Otherwise, we still have the old one.
2699         bp_.makeDocumentClass();
2700         paramsToDialog();
2701 }
2702
2703
2704 void GuiDocument::languagePackageChanged(int i)
2705 {
2706          langModule->languagePackageLE->setEnabled(
2707                 langModule->languagePackageCO->itemData(i).toString() == "custom");
2708 }
2709
2710
2711 void GuiDocument::biblioChanged()
2712 {
2713         biblioChanged_ = true;
2714         change_adaptor();
2715 }
2716
2717
2718 void GuiDocument::checkPossibleCiteEngines()
2719 {
2720         // Check if the class provides a specific engine,
2721         // and if so, enforce this.
2722         string force_engine;
2723         if (documentClass().provides("natbib")
2724             || documentClass().provides("natbib-internal"))
2725                 force_engine = "natbib";
2726         else if (documentClass().provides("jurabib"))
2727                 force_engine = "jurabib";
2728         else if (documentClass().provides("biblatex"))
2729                 force_engine = "biblatex";
2730         else if (documentClass().provides("biblatex-natbib"))
2731                 force_engine = "biblatex-natbib";
2732
2733         if (!force_engine.empty())
2734                 biblioModule->citeEngineCO->setCurrentIndex(
2735                         biblioModule->citeEngineCO->findData(toqstr(force_engine)));
2736         biblioModule->citeEngineCO->setEnabled(force_engine.empty());
2737 }
2738
2739
2740 void GuiDocument::rescanBibFiles()
2741 {
2742         if (isBiblatex())
2743                 rescanTexStyles("bbx cbx");
2744         else
2745                 rescanTexStyles("bst");
2746 }
2747
2748
2749 void GuiDocument::resetDefaultBibfile(string const & which)
2750 {
2751         QString const engine =
2752                 biblioModule->citeEngineCO->itemData(
2753                                 biblioModule->citeEngineCO->currentIndex()).toString();
2754
2755         CiteEngineType const cet =
2756                 CiteEngineType(biblioModule->citeStyleCO->itemData(
2757                                                           biblioModule->citeStyleCO->currentIndex()).toInt());
2758
2759         updateDefaultBiblio(theCiteEnginesList[fromqstr(engine)]->getDefaultBiblio(cet), which);
2760 }
2761
2762
2763 void GuiDocument::resetDefaultBbxBibfile()
2764 {
2765         resetDefaultBibfile("bbx");
2766 }
2767
2768
2769 void GuiDocument::resetDefaultCbxBibfile()
2770 {
2771         resetDefaultBibfile("cbx");
2772 }
2773
2774
2775 void GuiDocument::citeEngineChanged(int n)
2776 {
2777         QString const engine =
2778                 biblioModule->citeEngineCO->itemData(n).toString();
2779
2780         vector<string> const engs =
2781                 theCiteEnginesList[fromqstr(engine)]->getEngineType();
2782
2783         updateCiteStyles(engs);
2784         updateEngineDependends();
2785         resetDefaultBibfile();
2786         biblioChanged();
2787 }
2788
2789
2790 void GuiDocument::updateEngineDependends()
2791 {
2792         bool const biblatex = isBiblatex();
2793
2794         // These are only useful with BibTeX
2795         biblioModule->defaultBiblioCO->setEnabled(!biblatex);
2796         biblioModule->bibtexStyleLA->setEnabled(!biblatex);
2797         biblioModule->resetDefaultBiblioPB->setEnabled(!biblatex);
2798         biblioModule->bibtopicCB->setEnabled(!biblatex);
2799
2800         // These are only useful with Biblatex
2801         biblioModule->biblatexBbxCO->setEnabled(biblatex);
2802         biblioModule->biblatexBbxLA->setEnabled(biblatex);
2803         biblioModule->biblatexCbxCO->setEnabled(biblatex);
2804         biblioModule->biblatexCbxLA->setEnabled(biblatex);
2805         biblioModule->resetBbxPB->setEnabled(biblatex);
2806         biblioModule->resetCbxPB->setEnabled(biblatex);
2807         biblioModule->matchBbxPB->setEnabled(biblatex);
2808
2809         // These are useful with biblatex, jurabib and natbib
2810         QString const engine =
2811                 biblioModule->citeEngineCO->itemData(
2812                                 biblioModule->citeEngineCO->currentIndex()).toString();
2813         LyXCiteEngine const * ce = theCiteEnginesList[fromqstr(engine)];
2814
2815         bool const citepack = ce->requires("biblatex.sty") || ce->requires("jurabib.sty")
2816                         || ce->requires("natbib.sty");
2817         biblioModule->citePackageOptionsLE->setEnabled(citepack);
2818         biblioModule->citePackageOptionsL->setEnabled(citepack);
2819 }
2820
2821
2822 void GuiDocument::citeStyleChanged()
2823 {
2824         QString const engine =
2825                 biblioModule->citeEngineCO->itemData(
2826                                 biblioModule->citeEngineCO->currentIndex()).toString();
2827         QString const currentDef = isBiblatex() ?
2828                 biblioModule->biblatexBbxCO->currentText()
2829                 : biblioModule->defaultBiblioCO->currentText();
2830         if (theCiteEnginesList[fromqstr(engine)]->isDefaultBiblio(fromqstr(currentDef)))
2831                 resetDefaultBibfile();
2832
2833         biblioChanged();
2834 }
2835
2836
2837 void GuiDocument::bibtexChanged(int n)
2838 {
2839         biblioModule->bibtexOptionsLE->setEnabled(
2840                 biblioModule->bibtexCO->itemData(n).toString() != "default");
2841         biblioChanged();
2842 }
2843
2844
2845 void GuiDocument::updateCiteStyles(vector<string> const & engs, CiteEngineType const & sel)
2846 {
2847         biblioModule->citeStyleCO->clear();
2848
2849         vector<string>::const_iterator it  = engs.begin();
2850         vector<string>::const_iterator end = engs.end();
2851         for (; it != end; ++it) {
2852                 if (*it == "default")
2853                         biblioModule->citeStyleCO->addItem(qt_("Basic numerical"),
2854                                                            ENGINE_TYPE_DEFAULT);
2855                 else if (*it == "authoryear")
2856                         biblioModule->citeStyleCO->addItem(qt_("Author-year"),
2857                                                            ENGINE_TYPE_AUTHORYEAR);
2858                 else if (*it == "numerical")
2859                         biblioModule->citeStyleCO->addItem(qt_("Author-number"),
2860                                                            ENGINE_TYPE_NUMERICAL);
2861         }
2862         int i = biblioModule->citeStyleCO->findData(sel);
2863         if (biblioModule->citeStyleCO->findData(sel) == -1)
2864                 i = 0;
2865         biblioModule->citeStyleCO->setCurrentIndex(i);
2866
2867         biblioModule->citationStyleL->setEnabled(engs.size() > 1);
2868         biblioModule->citeStyleCO->setEnabled(engs.size() > 1);
2869 }
2870
2871
2872 void GuiDocument::updateEngineType(string const & items, CiteEngineType const & sel)
2873 {
2874         engine_types_.clear();
2875
2876         int nn = 0;
2877
2878         for (int n = 0; !token(items, '|', n).empty(); ++n) {
2879                 nn += 1;
2880                 string style = token(items, '|', n);
2881                 engine_types_.push_back(style);
2882         }
2883
2884         updateCiteStyles(engine_types_, sel);
2885 }
2886
2887
2888 namespace {
2889         // FIXME unicode
2890         // both of these should take a vector<docstring>
2891
2892         // This is an insanely complicated attempt to make this sort of thing
2893         // work with RTL languages.
2894         docstring formatStrVec(vector<string> const & v, docstring const & s)
2895         {
2896                 //this mess formats the list as "v[0], v[1], ..., [s] v[n]"
2897                 if (v.empty())
2898                         return docstring();
2899                 if (v.size() == 1)
2900                         return translateIfPossible(from_utf8(v[0]));
2901                 if (v.size() == 2) {
2902                         docstring retval = _("%1$s and %2$s");
2903                         retval = subst(retval, _("and"), s);
2904                         return bformat(retval, translateIfPossible(from_utf8(v[0])),
2905                                        translateIfPossible(from_utf8(v[1])));
2906                 }
2907                 // The idea here is to format all but the last two items...
2908                 int const vSize = v.size();
2909                 docstring t2 = _("%1$s, %2$s");
2910                 docstring retval = translateIfPossible(from_utf8(v[0]));
2911                 for (int i = 1; i < vSize - 2; ++i)
2912                         retval = bformat(t2, retval, translateIfPossible(from_utf8(v[i])));
2913                 //...and then to  plug them, and the last two, into this schema
2914                 docstring t = _("%1$s, %2$s, and %3$s");
2915                 t = subst(t, _("and"), s);
2916                 return bformat(t, retval, translateIfPossible(from_utf8(v[vSize - 2])),
2917                                translateIfPossible(from_utf8(v[vSize - 1])));
2918         }
2919
2920         vector<string> idsToNames(vector<string> const & idList)
2921         {
2922                 vector<string> retval;
2923                 vector<string>::const_iterator it  = idList.begin();
2924                 vector<string>::const_iterator end = idList.end();
2925                 for (; it != end; ++it) {
2926                         LyXModule const * const mod = theModuleList[*it];
2927                         if (!mod)
2928                                 retval.push_back(to_utf8(bformat(_("%1$s (unavailable)"),
2929                                                 translateIfPossible(from_utf8(*it)))));
2930                         else
2931                                 retval.push_back(mod->getName());
2932                 }
2933                 return retval;
2934         }
2935 } // end anonymous namespace
2936
2937
2938 void GuiDocument::modulesToParams(BufferParams & bp)
2939 {
2940         // update list of loaded modules
2941         bp.clearLayoutModules();
2942         int const srows = modules_sel_model_.rowCount();
2943         for (int i = 0; i < srows; ++i)
2944                 bp.addLayoutModule(modules_sel_model_.getIDString(i));
2945         updateSelectedModules();
2946
2947         // update the list of removed modules
2948         bp.clearRemovedModules();
2949         LayoutModuleList const & reqmods = bp.baseClass()->defaultModules();
2950         list<string>::const_iterator rit = reqmods.begin();
2951         list<string>::const_iterator ren = reqmods.end();
2952
2953         // check each of the default modules
2954         for (; rit != ren; ++rit) {
2955                 list<string>::const_iterator mit = bp.getModules().begin();
2956                 list<string>::const_iterator men = bp.getModules().end();
2957                 bool found = false;
2958                 for (; mit != men; ++mit) {
2959                         if (*rit == *mit) {
2960                                 found = true;
2961                                 break;
2962                         }
2963                 }
2964                 if (!found) {
2965                         // the module isn't present so must have been removed by the user
2966                         bp.addRemovedModule(*rit);
2967                 }
2968         }
2969 }
2970
2971 void GuiDocument::modulesChanged()
2972 {
2973         modulesToParams(bp_);
2974
2975         if (buttonBox->button(QDialogButtonBox::Apply)->isEnabled()
2976             && (nonModuleChanged_ || shellescapeChanged_)) {
2977                 int const ret = Alert::prompt(_("Unapplied changes"),
2978                                 _("Some changes in the dialog were not yet applied.\n"
2979                                 "If you do not apply now, they will be lost after this action."),
2980                                 1, 1, _("&Apply"), _("&Dismiss"));
2981                 if (ret == 0)
2982                         applyView();
2983         }
2984
2985         modulesChanged_ = true;
2986         bp_.makeDocumentClass();
2987         paramsToDialog();
2988         changed();
2989 }
2990
2991
2992 void GuiDocument::updateModuleInfo()
2993 {
2994         selectionManager->update();
2995
2996         //Module description
2997         bool const focus_on_selected = selectionManager->selectedFocused();
2998         QAbstractItemView * lv;
2999         bool category = false;
3000         if (focus_on_selected) {
3001                 lv = modulesModule->selectedLV;
3002                 category = true;
3003         } else
3004                 lv = modulesModule->availableLV;
3005         if (lv->selectionModel()->selectedIndexes().isEmpty()) {
3006                 modulesModule->infoML->document()->clear();
3007                 return;
3008         }
3009         QModelIndex const & idx = lv->selectionModel()->currentIndex();
3010
3011         if (!focus_on_selected
3012             && modules_av_model_.itemFromIndex(idx)->hasChildren()) {
3013                 // This is a category header
3014                 modulesModule->infoML->document()->clear();
3015                 return;
3016         }
3017
3018         string const modName = focus_on_selected ?
3019                                 modules_sel_model_.getIDString(idx.row())
3020                               : fromqstr(modules_av_model_.data(idx, Qt::UserRole).toString());
3021         docstring desc = getModuleDescription(modName);
3022
3023         LayoutModuleList const & provmods = bp_.baseClass()->providedModules();
3024         if (std::find(provmods.begin(), provmods.end(), modName) != provmods.end()) {
3025                 if (!desc.empty())
3026                         desc += "\n";
3027                 desc += _("Module provided by document class.");
3028         }
3029
3030         if (category) {
3031                 docstring cat = getModuleCategory(modName);
3032                 if (!cat.empty()) {
3033                         if (!desc.empty())
3034                                 desc += "\n";
3035                         desc += bformat(_("<p><b>Category:</b> %1$s.</p>"),
3036                                         translateIfPossible(cat));
3037                 }
3038         }
3039
3040         vector<string> pkglist = getPackageList(modName);
3041         docstring pkgdesc = formatStrVec(pkglist, _("and"));
3042         if (!pkgdesc.empty()) {
3043                 if (!desc.empty())
3044                         desc += "\n";
3045                 desc += bformat(_("<p><b>Package(s) required:</b> %1$s.</p>"), pkgdesc);
3046         }
3047
3048         pkglist = getRequiredList(modName);
3049         if (!pkglist.empty()) {
3050                 vector<string> const reqdescs = idsToNames(pkglist);
3051                 pkgdesc = formatStrVec(reqdescs, _("or"));
3052                 if (!desc.empty())
3053                         desc += "\n";
3054                 desc += bformat(_("<p><b>Modules required:</b> %1$s.</p>"), pkgdesc);
3055         }
3056
3057         pkglist = getExcludedList(modName);
3058         if (!pkglist.empty()) {
3059                 vector<string> const reqdescs = idsToNames(pkglist);
3060                 pkgdesc = formatStrVec(reqdescs, _( "and"));
3061                 if (!desc.empty())
3062                         desc += "\n";
3063                 desc += bformat(_("<p><b>Modules excluded:</b> %1$s.</p>"), pkgdesc);
3064         }
3065
3066         if (!desc.empty())
3067                 desc += "\n";
3068         desc += bformat(_("<p><b>Filename:</b> <tt>%1$s.module</tt>.</p>"), from_utf8(modName));
3069
3070         if (!isModuleAvailable(modName)) {
3071                 if (!desc.empty())
3072                         desc += "\n";
3073                 desc += _("<p><font color=red><b>WARNING: Some required packages are unavailable!</b></font></p>");
3074         }
3075
3076         modulesModule->infoML->document()->setHtml(toqstr(desc));
3077 }
3078
3079
3080 void GuiDocument::updateNumbering()
3081 {
3082         DocumentClass const & tclass = documentClass();
3083
3084         numberingModule->tocTW->setUpdatesEnabled(false);
3085         numberingModule->tocTW->clear();
3086
3087         int const depth = numberingModule->depthSL->value();
3088         int const toc = numberingModule->tocSL->value();
3089         QString const no = qt_("No");
3090         QString const yes = qt_("Yes");
3091         QTreeWidgetItem * item = 0;
3092
3093         DocumentClass::const_iterator lit = tclass.begin();
3094         DocumentClass::const_iterator len = tclass.end();
3095         for (; lit != len; ++lit) {
3096                 int const toclevel = lit->toclevel;
3097                 if (toclevel != Layout::NOT_IN_TOC && !lit->counter.empty()) {
3098                         item = new QTreeWidgetItem(numberingModule->tocTW);
3099                         item->setText(0, toqstr(translateIfPossible(lit->name())));
3100                         item->setText(1, (toclevel <= depth) ? yes : no);
3101                         item->setText(2, (toclevel <= toc) ? yes : no);
3102                 }
3103         }
3104
3105         numberingModule->tocTW->setUpdatesEnabled(true);
3106         numberingModule->tocTW->update();
3107 }
3108
3109
3110 void GuiDocument::getTableStyles()
3111 {
3112         // We look for lyx files in the subdirectory dir of
3113         //   1) user_lyxdir
3114         //   2) build_lyxdir (if not empty)
3115         //   3) system_lyxdir
3116         // in this order. Files with a given sub-hierarchy will
3117         // only be listed once.
3118         // We also consider i18n subdirectories and store them separately.
3119         QStringList dirs;
3120
3121         // The three locations to look at.
3122         string const user = addPath(package().user_support().absFileName(), "tabletemplates");
3123         string const build = addPath(package().build_support().absFileName(), "tabletemplates");
3124         string const system = addPath(package().system_support().absFileName(), "tabletemplates");
3125
3126         dirs << toqstr(user)
3127              << toqstr(build)
3128              << toqstr(system);
3129
3130         for (int i = 0; i < dirs.size(); ++i) {
3131                 QString const dir = dirs.at(i);
3132                 QDirIterator it(dir, QDir::Files, QDirIterator::Subdirectories);
3133                 while (it.hasNext()) {
3134                         QString fn = QFileInfo(it.next()).fileName();
3135                         if (!fn.endsWith(".lyx") || fn.contains("_1x"))
3136                                 continue;
3137                         QString data = fn.left(fn.lastIndexOf(".lyx"));
3138                         QString guiname = data;
3139                         guiname = toqstr(translateIfPossible(qstring_to_ucs4(guiname.replace('_', ' '))));
3140                         QString relpath = toqstr(makeRelPath(qstring_to_ucs4(fn),
3141                                                              qstring_to_ucs4(dir)));
3142                         if (textLayoutModule->tableStyleCO->findData(data) == -1)
3143                                 textLayoutModule->tableStyleCO->addItem(guiname, data);
3144                 }
3145         }
3146 }
3147
3148
3149 void GuiDocument::updateDefaultFormat()
3150 {
3151         if (!bufferview())
3152                 return;
3153         // make a copy in order to consider unapplied changes
3154         BufferParams param_copy = buffer().params();
3155         param_copy.useNonTeXFonts = fontModule->osFontsCB->isChecked();
3156         int const idx = latexModule->classCO->currentIndex();
3157         if (idx >= 0) {
3158                 string const classname = fromqstr(latexModule->classCO->getData(idx));
3159                 param_copy.setBaseClass(classname, buffer().layoutPos());
3160                 param_copy.makeDocumentClass(true);
3161         }
3162         outputModule->defaultFormatCO->blockSignals(true);
3163         outputModule->defaultFormatCO->clear();
3164         outputModule->defaultFormatCO->addItem(qt_("Default"),
3165                                 QVariant(QString("default")));
3166         FormatList const & formats =
3167                                 param_copy.exportableFormats(true);
3168         for (Format const * f : formats)
3169                 outputModule->defaultFormatCO->addItem
3170                         (toqstr(translateIfPossible(f->prettyname())),
3171                          QVariant(toqstr(f->name())));
3172         outputModule->defaultFormatCO->blockSignals(false);
3173 }
3174
3175
3176 bool GuiDocument::isChildIncluded(string const & child)
3177 {
3178         if (includeonlys_.empty())
3179                 return false;
3180         return (std::find(includeonlys_.begin(),
3181                           includeonlys_.end(), child) != includeonlys_.end());
3182 }
3183
3184
3185 void GuiDocument::applyView()
3186 {
3187         // preamble
3188         preambleModule->apply(bp_);
3189         localLayout->apply(bp_);
3190
3191         // date
3192         bp_.suppress_date = latexModule->suppressDateCB->isChecked();
3193         bp_.use_refstyle  = latexModule->refstyleCB->isChecked();
3194
3195         // biblio
3196         string const engine =
3197                 fromqstr(biblioModule->citeEngineCO->itemData(
3198                                 biblioModule->citeEngineCO->currentIndex()).toString());
3199         bp_.setCiteEngine(engine);
3200
3201         CiteEngineType const style = CiteEngineType(biblioModule->citeStyleCO->itemData(
3202                 biblioModule->citeStyleCO->currentIndex()).toInt());
3203         if (theCiteEnginesList[engine]->hasEngineType(style))
3204                 bp_.setCiteEngineType(style);
3205         else
3206                 bp_.setCiteEngineType(ENGINE_TYPE_DEFAULT);
3207
3208         bp_.splitbib(biblioModule->bibtopicCB->isChecked());
3209
3210         bp_.multibib = fromqstr(biblioModule->bibunitsCO->itemData(
3211                                 biblioModule->bibunitsCO->currentIndex()).toString());
3212
3213         bp_.setDefaultBiblioStyle(fromqstr(biblioModule->defaultBiblioCO->currentText()));
3214
3215         bp_.biblatex_bibstyle = fromqstr(biblioModule->biblatexBbxCO->currentText());
3216         bp_.biblatex_citestyle = fromqstr(biblioModule->biblatexCbxCO->currentText());
3217         bp_.biblio_opts = fromqstr(biblioModule->citePackageOptionsLE->text());
3218
3219         string const bibtex_command =
3220                 fromqstr(biblioModule->bibtexCO->itemData(
3221                         biblioModule->bibtexCO->currentIndex()).toString());
3222         string const bibtex_options =
3223                 fromqstr(biblioModule->bibtexOptionsLE->text());
3224         if (bibtex_command == "default" || bibtex_options.empty())
3225                 bp_.bibtex_command = bibtex_command;
3226         else
3227                 bp_.bibtex_command = bibtex_command + " " + bibtex_options;
3228
3229         if (biblioChanged_) {
3230                 buffer().invalidateBibinfoCache();
3231                 buffer().removeBiblioTempFiles();
3232         }
3233
3234         // Indices
3235         indicesModule->apply(bp_);
3236
3237         // language & quotes
3238         QString const encoding = langModule->encodingCO->itemData(
3239                                 langModule->encodingCO->currentIndex()).toString();
3240         if (encoding != "custom")
3241                 bp_.inputenc = fromqstr(encoding);
3242         else
3243                 bp_.inputenc = fromqstr(langModule->customEncodingCO->itemData(
3244                                         langModule->customEncodingCO->currentIndex()).toString());
3245         if (langModule->noInputencCB->isChecked()
3246             && (encoding == "auto-legacy" || encoding == "utf8"))
3247                 bp_.inputenc += "-plain";
3248
3249         bp_.quotes_style = (InsetQuotesParams::QuoteStyle) langModule->quoteStyleCO->itemData(
3250                 langModule->quoteStyleCO->currentIndex()).toInt();
3251         bp_.dynamic_quotes = langModule->dynamicQuotesCB->isChecked();
3252
3253         QString const langname = langModule->languageCO->itemData(
3254                 langModule->languageCO->currentIndex()).toString();
3255         Language const * newlang = lyx::languages.getLanguage(fromqstr(langname));
3256         Cursor & cur = const_cast<BufferView *>(bufferview())->cursor();
3257         // If current cursor language was the document language, then update it too.
3258         if (cur.current_font.language() == bp_.language) {
3259                 cur.current_font.setLanguage(newlang);
3260                 cur.real_current_font.setLanguage(newlang);
3261         }
3262         bp_.language = newlang;
3263
3264         QString const pack = langModule->languagePackageCO->itemData(
3265                 langModule->languagePackageCO->currentIndex()).toString();
3266         if (pack == "custom")
3267                 bp_.lang_package =
3268                         fromqstr(langModule->languagePackageLE->text());
3269         else
3270                 bp_.lang_package = fromqstr(pack);
3271
3272         //color
3273         bp_.backgroundcolor = set_backgroundcolor;
3274         bp_.isbackgroundcolor = is_backgroundcolor;
3275         bp_.fontcolor = set_fontcolor;
3276         bp_.isfontcolor = is_fontcolor;
3277         bp_.notefontcolor = set_notefontcolor;
3278         bp_.boxbgcolor = set_boxbgcolor;
3279
3280         // numbering
3281         if (bp_.documentClass().hasTocLevels()) {
3282                 bp_.tocdepth = numberingModule->tocSL->value();
3283                 bp_.secnumdepth = numberingModule->depthSL->value();
3284         }
3285
3286         // bullets
3287         bp_.user_defined_bullet(0) = bulletsModule->bullet(0);
3288         bp_.user_defined_bullet(1) = bulletsModule->bullet(1);
3289         bp_.user_defined_bullet(2) = bulletsModule->bullet(2);
3290         bp_.user_defined_bullet(3) = bulletsModule->bullet(3);
3291
3292         // packages
3293         bp_.graphics_driver =
3294                 tex_graphics[latexModule->psdriverCO->currentIndex()];
3295
3296         // text layout
3297         int idx = latexModule->classCO->currentIndex();
3298         if (idx >= 0) {
3299                 string const classname = fromqstr(latexModule->classCO->getData(idx));
3300                 bp_.setBaseClass(classname, buffer().layoutPos());
3301         }
3302
3303         // Modules
3304         modulesToParams(bp_);
3305
3306         // Math
3307         map<string, string> const & packages = BufferParams::auto_packages();
3308         for (map<string, string>::const_iterator it = packages.begin();
3309              it != packages.end(); ++it) {
3310                 QTableWidgetItem * item = mathsModule->packagesTW->findItems(toqstr(it->first), Qt::MatchExactly)[0];
3311                 if (!item)
3312                         continue;
3313                 int row = mathsModule->packagesTW->row(item);
3314
3315                 QRadioButton * rb =
3316                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 1)->layout()->itemAt(0)->widget();
3317                 if (rb->isChecked()) {
3318                         bp_.use_package(it->first, BufferParams::package_auto);
3319                         continue;
3320                 }
3321                 rb = (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 2)->layout()->itemAt(0)->widget();
3322                 if (rb->isChecked()) {
3323                         bp_.use_package(it->first, BufferParams::package_on);
3324                         continue;
3325                 }
3326                 rb = (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 3)->layout()->itemAt(0)->widget();
3327                 if (rb->isChecked())
3328                         bp_.use_package(it->first, BufferParams::package_off);
3329         }
3330         // if math is indented
3331         bp_.is_math_indent = mathsModule->MathIndentCB->isChecked();
3332         if (bp_.is_math_indent) {
3333                 // if formulas are indented
3334                 switch (mathsModule->MathIndentCO->currentIndex()) {
3335                 case 0:
3336                         bp_.setMathIndent(Length());
3337                         break;
3338                 case 1: {
3339                         Length mathindent(widgetsToLength(mathsModule->MathIndentLE,
3340                                                           mathsModule->MathIndentLengthCO));
3341                         bp_.setMathIndent(mathindent);
3342                         break;
3343                 }
3344                 default:
3345                         // this should never happen
3346                         bp_.setMathIndent(Length());
3347                         break;
3348                 }
3349         }
3350         switch (mathsModule->MathNumberingPosCO->currentIndex()) {
3351                 case 0:
3352                         bp_.math_numbering_side = BufferParams::LEFT;
3353                         break;
3354                 case 1:
3355                         bp_.math_numbering_side = BufferParams::DEFAULT;
3356                         break;
3357                 case 2:
3358                         bp_.math_numbering_side = BufferParams::RIGHT;
3359                         break;
3360                 default:
3361                         // this should never happen
3362                         bp_.math_numbering_side = BufferParams::DEFAULT;
3363                         break;
3364         }
3365
3366         // Page Layout
3367         if (pageLayoutModule->pagestyleCO->currentIndex() == 0)
3368                 bp_.pagestyle = "default";
3369         else {
3370                 QString style_gui = pageLayoutModule->pagestyleCO->currentText();
3371                 for (size_t i = 0; i != pagestyles.size(); ++i)
3372                         if (pagestyles[i].second == style_gui)
3373                                 bp_.pagestyle = pagestyles[i].first;
3374         }
3375
3376         // Text Layout
3377         switch (textLayoutModule->lspacingCO->currentIndex()) {
3378         case 0:
3379                 bp_.spacing().set(Spacing::Single);
3380                 break;
3381         case 1:
3382                 bp_.spacing().set(Spacing::Onehalf);
3383                 break;
3384         case 2:
3385                 bp_.spacing().set(Spacing::Double);
3386                 break;
3387         case 3: {
3388                 string s = widgetToDoubleStr(textLayoutModule->lspacingLE);
3389                 if (s.empty())
3390                         bp_.spacing().set(Spacing::Single);
3391                 else
3392                         bp_.spacing().set(Spacing::Other, s);
3393                 break;
3394                 }
3395         }
3396
3397         if (textLayoutModule->twoColumnCB->isChecked())
3398                 bp_.columns = 2;
3399         else
3400                 bp_.columns = 1;
3401
3402         bp_.justification = textLayoutModule->justCB->isChecked();
3403
3404         if (textLayoutModule->indentRB->isChecked()) {
3405                 // if paragraphs are separated by an indentation
3406                 bp_.paragraph_separation = BufferParams::ParagraphIndentSeparation;
3407                 switch (textLayoutModule->indentCO->currentIndex()) {
3408                 case 0:
3409                         bp_.setParIndent(Length());
3410                         break;
3411                 case 1: {
3412                         Length parindent(widgetsToLength(textLayoutModule->indentLE,
3413                                                          textLayoutModule->indentLengthCO));
3414                         bp_.setParIndent(parindent);
3415                         break;
3416                 }
3417                 default:
3418                         // this should never happen
3419                         bp_.setParIndent(Length());
3420                         break;
3421                 }
3422         } else {
3423                 // if paragraphs are separated by a skip
3424                 bp_.paragraph_separation = BufferParams::ParagraphSkipSeparation;
3425                 switch (textLayoutModule->skipCO->currentIndex()) {
3426                 case 0:
3427                         bp_.setDefSkip(VSpace(VSpace::SMALLSKIP));
3428                         break;
3429                 case 1:
3430                         bp_.setDefSkip(VSpace(VSpace::MEDSKIP));
3431                         break;
3432                 case 2:
3433                         bp_.setDefSkip(VSpace(VSpace::BIGSKIP));
3434                         break;
3435                 case 3:
3436                         {
3437                         VSpace vs = VSpace(
3438                                 widgetsToLength(textLayoutModule->skipLE,
3439                                 textLayoutModule->skipLengthCO)
3440                                 );
3441                         bp_.setDefSkip(vs);
3442                         break;
3443                         }
3444                 default:
3445                         // this should never happen
3446                         bp_.setDefSkip(VSpace(VSpace::MEDSKIP));
3447                         break;
3448                 }
3449         }
3450         bp_.tablestyle = fromqstr(textLayoutModule->tableStyleCO->itemData(
3451                                       textLayoutModule->tableStyleCO->currentIndex()).toString());
3452
3453         bp_.options =
3454                 fromqstr(latexModule->optionsLE->text());
3455
3456         bp_.use_default_options =
3457                 latexModule->defaultOptionsCB->isChecked();
3458
3459         if (latexModule->childDocGB->isChecked())
3460                 bp_.master =
3461                         fromqstr(latexModule->childDocLE->text());
3462         else
3463                 bp_.master = string();
3464
3465         // Master/Child
3466         bp_.clearIncludedChildren();
3467         if (masterChildModule->includeonlyRB->isChecked()) {
3468                 list<string>::const_iterator it = includeonlys_.begin();
3469                 for (; it != includeonlys_.end() ; ++it) {
3470                         bp_.addIncludedChildren(*it);
3471                 }
3472         }
3473         bp_.maintain_unincluded_children =
3474                 masterChildModule->maintainAuxCB->isChecked();
3475
3476         // Float Settings
3477         bp_.float_placement = floatModule->getPlacement();
3478         bp_.float_alignment = floatModule->getAlignment();
3479
3480         // Listings
3481         // text should have passed validation
3482         idx = listingsModule->packageCO->currentIndex();
3483         bp_.use_minted = string(lst_packages[idx]) == "Minted";
3484         bp_.listings_params =
3485                 InsetListingsParams(fromqstr(listingsModule->listingsED->toPlainText())).params();
3486
3487         // Formats
3488         bp_.default_output_format = fromqstr(outputModule->defaultFormatCO->itemData(
3489                 outputModule->defaultFormatCO->currentIndex()).toString());
3490
3491         bool const nontexfonts = fontModule->osFontsCB->isChecked();
3492         bp_.useNonTeXFonts = nontexfonts;
3493
3494         bp_.shell_escape = outputModule->shellescapeCB->isChecked();
3495         if (!bp_.shell_escape)
3496             theSession().shellescapeFiles().remove(buffer().absFileName());
3497         else if (!theSession().shellescapeFiles().find(buffer().absFileName()))
3498             theSession().shellescapeFiles().insert(buffer().absFileName());
3499         Buffer & buf = const_cast<Buffer &>(buffer());
3500         buf.params().shell_escape = bp_.shell_escape;
3501
3502         bp_.output_sync = outputModule->outputsyncCB->isChecked();
3503
3504         bp_.output_sync_macro = fromqstr(outputModule->synccustomCB->currentText());
3505
3506         int mathfmt = outputModule->mathoutCB->currentIndex();
3507         if (mathfmt == -1)
3508                 mathfmt = 0;
3509         BufferParams::MathOutput const mo =
3510                 static_cast<BufferParams::MathOutput>(mathfmt);
3511         bp_.html_math_output = mo;
3512         bp_.html_be_strict = outputModule->strictCB->isChecked();
3513         bp_.html_css_as_file = outputModule->cssCB->isChecked();
3514         bp_.html_math_img_scale = outputModule->mathimgSB->value();
3515         bp_.display_pixel_ratio = theGuiApp()->pixelRatio();
3516
3517         bp_.save_transient_properties =
3518                 outputModule->saveTransientPropertiesCB->isChecked();
3519
3520         // fonts
3521         bp_.fonts_roman[nontexfonts] =
3522                 fromqstr(fontModule->fontsRomanCO->
3523                         itemData(fontModule->fontsRomanCO->currentIndex()).toString());
3524         bp_.fonts_roman[!nontexfonts] = fromqstr(fontModule->font_roman);
3525
3526         bp_.fonts_sans[nontexfonts] =
3527                 fromqstr(fontModule->fontsSansCO->
3528                         itemData(fontModule->fontsSansCO->currentIndex()).toString());
3529         bp_.fonts_sans[!nontexfonts] = fromqstr(fontModule->font_sans);
3530
3531         bp_.fonts_typewriter[nontexfonts] =
3532                 fromqstr(fontModule->fontsTypewriterCO->
3533                         itemData(fontModule->fontsTypewriterCO->currentIndex()).toString());
3534         bp_.fonts_typewriter[!nontexfonts] = fromqstr(fontModule->font_typewriter);
3535
3536         bp_.fonts_math[nontexfonts] =
3537                 fromqstr(fontModule->fontsMathCO->
3538                         itemData(fontModule->fontsMathCO->currentIndex()).toString());
3539         bp_.fonts_math[!nontexfonts] = fromqstr(fontModule->font_math);
3540
3541         QString const fontenc =
3542                 fontModule->fontencCO->itemData(fontModule->fontencCO->currentIndex()).toString();
3543         if (fontenc == "custom")
3544                 bp_.fontenc = fromqstr(fontModule->fontencLE->text());
3545         else
3546                 bp_.fontenc = fromqstr(fontenc);
3547
3548         bp_.fonts_cjk =
3549                 fromqstr(fontModule->cjkFontLE->text());
3550
3551         bp_.use_microtype = fontModule->microtypeCB->isChecked();
3552         bp_.use_dash_ligatures = !fontModule->dashesCB->isChecked();
3553
3554         bp_.fonts_sans_scale[nontexfonts] = fontModule->scaleSansSB->value();
3555         bp_.fonts_sans_scale[!nontexfonts] = fontModule->font_sf_scale;
3556
3557         bp_.fonts_typewriter_scale[nontexfonts] = fontModule->scaleTypewriterSB->value();
3558         bp_.fonts_typewriter_scale[!nontexfonts] = fontModule->font_tt_scale;
3559
3560         bp_.fonts_expert_sc = fontModule->fontScCB->isChecked();
3561
3562         bp_.fonts_old_figures = fontModule->fontOsfCB->isChecked();
3563
3564         if (nontexfonts)
3565                 bp_.fonts_default_family = "default";
3566         else
3567                 bp_.fonts_default_family = GuiDocument::fontfamilies[
3568                         fontModule->fontsDefaultCO->currentIndex()];
3569
3570         if (fontModule->fontsizeCO->currentIndex() == 0)
3571                 bp_.fontsize = "default";
3572         else
3573                 bp_.fontsize =
3574                         fromqstr(fontModule->fontsizeCO->currentText());
3575
3576         // paper
3577         bp_.papersize = PAPER_SIZE(
3578                 pageLayoutModule->papersizeCO->currentIndex());
3579
3580         bp_.paperwidth = widgetsToLength(pageLayoutModule->paperwidthLE,
3581                 pageLayoutModule->paperwidthUnitCO);
3582
3583         bp_.paperheight = widgetsToLength(pageLayoutModule->paperheightLE,
3584                 pageLayoutModule->paperheightUnitCO);
3585
3586         if (pageLayoutModule->facingPagesCB->isChecked())
3587                 bp_.sides = TwoSides;
3588         else
3589                 bp_.sides = OneSide;
3590
3591         if (pageLayoutModule->landscapeRB->isChecked())
3592                 bp_.orientation = ORIENTATION_LANDSCAPE;
3593         else
3594                 bp_.orientation = ORIENTATION_PORTRAIT;
3595
3596         // margins
3597         bp_.use_geometry = !marginsModule->marginCB->isChecked();
3598
3599         Ui::MarginsUi const * m = marginsModule;
3600
3601         bp_.leftmargin = widgetsToLength(m->innerLE, m->innerUnit);
3602         bp_.topmargin = widgetsToLength(m->topLE, m->topUnit);
3603         bp_.rightmargin = widgetsToLength(m->outerLE, m->outerUnit);
3604         bp_.bottommargin = widgetsToLength(m->bottomLE, m->bottomUnit);
3605         bp_.headheight = widgetsToLength(m->headheightLE, m->headheightUnit);
3606         bp_.headsep = widgetsToLength(m->headsepLE, m->headsepUnit);
3607         bp_.footskip = widgetsToLength(m->footskipLE, m->footskipUnit);
3608         bp_.columnsep = widgetsToLength(m->columnsepLE, m->columnsepUnit);
3609
3610         // branches
3611         branchesModule->apply(bp_);
3612
3613         // PDF support
3614         PDFOptions & pdf = bp_.pdfoptions();
3615         pdf.use_hyperref = pdfSupportModule->use_hyperrefGB->isChecked();
3616         pdf.title = fromqstr(pdfSupportModule->titleLE->text());
3617         pdf.author = fromqstr(pdfSupportModule->authorLE->text());
3618         pdf.subject = fromqstr(pdfSupportModule->subjectLE->text());
3619         pdf.keywords = fromqstr(pdfSupportModule->keywordsLE->text());
3620
3621         pdf.bookmarks = pdfSupportModule->bookmarksGB->isChecked();
3622         pdf.bookmarksnumbered = pdfSupportModule->bookmarksnumberedCB->isChecked();
3623         pdf.bookmarksopen = pdfSupportModule->bookmarksopenGB->isChecked();
3624         pdf.bookmarksopenlevel = pdfSupportModule->bookmarksopenlevelSB->value();
3625
3626         pdf.breaklinks = pdfSupportModule->breaklinksCB->isChecked();
3627         pdf.pdfborder = pdfSupportModule->pdfborderCB->isChecked();
3628         pdf.pdfusetitle = pdfSupportModule->pdfusetitleCB->isChecked();
3629         pdf.colorlinks = pdfSupportModule->colorlinksCB->isChecked();
3630         pdf.backref =
3631                 backref_opts[pdfSupportModule->backrefCO->currentIndex()];
3632         if (pdfSupportModule->fullscreenCB->isChecked())
3633                 pdf.pagemode = pdf.pagemode_fullscreen;
3634         else
3635                 pdf.pagemode.clear();
3636         pdf.quoted_options = pdf.quoted_options_check(
3637                                 fromqstr(pdfSupportModule->optionsLE->text()));
3638
3639         // reset trackers
3640         nonModuleChanged_ = false;
3641         shellescapeChanged_ = false;
3642 }
3643
3644
3645 void GuiDocument::paramsToDialog()
3646 {
3647         // set the default unit
3648         Length::UNIT const default_unit = Length::defaultUnit();
3649
3650         // preamble
3651         preambleModule->update(bp_, id());
3652         localLayout->update(bp_, id());
3653
3654         // date
3655         latexModule->suppressDateCB->setChecked(bp_.suppress_date);
3656         latexModule->refstyleCB->setChecked(bp_.use_refstyle);
3657
3658         // biblio
3659         string const cite_engine = bp_.citeEngine();
3660
3661         biblioModule->citeEngineCO->setCurrentIndex(
3662                 biblioModule->citeEngineCO->findData(toqstr(cite_engine)));
3663
3664         updateEngineType(documentClass().opt_enginetype(),
3665                 bp_.citeEngineType());
3666
3667         checkPossibleCiteEngines();
3668
3669         biblioModule->citeStyleCO->setCurrentIndex(
3670                 biblioModule->citeStyleCO->findData(bp_.citeEngineType()));
3671
3672         biblioModule->bibtopicCB->setChecked(bp_.splitbib());
3673
3674         biblioModule->bibunitsCO->clear();
3675         biblioModule->bibunitsCO->addItem(qt_("No"), QString());
3676         if (documentClass().hasLaTeXLayout("part"))
3677                 biblioModule->bibunitsCO->addItem(qt_("per part"), toqstr("part"));
3678         if (documentClass().hasLaTeXLayout("chapter"))
3679                 biblioModule->bibunitsCO->addItem(qt_("per chapter"), toqstr("chapter"));
3680         if (documentClass().hasLaTeXLayout("section"))
3681                 biblioModule->bibunitsCO->addItem(qt_("per section"), toqstr("section"));
3682         if (documentClass().hasLaTeXLayout("subsection"))
3683                 biblioModule->bibunitsCO->addItem(qt_("per subsection"), toqstr("subsection"));
3684         biblioModule->bibunitsCO->addItem(qt_("per child document"), toqstr("child"));
3685
3686         int const mbpos = biblioModule->bibunitsCO->findData(toqstr(bp_.multibib));
3687         if (mbpos != -1)
3688                 biblioModule->bibunitsCO->setCurrentIndex(mbpos);
3689         else
3690                 biblioModule->bibunitsCO->setCurrentIndex(0);
3691
3692         updateEngineDependends();
3693
3694         if (isBiblatex()) {
3695                 updateDefaultBiblio(bp_.biblatex_bibstyle, "bbx");
3696                 updateDefaultBiblio(bp_.biblatex_citestyle, "cbx");
3697         } else
3698                 updateDefaultBiblio(bp_.defaultBiblioStyle());
3699
3700         biblioModule->citePackageOptionsLE->setText(toqstr(bp_.biblio_opts));
3701
3702         string command;
3703         string options =
3704                 split(bp_.bibtex_command, command, ' ');
3705
3706         int const bpos = biblioModule->bibtexCO->findData(toqstr(command));
3707         if (bpos != -1) {
3708                 biblioModule->bibtexCO->setCurrentIndex(bpos);
3709                 biblioModule->bibtexOptionsLE->setText(toqstr(options).trimmed());
3710         } else {
3711                 // We reset to default if we do not know the specified compiler
3712                 // This is for security reasons
3713                 biblioModule->bibtexCO->setCurrentIndex(
3714                         biblioModule->bibtexCO->findData(toqstr("default")));
3715                 biblioModule->bibtexOptionsLE->clear();
3716         }
3717         biblioModule->bibtexOptionsLE->setEnabled(
3718                 biblioModule->bibtexCO->currentIndex() != 0);
3719
3720         biblioChanged_ = false;
3721
3722         // indices
3723         // We may be called when there is no Buffer, e.g., when
3724         // the last view has just been closed.
3725         bool const isReadOnly = isBufferAvailable() ? buffer().isReadonly() : false;
3726         indicesModule->update(bp_, isReadOnly);
3727
3728         // language & quotes
3729         int const pos = langModule->languageCO->findData(toqstr(
3730                 bp_.language->lang()));
3731         langModule->languageCO->setCurrentIndex(pos);
3732
3733         updateQuoteStyles();
3734
3735         langModule->quoteStyleCO->setCurrentIndex(
3736                 langModule->quoteStyleCO->findData(bp_.quotes_style));
3737         langModule->dynamicQuotesCB->setChecked(bp_.dynamic_quotes);
3738
3739         QString inputenc = toqstr(bp_.inputenc);
3740         bool plain = false;
3741         if (inputenc.endsWith("-plain")) {
3742                 inputenc = inputenc.left(inputenc.lastIndexOf("-plain"));
3743                 plain = true;
3744         }
3745         langModule->noInputencCB->setChecked(plain);
3746         int p = langModule->encodingCO->findData(inputenc);
3747         if (p != -1)
3748                 langModule->encodingCO->setCurrentIndex(p);
3749         else {
3750                 langModule->encodingCO->setCurrentIndex(
3751                           langModule->encodingCO->findData("custom"));
3752                 p = langModule->customEncodingCO->findData(inputenc);
3753                 if (p != -1)
3754                         langModule->customEncodingCO->setCurrentIndex(p);
3755                 else
3756                         langModule->encodingCO->setCurrentIndex(0);
3757         }
3758
3759         p = langModule->languagePackageCO->findData(toqstr(bp_.lang_package));
3760         if (p == -1) {
3761                 langModule->languagePackageCO->setCurrentIndex(
3762                           langModule->languagePackageCO->findData("custom"));
3763                 langModule->languagePackageLE->setText(toqstr(bp_.lang_package));
3764         } else {
3765                 langModule->languagePackageCO->setCurrentIndex(p);
3766                 langModule->languagePackageLE->clear();
3767         }
3768
3769         //color
3770         if (bp_.isfontcolor) {
3771                 colorModule->fontColorPB->setStyleSheet(
3772                         colorButtonStyleSheet(rgb2qcolor(bp_.fontcolor)));
3773         }
3774         set_fontcolor = bp_.fontcolor;
3775         is_fontcolor = bp_.isfontcolor;
3776
3777         colorModule->noteFontColorPB->setStyleSheet(
3778                 colorButtonStyleSheet(rgb2qcolor(bp_.notefontcolor)));
3779         set_notefontcolor = bp_.notefontcolor;
3780
3781         if (bp_.isbackgroundcolor) {
3782                 colorModule->backgroundPB->setStyleSheet(
3783                         colorButtonStyleSheet(rgb2qcolor(bp_.backgroundcolor)));
3784         }
3785         set_backgroundcolor = bp_.backgroundcolor;
3786         is_backgroundcolor = bp_.isbackgroundcolor;
3787
3788         colorModule->boxBackgroundPB->setStyleSheet(
3789                 colorButtonStyleSheet(rgb2qcolor(bp_.boxbgcolor)));
3790         set_boxbgcolor = bp_.boxbgcolor;
3791
3792         // numbering
3793         int const min_toclevel = documentClass().min_toclevel();
3794         int const max_toclevel = documentClass().max_toclevel();
3795         if (documentClass().hasTocLevels()) {
3796                 numberingModule->setEnabled(true);
3797                 numberingModule->depthSL->setMinimum(min_toclevel - 1);
3798                 numberingModule->depthSL->setMaximum(max_toclevel);
3799                 numberingModule->depthSL->setValue(bp_.secnumdepth);
3800                 numberingModule->tocSL->setMaximum(min_toclevel - 1);
3801                 numberingModule->tocSL->setMaximum(max_toclevel);
3802                 numberingModule->tocSL->setValue(bp_.tocdepth);
3803                 updateNumbering();
3804         } else {
3805                 numberingModule->setEnabled(false);
3806                 numberingModule->tocTW->clear();
3807         }
3808
3809         // bullets
3810         bulletsModule->setBullet(0, bp_.user_defined_bullet(0));
3811         bulletsModule->setBullet(1, bp_.user_defined_bullet(1));
3812         bulletsModule->setBullet(2, bp_.user_defined_bullet(2));
3813         bulletsModule->setBullet(3, bp_.user_defined_bullet(3));
3814         bulletsModule->init();
3815
3816         // packages
3817         int nitem = findToken(tex_graphics, bp_.graphics_driver);
3818         if (nitem >= 0)
3819                 latexModule->psdriverCO->setCurrentIndex(nitem);
3820         updateModuleInfo();
3821
3822         // math
3823         mathsModule->MathIndentCB->setChecked(bp_.is_math_indent);
3824         if (bp_.is_math_indent) {
3825                 Length const mathindent = bp_.getMathIndent();
3826                 int indent = 0;
3827                 if (!mathindent.empty()) {
3828                         lengthToWidgets(mathsModule->MathIndentLE,
3829                                         mathsModule->MathIndentLengthCO,
3830                                         mathindent, default_unit);
3831                         indent = 1;
3832                 }
3833                 mathsModule->MathIndentCO->setCurrentIndex(indent);
3834                 enableMathIndent(indent);
3835         }
3836         switch(bp_.math_numbering_side) {
3837         case BufferParams::LEFT:
3838                 mathsModule->MathNumberingPosCO->setCurrentIndex(0);
3839                 break;
3840         case BufferParams::DEFAULT:
3841                 mathsModule->MathNumberingPosCO->setCurrentIndex(1);
3842                 break;
3843         case BufferParams::RIGHT:
3844                 mathsModule->MathNumberingPosCO->setCurrentIndex(2);
3845         }
3846
3847         map<string, string> const & packages = BufferParams::auto_packages();
3848         for (map<string, string>::const_iterator it = packages.begin();
3849              it != packages.end(); ++it) {
3850                 QTableWidgetItem * item = mathsModule->packagesTW->findItems(toqstr(it->first), Qt::MatchExactly)[0];
3851                 if (!item)
3852                         continue;
3853                 int row = mathsModule->packagesTW->row(item);
3854                 switch (bp_.use_package(it->first)) {
3855                         case BufferParams::package_off: {
3856                                 QRadioButton * rb =
3857                                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 3)->layout()->itemAt(0)->widget();
3858                                 rb->setChecked(true);
3859                                 break;
3860                         }
3861                         case BufferParams::package_on: {
3862                                 QRadioButton * rb =
3863                                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 2)->layout()->itemAt(0)->widget();
3864                                 rb->setChecked(true);
3865                                 break;
3866                         }
3867                         case BufferParams::package_auto: {
3868                                 QRadioButton * rb =
3869                                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 1)->layout()->itemAt(0)->widget();
3870                                 rb->setChecked(true);
3871                                 break;
3872                         }
3873                 }
3874         }
3875
3876         switch (bp_.spacing().getSpace()) {
3877                 case Spacing::Other: nitem = 3; break;
3878                 case Spacing::Double: nitem = 2; break;
3879                 case Spacing::Onehalf: nitem = 1; break;
3880                 case Spacing::Default: case Spacing::Single: nitem = 0; break;
3881         }
3882
3883         // text layout
3884         string const & layoutID = bp_.baseClassID();
3885         setLayoutComboByIDString(layoutID);
3886
3887         updatePagestyle(documentClass().opt_pagestyle(),
3888                                  bp_.pagestyle);
3889
3890         textLayoutModule->lspacingCO->setCurrentIndex(nitem);
3891         if (bp_.spacing().getSpace() == Spacing::Other) {
3892                 doubleToWidget(textLayoutModule->lspacingLE,
3893                         bp_.spacing().getValueAsString());
3894         }
3895         setLSpacing(nitem);
3896         int ts = textLayoutModule->tableStyleCO->findData(toqstr(bp_.tablestyle));
3897         if (ts != -1)
3898                 textLayoutModule->tableStyleCO->setCurrentIndex(ts);
3899
3900         if (bp_.paragraph_separation == BufferParams::ParagraphIndentSeparation) {
3901                 textLayoutModule->indentRB->setChecked(true);
3902                 string parindent = bp_.getParIndent().asString();
3903                 int indent = 0;
3904                 if (!parindent.empty()) {
3905                         lengthToWidgets(textLayoutModule->indentLE,
3906                                         textLayoutModule->indentLengthCO,
3907                                         parindent, default_unit);
3908                         indent = 1;
3909                 }
3910                 textLayoutModule->indentCO->setCurrentIndex(indent);
3911                 setIndent(indent);
3912         } else {
3913                 textLayoutModule->skipRB->setChecked(true);
3914                 int skip = 0;
3915                 switch (bp_.getDefSkip().kind()) {
3916                 case VSpace::SMALLSKIP:
3917                         skip = 0;
3918                         break;
3919                 case VSpace::MEDSKIP:
3920                         skip = 1;
3921                         break;
3922                 case VSpace::BIGSKIP:
3923                         skip = 2;
3924                         break;
3925                 case VSpace::LENGTH:
3926                         {
3927                         skip = 3;
3928                         string const length = bp_.getDefSkip().asLyXCommand();
3929                         lengthToWidgets(textLayoutModule->skipLE,
3930                                 textLayoutModule->skipLengthCO,
3931                                 length, default_unit);
3932                         break;
3933                         }
3934                 default:
3935                         skip = 0;
3936                         break;
3937                 }
3938                 textLayoutModule->skipCO->setCurrentIndex(skip);
3939                 setSkip(skip);
3940         }
3941
3942         textLayoutModule->twoColumnCB->setChecked(
3943                 bp_.columns == 2);
3944         textLayoutModule->justCB->setChecked(bp_.justification);
3945
3946         if (!bp_.options.empty()) {
3947                 latexModule->optionsLE->setText(
3948                         toqstr(bp_.options));
3949         } else {
3950                 latexModule->optionsLE->setText(QString());
3951         }
3952
3953         // latex
3954         latexModule->defaultOptionsCB->setChecked(
3955                         bp_.use_default_options);
3956         updateSelectedModules();
3957         selectionManager->updateProvidedModules(
3958                         bp_.baseClass()->providedModules());
3959         selectionManager->updateExcludedModules(
3960                         bp_.baseClass()->excludedModules());
3961
3962         if (!documentClass().options().empty()) {
3963                 latexModule->defaultOptionsLE->setText(
3964                         toqstr(documentClass().options()));
3965         } else {
3966                 latexModule->defaultOptionsLE->setText(
3967                         toqstr(_("[No options predefined]")));
3968         }
3969
3970         latexModule->defaultOptionsLE->setEnabled(
3971                 bp_.use_default_options
3972                 && !documentClass().options().empty());
3973
3974         latexModule->defaultOptionsCB->setEnabled(
3975                 !documentClass().options().empty());
3976
3977         if (!bp_.master.empty()) {
3978                 latexModule->childDocGB->setChecked(true);
3979                 latexModule->childDocLE->setText(
3980                         toqstr(bp_.master));
3981         } else {
3982                 latexModule->childDocLE->setText(QString());
3983                 latexModule->childDocGB->setChecked(false);
3984         }
3985
3986         // Master/Child
3987         if (!bufferview() || !buffer().hasChildren()) {
3988                 masterChildModule->childrenTW->clear();
3989                 includeonlys_.clear();
3990                 docPS->showPanel("Child Documents", false);
3991                 if (docPS->isCurrentPanel("Child Documents"))
3992                         docPS->setCurrentPanel("Document Class");
3993         } else {
3994                 docPS->showPanel("Child Documents", true);
3995                 masterChildModule->setEnabled(true);
3996                 includeonlys_ = bp_.getIncludedChildren();
3997                 updateIncludeonlys();
3998         }
3999         masterChildModule->maintainAuxCB->setChecked(
4000                 bp_.maintain_unincluded_children);
4001
4002         // Float Settings
4003         floatModule->setPlacement(bp_.float_placement);
4004         floatModule->setAlignment(bp_.float_alignment);
4005
4006         // ListingsSettings
4007         // break listings_params to multiple lines
4008         string lstparams =
4009                 InsetListingsParams(bp_.listings_params).separatedParams();
4010         listingsModule->listingsED->setPlainText(toqstr(lstparams));
4011         int nn = findToken(lst_packages, bp_.use_minted ? "Minted" : "Listings");
4012         if (nn >= 0)
4013                 listingsModule->packageCO->setCurrentIndex(nn);
4014
4015         // Fonts
4016         // some languages only work with Polyglossia (which requires non-TeX fonts)
4017         Language const * lang = lyx::languages.getLanguage(
4018                 fromqstr(langModule->languageCO->itemData(
4019                         langModule->languageCO->currentIndex()).toString()));
4020         bool const need_fontspec =
4021                 lang->babel().empty() && !lang->polyglossia().empty();
4022         bool const os_fonts_available =
4023                 bp_.baseClass()->outputType() == lyx::LATEX
4024                 && LaTeXFeatures::isAvailable("fontspec");
4025         fontModule->osFontsCB->setEnabled(os_fonts_available && !need_fontspec);
4026         fontModule->osFontsCB->setChecked(
4027                 (os_fonts_available && bp_.useNonTeXFonts) || need_fontspec);
4028         updateFontsize(documentClass().opt_fontsize(),
4029                         bp_.fontsize);
4030
4031         QString font = toqstr(bp_.fontsRoman());
4032         int rpos = fontModule->fontsRomanCO->findData(font);
4033         if (rpos == -1) {
4034                 rpos = fontModule->fontsRomanCO->count();
4035                 fontModule->fontsRomanCO->addItem(font + qt_(" (not installed)"), font);
4036         }
4037         fontModule->fontsRomanCO->setCurrentIndex(rpos);
4038         fontModule->font_roman = toqstr(bp_.fonts_roman[!bp_.useNonTeXFonts]);
4039
4040         font = toqstr(bp_.fontsSans());
4041         int spos = fontModule->fontsSansCO->findData(font);
4042         if (spos == -1) {
4043                 spos = fontModule->fontsSansCO->count();
4044                 fontModule->fontsSansCO->addItem(font + qt_(" (not installed)"), font);
4045         }
4046         fontModule->fontsSansCO->setCurrentIndex(spos);
4047         fontModule->font_sans = toqstr(bp_.fonts_sans[!bp_.useNonTeXFonts]);
4048
4049         font = toqstr(bp_.fontsTypewriter());
4050         int tpos = fontModule->fontsTypewriterCO->findData(font);
4051         if (tpos == -1) {
4052                 tpos = fontModule->fontsTypewriterCO->count();
4053                 fontModule->fontsTypewriterCO->addItem(font + qt_(" (not installed)"), font);
4054         }
4055         fontModule->fontsTypewriterCO->setCurrentIndex(tpos);
4056         fontModule->font_typewriter = toqstr(bp_.fonts_typewriter[!bp_.useNonTeXFonts]);
4057
4058         font = toqstr(bp_.fontsMath());
4059         int mpos = fontModule->fontsMathCO->findData(font);
4060         if (mpos == -1) {
4061                 mpos = fontModule->fontsMathCO->count();
4062                 fontModule->fontsMathCO->addItem(font + qt_(" (not installed)"), font);
4063         }
4064         fontModule->fontsMathCO->setCurrentIndex(mpos);
4065         fontModule->font_math = toqstr(bp_.fonts_math[!bp_.useNonTeXFonts]);
4066
4067         if (bp_.useNonTeXFonts && os_fonts_available) {
4068                 fontModule->fontencLA->setEnabled(false);
4069                 fontModule->fontencCO->setEnabled(false);
4070                 fontModule->fontencLE->setEnabled(false);
4071         } else {
4072                 fontModule->fontencLA->setEnabled(true);
4073                 fontModule->fontencCO->setEnabled(true);
4074                 fontModule->fontencLE->setEnabled(true);
4075                 romanChanged(rpos);
4076                 sansChanged(spos);
4077                 ttChanged(tpos);
4078         }
4079
4080         if (!bp_.fonts_cjk.empty())
4081                 fontModule->cjkFontLE->setText(
4082                         toqstr(bp_.fonts_cjk));
4083         else
4084                 fontModule->cjkFontLE->setText(QString());
4085
4086         fontModule->microtypeCB->setChecked(bp_.use_microtype);
4087         fontModule->dashesCB->setChecked(!bp_.use_dash_ligatures);
4088
4089         fontModule->fontScCB->setChecked(bp_.fonts_expert_sc);
4090         fontModule->fontOsfCB->setChecked(bp_.fonts_old_figures);
4091         fontModule->scaleSansSB->setValue(bp_.fontsSansScale());
4092         fontModule->font_sf_scale = bp_.fonts_sans_scale[!bp_.useNonTeXFonts];
4093         fontModule->scaleTypewriterSB->setValue(bp_.fontsTypewriterScale());
4094         fontModule->font_tt_scale = bp_.fonts_typewriter_scale[!bp_.useNonTeXFonts];
4095
4096         nn = findToken(GuiDocument::fontfamilies, bp_.fonts_default_family);
4097         if (nn >= 0)
4098                 fontModule->fontsDefaultCO->setCurrentIndex(nn);
4099
4100         if (bp_.fontenc == "auto" || bp_.fontenc == "default") {
4101                 fontModule->fontencCO->setCurrentIndex(
4102                         fontModule->fontencCO->findData(toqstr(bp_.fontenc)));
4103                 fontModule->fontencLE->setEnabled(false);
4104         } else {
4105                 fontModule->fontencCO->setCurrentIndex(
4106                                         fontModule->fontencCO->findData("custom"));
4107                 fontModule->fontencLE->setText(toqstr(bp_.fontenc));
4108         }
4109
4110         // Formats
4111         // This must be set _after_ fonts since updateDefaultFormat()
4112         // checks osFontsCB settings.
4113         // update combobox with formats
4114         updateDefaultFormat();
4115         int index = outputModule->defaultFormatCO->findData(toqstr(
4116                 bp_.default_output_format));
4117         // set to default if format is not found
4118         if (index == -1)
4119                 index = 0;
4120         outputModule->defaultFormatCO->setCurrentIndex(index);
4121
4122         outputModule->shellescapeCB->setChecked(bp_.shell_escape);
4123         outputModule->outputsyncCB->setChecked(bp_.output_sync);
4124         outputModule->synccustomCB->setEditText(toqstr(bp_.output_sync_macro));
4125
4126         outputModule->mathimgSB->setValue(bp_.html_math_img_scale);
4127         outputModule->mathoutCB->setCurrentIndex(bp_.html_math_output);
4128         outputModule->strictCB->setChecked(bp_.html_be_strict);
4129         outputModule->cssCB->setChecked(bp_.html_css_as_file);
4130
4131         outputModule->saveTransientPropertiesCB
4132                 ->setChecked(bp_.save_transient_properties);
4133
4134         // paper
4135         bool const extern_geometry =
4136                 documentClass().provides("geometry");
4137         int const psize = bp_.papersize;
4138         pageLayoutModule->papersizeCO->setCurrentIndex(psize);
4139         setCustomPapersize(!extern_geometry && psize == 1);
4140         pageLayoutModule->papersizeCO->setEnabled(!extern_geometry);
4141
4142         bool const landscape =
4143                 bp_.orientation == ORIENTATION_LANDSCAPE;
4144         pageLayoutModule->landscapeRB->setChecked(landscape);
4145         pageLayoutModule->portraitRB->setChecked(!landscape);
4146         pageLayoutModule->landscapeRB->setEnabled(!extern_geometry);
4147         pageLayoutModule->portraitRB->setEnabled(!extern_geometry);
4148
4149         pageLayoutModule->facingPagesCB->setChecked(
4150                 bp_.sides == TwoSides);
4151
4152         lengthToWidgets(pageLayoutModule->paperwidthLE,
4153                 pageLayoutModule->paperwidthUnitCO, bp_.paperwidth, default_unit);
4154         lengthToWidgets(pageLayoutModule->paperheightLE,
4155                 pageLayoutModule->paperheightUnitCO, bp_.paperheight, default_unit);
4156
4157         // margins
4158         Ui::MarginsUi * m = marginsModule;
4159
4160         setMargins();
4161
4162         lengthToWidgets(m->topLE, m->topUnit,
4163                 bp_.topmargin, default_unit);
4164
4165         lengthToWidgets(m->bottomLE, m->bottomUnit,
4166                 bp_.bottommargin, default_unit);
4167
4168         lengthToWidgets(m->innerLE, m->innerUnit,
4169                 bp_.leftmargin, default_unit);
4170
4171         lengthToWidgets(m->outerLE, m->outerUnit,
4172                 bp_.rightmargin, default_unit);
4173
4174         lengthToWidgets(m->headheightLE, m->headheightUnit,
4175                 bp_.headheight, default_unit);
4176
4177         lengthToWidgets(m->headsepLE, m->headsepUnit,
4178                 bp_.headsep, default_unit);
4179
4180         lengthToWidgets(m->footskipLE, m->footskipUnit,
4181                 bp_.footskip, default_unit);
4182
4183         lengthToWidgets(m->columnsepLE, m->columnsepUnit,
4184                 bp_.columnsep, default_unit);
4185
4186         // branches
4187         updateUnknownBranches();
4188         branchesModule->update(bp_);
4189
4190         // PDF support
4191         PDFOptions const & pdf = bp_.pdfoptions();
4192         pdfSupportModule->use_hyperrefGB->setChecked(pdf.use_hyperref);
4193         if (bp_.documentClass().provides("hyperref"))
4194                 pdfSupportModule->use_hyperrefGB->setTitle(qt_("C&ustomize Hyperref Options"));
4195         else
4196                 pdfSupportModule->use_hyperrefGB->setTitle(qt_("&Use Hyperref Support"));
4197         pdfSupportModule->titleLE->setText(toqstr(pdf.title));
4198         pdfSupportModule->authorLE->setText(toqstr(pdf.author));
4199         pdfSupportModule->subjectLE->setText(toqstr(pdf.subject));
4200         pdfSupportModule->keywordsLE->setText(toqstr(pdf.keywords));
4201
4202         pdfSupportModule->bookmarksGB->setChecked(pdf.bookmarks);
4203         pdfSupportModule->bookmarksnumberedCB->setChecked(pdf.bookmarksnumbered);
4204         pdfSupportModule->bookmarksopenGB->setChecked(pdf.bookmarksopen);
4205
4206         pdfSupportModule->bookmarksopenlevelSB->setValue(pdf.bookmarksopenlevel);
4207
4208         pdfSupportModule->breaklinksCB->setChecked(pdf.breaklinks);
4209         pdfSupportModule->pdfborderCB->setChecked(pdf.pdfborder);
4210         pdfSupportModule->pdfusetitleCB->setChecked(pdf.pdfusetitle);
4211         pdfSupportModule->colorlinksCB->setChecked(pdf.colorlinks);
4212
4213         nn = findToken(backref_opts, pdf.backref);
4214         if (nn >= 0)
4215                 pdfSupportModule->backrefCO->setCurrentIndex(nn);
4216
4217         pdfSupportModule->fullscreenCB->setChecked
4218                 (pdf.pagemode == pdf.pagemode_fullscreen);
4219
4220         pdfSupportModule->optionsLE->setText(
4221                 toqstr(pdf.quoted_options));
4222
4223         // Make sure that the bc is in the INITIAL state
4224         if (bc().policy().buttonStatus(ButtonPolicy::RESTORE))
4225                 bc().restore();
4226
4227         // clear changed branches cache
4228         changedBranches_.clear();
4229
4230         // reset trackers
4231         nonModuleChanged_ = false;
4232         shellescapeChanged_ = false;
4233 }
4234
4235
4236 void GuiDocument::saveDocDefault()
4237 {
4238         // we have to apply the params first
4239         applyView();
4240         saveAsDefault();
4241 }
4242
4243
4244 void GuiDocument::updateAvailableModules()
4245 {
4246         modules_av_model_.clear();
4247         list<modInfoStruct> modInfoList = getModuleInfo();
4248         // Sort names according to the locale
4249         modInfoList.sort([](modInfoStruct const & a, modInfoStruct const & b) {
4250                         return 0 < b.name.localeAwareCompare(a.name);
4251                 });
4252         QIcon user_icon(getPixmap("images/", "lyxfiles-user", "svgz,png"));
4253         QIcon system_icon(getPixmap("images/", "lyxfiles-system", "svgz,png"));
4254         int i = 0;
4255         QFont catfont;
4256         catfont.setBold(true);
4257         QBrush unavbrush;
4258         unavbrush.setColor(Qt::gray);
4259         for (modInfoStruct const & m : modInfoList) {
4260                 QStandardItem * item = new QStandardItem();
4261                 QStandardItem * catItem = new QStandardItem();
4262                 QString const catname = m.category;
4263                 QList<QStandardItem *> fcats = modules_av_model_.findItems(catname, Qt::MatchExactly);
4264                 if (!fcats.empty())
4265                         catItem = fcats.first();
4266                 else {
4267                         catItem->setText(catname);
4268                         catItem->setFont(catfont);
4269                         modules_av_model_.insertRow(i, catItem);
4270                         ++i;
4271                 }
4272                 item->setEditable(false);
4273                 catItem->setEditable(false);
4274                 item->setData(m.name, Qt::DisplayRole);
4275                 if (m.missingreqs)
4276                         item->setForeground(unavbrush);
4277                 item->setData(toqstr(m.id), Qt::UserRole);
4278                 item->setData(m.description, Qt::ToolTipRole);
4279                 if (m.local)
4280                         item->setIcon(user_icon);
4281                 else
4282                         item->setIcon(system_icon);
4283                 catItem->appendRow(item);
4284         }
4285         modules_av_model_.sort(0);
4286 }
4287
4288
4289 void GuiDocument::updateSelectedModules()
4290 {
4291         modules_sel_model_.clear();
4292         list<modInfoStruct> const selModList = getSelectedModules();
4293         int i = 0;
4294         for (modInfoStruct const & m : selModList) {
4295                 modules_sel_model_.insertRow(i, m.name, m.id, m.description);
4296                 ++i;
4297         }
4298 }
4299
4300
4301 void GuiDocument::updateIncludeonlys()
4302 {
4303         masterChildModule->childrenTW->clear();
4304         QString const no = qt_("No");
4305         QString const yes = qt_("Yes");
4306
4307         if (includeonlys_.empty()) {
4308                 masterChildModule->includeallRB->setChecked(true);
4309                 masterChildModule->childrenTW->setEnabled(false);
4310                 masterChildModule->maintainAuxCB->setEnabled(false);
4311         } else {
4312                 masterChildModule->includeonlyRB->setChecked(true);
4313                 masterChildModule->childrenTW->setEnabled(true);
4314                 masterChildModule->maintainAuxCB->setEnabled(true);
4315         }
4316         ListOfBuffers children = buffer().getChildren();
4317         ListOfBuffers::const_iterator it  = children.begin();
4318         ListOfBuffers::const_iterator end = children.end();
4319         bool has_unincluded = false;
4320         bool all_unincluded = true;
4321         for (; it != end; ++it) {
4322                 QTreeWidgetItem * item = new QTreeWidgetItem(masterChildModule->childrenTW);
4323                 // FIXME Unicode
4324                 string const name =
4325                         to_utf8(makeRelPath(from_utf8((*it)->fileName().absFileName()),
4326                                                         from_utf8(buffer().filePath())));
4327                 item->setText(0, toqstr(name));
4328                 item->setText(1, isChildIncluded(name) ? yes : no);
4329                 if (!isChildIncluded(name))
4330                         has_unincluded = true;
4331                 else
4332                         all_unincluded = false;
4333         }
4334         // Both if all childs are included and if none is included
4335         // is equal to "include all" (i.e., omit \includeonly).
4336         // Thus, reset the GUI.
4337         if (!has_unincluded || all_unincluded) {
4338                 masterChildModule->includeallRB->setChecked(true);
4339                 masterChildModule->childrenTW->setEnabled(false);
4340                 includeonlys_.clear();
4341         }
4342         // If all are included, we need to update again.
4343         if (!has_unincluded)
4344                 updateIncludeonlys();
4345 }
4346
4347
4348 bool GuiDocument::isBiblatex() const
4349 {
4350         QString const engine =
4351                 biblioModule->citeEngineCO->itemData(
4352                                 biblioModule->citeEngineCO->currentIndex()).toString();
4353
4354         // this can happen if the cite engine is unknown, which can happen
4355         // if one is using a file that came from someone else, etc. in that
4356         // case, we crash if we proceed.
4357         if (engine.isEmpty())
4358             return false;
4359
4360         return theCiteEnginesList[fromqstr(engine)]->getCiteFramework() == "biblatex";
4361 }
4362
4363
4364 void GuiDocument::updateDefaultBiblio(string const & style,
4365                                       string const & which)
4366 {
4367         QString const bibstyle = toqstr(style);
4368         biblioModule->defaultBiblioCO->clear();
4369
4370         int item_nr = -1;
4371
4372         if (isBiblatex()) {
4373                 if (which != "cbx") {
4374                         // First the bbx styles
4375                         biblioModule->biblatexBbxCO->clear();
4376                         QStringList str = texFileList("bbxFiles.lst");
4377                         // test whether we have a valid list, otherwise run rescan
4378                         if (str.isEmpty()) {
4379                                 rescanTexStyles("bbx");
4380                                 str = texFileList("bbxFiles.lst");
4381                         }
4382                         for (int i = 0; i != str.size(); ++i)
4383                                 str[i] = onlyFileName(str[i]);
4384                         // sort on filename only (no path)
4385                         str.sort();
4386
4387                         for (int i = 0; i != str.count(); ++i) {
4388                                 QString item = changeExtension(str[i], "");
4389                                 if (item == bibstyle)
4390                                         item_nr = i;
4391                                 biblioModule->biblatexBbxCO->addItem(item);
4392                         }
4393
4394                         if (item_nr == -1 && !bibstyle.isEmpty()) {
4395                                 biblioModule->biblatexBbxCO->addItem(bibstyle);
4396                                 item_nr = biblioModule->biblatexBbxCO->count() - 1;
4397                         }
4398
4399                         if (item_nr != -1)
4400                                 biblioModule->biblatexBbxCO->setCurrentIndex(item_nr);
4401                         else
4402                                 biblioModule->biblatexBbxCO->clearEditText();
4403                 }
4404
4405                 if (which != "bbx") {
4406                         // now the cbx styles
4407                         biblioModule->biblatexCbxCO->clear();
4408                         QStringList str = texFileList("cbxFiles.lst");
4409                         // test whether we have a valid list, otherwise run rescan
4410                         if (str.isEmpty()) {
4411                                 rescanTexStyles("cbx");
4412                                 str = texFileList("cbxFiles.lst");
4413                         }
4414                         for (int i = 0; i != str.size(); ++i)
4415                                 str[i] = onlyFileName(str[i]);
4416                         // sort on filename only (no path)
4417                         str.sort();
4418
4419                         for (int i = 0; i != str.count(); ++i) {
4420                                 QString item = changeExtension(str[i], "");
4421                                 if (item == bibstyle)
4422                                         item_nr = i;
4423                                 biblioModule->biblatexCbxCO->addItem(item);
4424                         }
4425
4426                         if (item_nr == -1 && !bibstyle.isEmpty()) {
4427                                 biblioModule->biblatexCbxCO->addItem(bibstyle);
4428                                 item_nr = biblioModule->biblatexCbxCO->count() - 1;
4429                         }
4430
4431                         if (item_nr != -1)
4432                                 biblioModule->biblatexCbxCO->setCurrentIndex(item_nr);
4433                         else
4434                                 biblioModule->biblatexCbxCO->clearEditText();
4435                 }
4436         } else {// BibTeX
4437                 biblioModule->biblatexBbxCO->clear();
4438                 biblioModule->biblatexCbxCO->clear();
4439                 QStringList str = texFileList("bstFiles.lst");
4440                 // test whether we have a valid list, otherwise run rescan
4441                 if (str.isEmpty()) {
4442                         rescanTexStyles("bst");
4443                         str = texFileList("bstFiles.lst");
4444                 }
4445                 for (int i = 0; i != str.size(); ++i)
4446                         str[i] = onlyFileName(str[i]);
4447                 // sort on filename only (no path)
4448                 str.sort();
4449
4450                 for (int i = 0; i != str.count(); ++i) {
4451                         QString item = changeExtension(str[i], "");
4452                         if (item == bibstyle)
4453                                 item_nr = i;
4454                         biblioModule->defaultBiblioCO->addItem(item);
4455                 }
4456
4457                 if (item_nr == -1 && !bibstyle.isEmpty()) {
4458                         biblioModule->defaultBiblioCO->addItem(bibstyle);
4459                         item_nr = biblioModule->defaultBiblioCO->count() - 1;
4460                 }
4461
4462                 if (item_nr != -1)
4463                         biblioModule->defaultBiblioCO->setCurrentIndex(item_nr);
4464                 else
4465                         biblioModule->defaultBiblioCO->clearEditText();
4466         }
4467
4468         updateResetDefaultBiblio();
4469 }
4470
4471
4472 void GuiDocument::updateResetDefaultBiblio()
4473 {
4474         QString const engine =
4475                 biblioModule->citeEngineCO->itemData(
4476                                 biblioModule->citeEngineCO->currentIndex()).toString();
4477         CiteEngineType const cet =
4478                 CiteEngineType(biblioModule->citeStyleCO->itemData(
4479                                                           biblioModule->citeStyleCO->currentIndex()).toInt());
4480
4481         string const defbib = theCiteEnginesList[fromqstr(engine)]->getDefaultBiblio(cet);
4482         if (isBiblatex()) {
4483                 QString const bbx = biblioModule->biblatexBbxCO->currentText();
4484                 QString const cbx = biblioModule->biblatexCbxCO->currentText();
4485                 biblioModule->resetCbxPB->setEnabled(defbib != fromqstr(cbx));
4486                 biblioModule->resetBbxPB->setEnabled(defbib != fromqstr(bbx));
4487                 biblioModule->matchBbxPB->setEnabled(bbx != cbx && !cbx.isEmpty()
4488                         && biblioModule->biblatexBbxCO->findText(cbx) != -1);
4489         } else
4490                 biblioModule->resetDefaultBiblioPB->setEnabled(
4491                         defbib != fromqstr(biblioModule->defaultBiblioCO->currentText()));
4492 }
4493
4494
4495 void GuiDocument::matchBiblatexStyles()
4496 {
4497         updateDefaultBiblio(fromqstr(biblioModule->biblatexCbxCO->currentText()), "bbx");
4498         biblioChanged();
4499 }
4500
4501
4502 void GuiDocument::updateContents()
4503 {
4504         // Nothing to do here as the document settings is not cursor dependant.
4505         return;
4506 }
4507
4508
4509 void GuiDocument::useClassDefaults()
4510 {
4511         if (buttonBox->button(QDialogButtonBox::Apply)->isEnabled()) {
4512                 int const ret = Alert::prompt(_("Unapplied changes"),
4513                                 _("Some changes in the dialog were not yet applied.\n"
4514                                   "If you do not apply now, they will be lost after this action."),
4515                                 1, 1, _("&Apply"), _("&Dismiss"));
4516                 if (ret == 0)
4517                         applyView();
4518         }
4519
4520         int idx = latexModule->classCO->currentIndex();
4521         string const classname = fromqstr(latexModule->classCO->getData(idx));
4522         if (!bp_.setBaseClass(classname, buffer().layoutPos())) {
4523                 Alert::error(_("Error"), _("Unable to set document class."));
4524                 return;
4525         }
4526         bp_.useClassDefaults();
4527         paramsToDialog();
4528         changed();
4529 }
4530
4531
4532 void GuiDocument::setLayoutComboByIDString(string const & idString)
4533 {
4534         if (!latexModule->classCO->set(toqstr(idString)))
4535                 Alert::warning(_("Can't set layout!"),
4536                         bformat(_("Unable to set layout for ID: %1$s"), from_utf8(idString)));
4537 }
4538
4539
4540 bool GuiDocument::isValid()
4541 {
4542         return
4543                 validateListingsParameters().isEmpty() &&
4544                 localLayout->isValid() &&
4545                 !localLayout->editing() &&
4546                 !preambleModule->editing() &&
4547                 (
4548                         // if we're asking for skips between paragraphs
4549                         !textLayoutModule->skipRB->isChecked() ||
4550                         // then either we haven't chosen custom
4551                         textLayoutModule->skipCO->currentIndex() != 3 ||
4552                         // or else a length has been given
4553                         !textLayoutModule->skipLE->text().isEmpty()
4554                 ) &&
4555                 (
4556                         // if we're asking for indentation
4557                         !textLayoutModule->indentRB->isChecked() ||
4558                         // then either we haven't chosen custom
4559                         textLayoutModule->indentCO->currentIndex() != 1 ||
4560                         // or else a length has been given
4561                         !textLayoutModule->indentLE->text().isEmpty()
4562                 ) &&
4563                 (
4564                         // if we're asking for math indentation
4565                         !mathsModule->MathIndentCB->isChecked() ||
4566                         // then either we haven't chosen custom
4567                         mathsModule->MathIndentCO->currentIndex() != 1 ||
4568                         // or else a length has been given
4569                         !mathsModule->MathIndentLE->text().isEmpty()
4570                 );
4571 }
4572
4573
4574 char const * const GuiDocument::fontfamilies[5] = {
4575         "default", "rmdefault", "sfdefault", "ttdefault", ""
4576 };
4577
4578
4579 char const * GuiDocument::fontfamilies_gui[5] = {
4580         N_("Default"), N_("Roman"), N_("Sans Serif"), N_("Typewriter"), ""
4581 };
4582
4583
4584 bool GuiDocument::initialiseParams(string const &)
4585 {
4586         BufferView const * view = bufferview();
4587         if (!view) {
4588                 bp_ = BufferParams();
4589                 paramsToDialog();
4590                 return true;
4591         }
4592         bp_ = view->buffer().params();
4593         loadModuleInfo();
4594         updateAvailableModules();
4595         //FIXME It'd be nice to make sure here that the selected
4596         //modules are consistent: That required modules are actually
4597         //selected, and that we don't have conflicts. If so, we could
4598         //at least pop up a warning.
4599         paramsToDialog();
4600         return true;
4601 }
4602
4603
4604 void GuiDocument::clearParams()
4605 {
4606         bp_ = BufferParams();
4607 }
4608
4609
4610 BufferId GuiDocument::id() const
4611 {
4612         BufferView const * const view = bufferview();
4613         return view? &view->buffer() : 0;
4614 }
4615
4616
4617 list<GuiDocument::modInfoStruct> const & GuiDocument::getModuleInfo()
4618 {
4619         return moduleNames_;
4620 }
4621
4622
4623 list<GuiDocument::modInfoStruct> const
4624 GuiDocument::makeModuleInfo(LayoutModuleList const & mods)
4625 {
4626         list<modInfoStruct> mInfo;
4627         for (string const & name : mods) {
4628                 modInfoStruct m;
4629                 LyXModule const * const mod = theModuleList[name];
4630                 if (mod)
4631                         m = modInfo(*mod);
4632                 else {
4633                         m.id = name;
4634                         m.name = toqstr(name + " (") + qt_("Not Found") + toqstr(")");
4635                         m.local = false;
4636                         m.missingreqs = true;
4637                 }
4638                 mInfo.push_back(m);
4639         }
4640         return mInfo;
4641 }
4642
4643
4644 list<GuiDocument::modInfoStruct> const GuiDocument::getSelectedModules()
4645 {
4646         return makeModuleInfo(params().getModules());
4647 }
4648
4649
4650 list<GuiDocument::modInfoStruct> const GuiDocument::getProvidedModules()
4651 {
4652         return makeModuleInfo(params().baseClass()->providedModules());
4653 }
4654
4655
4656 DocumentClass const & GuiDocument::documentClass() const
4657 {
4658         return bp_.documentClass();
4659 }
4660
4661
4662 static void dispatch_bufferparams(Dialog const & dialog,
4663         BufferParams const & bp, FuncCode lfun, Buffer const * buf)
4664 {
4665         ostringstream ss;
4666         ss << "\\begin_header\n";
4667         bp.writeFile(ss, buf);
4668         ss << "\\end_header\n";
4669         dialog.dispatch(FuncRequest(lfun, ss.str()));
4670 }
4671
4672
4673 void GuiDocument::dispatchParams()
4674 {
4675         // We need a non-const buffer object.
4676         Buffer & buf = const_cast<BufferView *>(bufferview())->buffer();
4677         // There may be several undo records; group them (bug #8998)
4678         // This handles undo groups automagically
4679         UndoGroupHelper ugh(&buf);
4680
4681         // This must come first so that a language change is correctly noticed
4682         setLanguage();
4683
4684         // We need to load the master before we formally update the params,
4685         // since otherwise we run updateBuffer, etc, before the child's master
4686         // has been set.
4687         if (!params().master.empty()) {
4688                 FileName const master_file = support::makeAbsPath(params().master,
4689                            support::onlyPath(buffer().absFileName()));
4690                 if (isLyXFileName(master_file.absFileName())) {
4691                         Buffer * master = checkAndLoadLyXFile(master_file);
4692                         if (master) {
4693                                 if (master->isChild(const_cast<Buffer *>(&buffer())))
4694                                         const_cast<Buffer &>(buffer()).setParent(master);
4695                                 else
4696                                         Alert::warning(_("Assigned master does not include this file"),
4697                                                 bformat(_("You must include this file in the document\n"
4698                                                           "'%1$s' in order to use the master document\n"
4699                                                           "feature."), from_utf8(params().master)));
4700                         } else
4701                                 Alert::warning(_("Could not load master"),
4702                                                 bformat(_("The master document '%1$s'\n"
4703                                                            "could not be loaded."),
4704                                                            from_utf8(params().master)));
4705                 }
4706         }
4707
4708         // Apply the BufferParams. Note that this will set the base class
4709         // and then update the buffer's layout.
4710         dispatch_bufferparams(*this, params(), LFUN_BUFFER_PARAMS_APPLY, &buffer());
4711
4712         // Generate the colours requested by each new branch.
4713         BranchList & branchlist = params().branchlist();
4714         if (!branchlist.empty()) {
4715                 BranchList::const_iterator it = branchlist.begin();
4716                 BranchList::const_iterator const end = branchlist.end();
4717                 for (; it != end; ++it) {
4718                         docstring const & current_branch = it->branch();
4719                         Branch const * branch = branchlist.find(current_branch);
4720                         string const x11hexname = X11hexname(branch->color());
4721                         // display the new color
4722                         docstring const str = current_branch + ' ' + from_ascii(x11hexname);
4723                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
4724                 }
4725         }
4726         // rename branches in the document
4727         executeBranchRenaming();
4728         // and clear changed branches cache
4729         changedBranches_.clear();
4730
4731         // Generate the colours requested by indices.
4732         IndicesList & indiceslist = params().indiceslist();
4733         if (!indiceslist.empty()) {
4734                 IndicesList::const_iterator it = indiceslist.begin();
4735                 IndicesList::const_iterator const end = indiceslist.end();
4736                 for (; it != end; ++it) {
4737                         docstring const & current_index = it->shortcut();
4738                         Index const * index = indiceslist.findShortcut(current_index);
4739                         string const x11hexname = X11hexname(index->color());
4740                         // display the new color
4741                         docstring const str = current_index + ' ' + from_ascii(x11hexname);
4742                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
4743                 }
4744         }
4745         // FIXME LFUN
4746         // If we used an LFUN, we would not need these two lines:
4747         BufferView * bv = const_cast<BufferView *>(bufferview());
4748         bv->processUpdateFlags(Update::Force | Update::FitCursor);
4749 }
4750
4751
4752 void GuiDocument::setLanguage() const
4753 {
4754         Language const * const newL = bp_.language;
4755         if (buffer().params().language == newL)
4756                 return;
4757
4758         string const & lang_name = newL->lang();
4759         dispatch(FuncRequest(LFUN_BUFFER_LANGUAGE, lang_name));
4760 }
4761
4762
4763 void GuiDocument::saveAsDefault() const
4764 {
4765         dispatch_bufferparams(*this, params(), LFUN_BUFFER_SAVE_AS_DEFAULT, &buffer());
4766 }
4767
4768
4769 bool GuiDocument::providesOSF(QString const & font) const
4770 {
4771         if (fontModule->osFontsCB->isChecked())
4772                 // FIXME: we should check if the fonts really
4773                 // have OSF support. But how?
4774                 return true;
4775         return theLaTeXFonts().getLaTeXFont(
4776                                 qstring_to_ucs4(font)).providesOSF(ot1(),
4777                                                                    completeFontset(),
4778                                                                    noMathFont());
4779 }
4780
4781
4782 bool GuiDocument::providesSC(QString const & font) const
4783 {
4784         if (fontModule->osFontsCB->isChecked())
4785                 return false;
4786         return theLaTeXFonts().getLaTeXFont(
4787                                 qstring_to_ucs4(font)).providesSC(ot1(),
4788                                                                   completeFontset(),
4789                                                                   noMathFont());
4790 }
4791
4792
4793 bool GuiDocument::providesScale(QString const & font) const
4794 {
4795         if (fontModule->osFontsCB->isChecked())
4796                 return true;
4797         return theLaTeXFonts().getLaTeXFont(
4798                                 qstring_to_ucs4(font)).providesScale(ot1(),
4799                                                                      completeFontset(),
4800                                                                      noMathFont());
4801 }
4802
4803
4804 bool GuiDocument::providesNoMath(QString const & font) const
4805 {
4806         if (fontModule->osFontsCB->isChecked())
4807                 return false;
4808         return theLaTeXFonts().getLaTeXFont(
4809                                 qstring_to_ucs4(font)).providesNoMath(ot1(),
4810                                                                       completeFontset());
4811 }
4812
4813
4814 bool GuiDocument::hasMonolithicExpertSet(QString const & font) const
4815 {
4816         if (fontModule->osFontsCB->isChecked())
4817                 return false;
4818         return theLaTeXFonts().getLaTeXFont(
4819                                 qstring_to_ucs4(font)).hasMonolithicExpertSet(ot1(),
4820                                                                               completeFontset(),
4821                                                                               noMathFont());
4822 }
4823
4824
4825 //static
4826 GuiDocument::modInfoStruct GuiDocument::modInfo(LyXModule const & mod)
4827 {
4828         // FIXME Unicode: docstrings would be better for these parameters but this
4829         // change requires a lot of others
4830         modInfoStruct m;
4831         m.id = mod.getID();
4832         QString const guiname = toqstr(translateIfPossible(from_utf8(mod.getName())));
4833         m.missingreqs = !isModuleAvailable(mod.getID());
4834         if (m.missingreqs) {
4835                 m.name = QString(qt_("%1 (missing req.)")).arg(guiname);
4836         } else
4837                 m.name = guiname;
4838         m.category = mod.category().empty() ? qt_("Miscellaneous")
4839                                             : toqstr(translateIfPossible(from_utf8(mod.category())));
4840         QString desc = toqstr(translateIfPossible(from_utf8(mod.getDescription())));
4841         // Find the first sentence of the description
4842         QTextBoundaryFinder bf(QTextBoundaryFinder::Sentence, desc);
4843         int pos = bf.toNextBoundary();
4844         if (pos > 0)
4845                 desc.truncate(pos);
4846         m.local = mod.isLocal();
4847         QString const mtype = m.local ? qt_("personal module") : qt_("distributed module");
4848         QString modulename = QString(qt_("<b>Module name:</b> <i>%1</i> (%2)")).arg(toqstr(m.id)).arg(mtype);
4849         // Tooltip is the desc followed by the module name and the type
4850         m.description = QString("%1%2")
4851                 .arg(desc.isEmpty() ? QString() : QString("<p>%1</p>").arg(desc),
4852                      modulename);
4853         if (m.missingreqs)
4854                 m.description += QString("<p>%1</p>").arg(qt_("<b>Note:</b> Some requirements for this module are missing!"));
4855         return m;
4856 }
4857
4858
4859 void GuiDocument::loadModuleInfo()
4860 {
4861         moduleNames_.clear();
4862         for (LyXModule const & mod : theModuleList)
4863                 moduleNames_.push_back(modInfo(mod));
4864 }
4865
4866
4867 void GuiDocument::updateUnknownBranches()
4868 {
4869         if (!bufferview())
4870                 return;
4871         list<docstring> used_branches;
4872         buffer().getUsedBranches(used_branches);
4873         list<docstring>::const_iterator it = used_branches.begin();
4874         QStringList unknown_branches;
4875         for (; it != used_branches.end() ; ++it) {
4876                 if (!buffer().params().branchlist().find(*it))
4877                         unknown_branches.append(toqstr(*it));
4878         }
4879         branchesModule->setUnknownBranches(unknown_branches);
4880 }
4881
4882
4883 void GuiDocument::branchesRename(docstring const & oldname, docstring const & newname)
4884 {
4885         map<docstring, docstring>::iterator it = changedBranches_.begin();
4886         for (; it != changedBranches_.end() ; ++it) {
4887                 if (it->second == oldname) {
4888                         // branch has already been renamed
4889                         it->second = newname;
4890                         return;
4891                 }
4892         }
4893         // store new name
4894         changedBranches_[oldname] = newname;
4895 }
4896
4897
4898 void GuiDocument::executeBranchRenaming() const
4899 {
4900         map<docstring, docstring>::const_iterator it = changedBranches_.begin();
4901         for (; it != changedBranches_.end() ; ++it) {
4902                 docstring const arg = '"' + it->first + '"' + " " + '"' + it->second + '"';
4903                 dispatch(FuncRequest(LFUN_BRANCHES_RENAME, arg));
4904         }
4905 }
4906
4907
4908 void GuiDocument::allPackagesAuto()
4909 {
4910         allPackages(1);
4911 }
4912
4913
4914 void GuiDocument::allPackagesAlways()
4915 {
4916         allPackages(2);
4917 }
4918
4919
4920 void GuiDocument::allPackagesNot()
4921 {
4922         allPackages(3);
4923 }
4924
4925
4926 void GuiDocument::allPackages(int col)
4927 {
4928         for (int row = 0; row < mathsModule->packagesTW->rowCount(); ++row) {
4929                 QRadioButton * rb =
4930                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, col)->layout()->itemAt(0)->widget();
4931                 rb->setChecked(true);
4932         }
4933 }
4934
4935
4936 Dialog * createGuiDocument(GuiView & lv) { return new GuiDocument(lv); }
4937
4938
4939 } // namespace frontend
4940 } // namespace lyx
4941
4942 #include "moc_GuiDocument.cpp"