]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiDocument.cpp
lineno: convert ui GB to CB per Juergen's request
[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         connect(numberingModule->linenoCB, SIGNAL(toggled(bool)),
1257                 this, SLOT(linenoToggled()));
1258         connect(numberingModule->linenoCB, SIGNAL(clicked()),
1259                 this, SLOT(change_adaptor()));
1260         connect(numberingModule->linenoLE, SIGNAL(textChanged(QString)),
1261                 this, SLOT(change_adaptor()));
1262
1263
1264         // biblio
1265         biblioModule = new UiWidget<Ui::BiblioUi>(this);
1266         connect(biblioModule->citeEngineCO, SIGNAL(activated(int)),
1267                 this, SLOT(citeEngineChanged(int)));
1268         connect(biblioModule->citeStyleCO, SIGNAL(activated(int)),
1269                 this, SLOT(citeStyleChanged()));
1270         connect(biblioModule->bibtopicCB, SIGNAL(clicked()),
1271                 this, SLOT(biblioChanged()));
1272         connect(biblioModule->bibunitsCO, SIGNAL(activated(int)),
1273                 this, SLOT(biblioChanged()));
1274         connect(biblioModule->bibtexCO, SIGNAL(activated(int)),
1275                 this, SLOT(bibtexChanged(int)));
1276         connect(biblioModule->bibtexOptionsLE, SIGNAL(textChanged(QString)),
1277                 this, SLOT(biblioChanged()));
1278         connect(biblioModule->citePackageOptionsLE, SIGNAL(textChanged(QString)),
1279                 this, SLOT(biblioChanged()));
1280         connect(biblioModule->defaultBiblioCO, SIGNAL(activated(int)),
1281                 this, SLOT(biblioChanged()));
1282         connect(biblioModule->defaultBiblioCO, SIGNAL(editTextChanged(QString)),
1283                 this, SLOT(biblioChanged()));
1284         connect(biblioModule->defaultBiblioCO, SIGNAL(editTextChanged(QString)),
1285                 this, SLOT(updateResetDefaultBiblio()));
1286         connect(biblioModule->biblatexBbxCO, SIGNAL(activated(int)),
1287                 this, SLOT(biblioChanged()));
1288         connect(biblioModule->biblatexBbxCO, SIGNAL(editTextChanged(QString)),
1289                 this, SLOT(biblioChanged()));
1290         connect(biblioModule->biblatexBbxCO, SIGNAL(editTextChanged(QString)),
1291                 this, SLOT(updateResetDefaultBiblio()));
1292         connect(biblioModule->biblatexCbxCO, SIGNAL(activated(int)),
1293                 this, SLOT(biblioChanged()));
1294         connect(biblioModule->biblatexCbxCO, SIGNAL(editTextChanged(QString)),
1295                 this, SLOT(biblioChanged()));
1296         connect(biblioModule->biblatexCbxCO, SIGNAL(editTextChanged(QString)),
1297                 this, SLOT(updateResetDefaultBiblio()));
1298         connect(biblioModule->rescanBibliosPB, SIGNAL(clicked()),
1299                 this, SLOT(rescanBibFiles()));
1300         connect(biblioModule->resetDefaultBiblioPB, SIGNAL(clicked()),
1301                 this, SLOT(resetDefaultBibfile()));
1302         connect(biblioModule->resetCbxPB, SIGNAL(clicked()),
1303                 this, SLOT(resetDefaultCbxBibfile()));
1304         connect(biblioModule->resetBbxPB, SIGNAL(clicked()),
1305                 this, SLOT(resetDefaultBbxBibfile()));
1306         connect(biblioModule->matchBbxPB, SIGNAL(clicked()),
1307                 this, SLOT(matchBiblatexStyles()));
1308
1309         biblioModule->citeEngineCO->clear();
1310         for (LyXCiteEngine const & cet : theCiteEnginesList) {
1311                 biblioModule->citeEngineCO->addItem(qt_(cet.getName()), toqstr(cet.getID()));
1312                 int const i = biblioModule->citeEngineCO->findData(toqstr(cet.getID()));
1313                 biblioModule->citeEngineCO->setItemData(i, qt_(cet.getDescription()),
1314                                                         Qt::ToolTipRole);
1315         }
1316
1317         biblioModule->bibtexOptionsLE->setValidator(new NoNewLineValidator(
1318                 biblioModule->bibtexOptionsLE));
1319         biblioModule->defaultBiblioCO->lineEdit()->setValidator(new NoNewLineValidator(
1320                 biblioModule->defaultBiblioCO->lineEdit()));
1321         biblioModule->citePackageOptionsLE->setValidator(new NoNewLineValidator(
1322                 biblioModule->citePackageOptionsLE));
1323
1324         // NOTE: we do not provide "custom" here for security reasons!
1325         biblioModule->bibtexCO->clear();
1326         biblioModule->bibtexCO->addItem(qt_("Default"), QString("default"));
1327         for (auto const & alts : lyxrc.bibtex_alternatives) {
1328                 QString const command = toqstr(alts).left(toqstr(alts).indexOf(" "));
1329                 biblioModule->bibtexCO->addItem(command, command);
1330         }
1331
1332
1333         // indices
1334         indicesModule = new GuiIndices;
1335         connect(indicesModule, SIGNAL(changed()),
1336                 this, SLOT(change_adaptor()));
1337
1338
1339         // maths
1340         mathsModule = new UiWidget<Ui::MathsUi>(this);
1341         QStringList headers;
1342         headers << qt_("Package") << qt_("Load automatically")
1343                 << qt_("Load always") << qt_("Do not load");
1344         mathsModule->packagesTW->setHorizontalHeaderLabels(headers);
1345         setSectionResizeMode(mathsModule->packagesTW->horizontalHeader(), QHeaderView::Stretch);
1346         map<string, string> const & packages = BufferParams::auto_packages();
1347         mathsModule->packagesTW->setRowCount(packages.size());
1348         int packnum = 0;
1349         for (auto const & pkgvar : packages) {
1350                 docstring const package = from_ascii(pkgvar.first);
1351                 QString autoTooltip = qt_(pkgvar.second);
1352                 QString alwaysTooltip;
1353                 if (package == "amsmath")
1354                         alwaysTooltip =
1355                                 qt_("The AMS LaTeX packages are always used");
1356                 else
1357                         alwaysTooltip = toqstr(bformat(
1358                                 _("The LaTeX package %1$s is always used"),
1359                                 package));
1360                 QString neverTooltip;
1361                 if (package == "amsmath")
1362                         neverTooltip =
1363                                 qt_("The AMS LaTeX packages are never used");
1364                 else
1365                         neverTooltip = toqstr(bformat(
1366                                 _("The LaTeX package %1$s is never used"),
1367                                 package));
1368                 QRadioButton * autoRB = new QRadioButton(mathsModule);
1369                 QRadioButton * alwaysRB = new QRadioButton(mathsModule);
1370                 QRadioButton * neverRB = new QRadioButton(mathsModule);
1371                 QButtonGroup * packageGroup = new QButtonGroup(mathsModule);
1372                 packageGroup->addButton(autoRB);
1373                 packageGroup->addButton(alwaysRB);
1374                 packageGroup->addButton(neverRB);
1375                 autoRB->setToolTip(autoTooltip);
1376                 alwaysRB->setToolTip(alwaysTooltip);
1377                 neverRB->setToolTip(neverTooltip);
1378
1379                 // Pack the buttons in a layout in order to get proper alignment
1380                 QWidget * autoRBWidget = new QWidget();
1381                 QHBoxLayout * autoRBLayout = new QHBoxLayout(autoRBWidget);
1382                 autoRBLayout->addWidget(autoRB);
1383                 autoRBLayout->setAlignment(Qt::AlignCenter);
1384                 autoRBLayout->setContentsMargins(0, 0, 0, 0);
1385                 autoRBWidget->setLayout(autoRBLayout);
1386
1387                 QWidget * alwaysRBWidget = new QWidget();
1388                 QHBoxLayout * alwaysRBLayout = new QHBoxLayout(alwaysRBWidget);
1389                 alwaysRBLayout->addWidget(alwaysRB);
1390                 alwaysRBLayout->setAlignment(Qt::AlignCenter);
1391                 alwaysRBLayout->setContentsMargins(0, 0, 0, 0);
1392                 alwaysRBWidget->setLayout(alwaysRBLayout);
1393
1394                 QWidget * neverRBWidget = new QWidget();
1395                 QHBoxLayout * neverRBLayout = new QHBoxLayout(neverRBWidget);
1396                 neverRBLayout->addWidget(neverRB);
1397                 neverRBLayout->setAlignment(Qt::AlignCenter);
1398                 neverRBLayout->setContentsMargins(0, 0, 0, 0);
1399                 neverRBWidget->setLayout(neverRBLayout);
1400
1401                 QTableWidgetItem * pack = new QTableWidgetItem(toqstr(package));
1402                 mathsModule->packagesTW->setItem(packnum, 0, pack);
1403                 mathsModule->packagesTW->setCellWidget(packnum, 1, autoRBWidget);
1404                 mathsModule->packagesTW->setCellWidget(packnum, 2, alwaysRBWidget);
1405                 mathsModule->packagesTW->setCellWidget(packnum, 3, neverRBWidget);
1406
1407                 connect(autoRB, SIGNAL(clicked()),
1408                         this, SLOT(change_adaptor()));
1409                 connect(alwaysRB, SIGNAL(clicked()),
1410                         this, SLOT(change_adaptor()));
1411                 connect(neverRB, SIGNAL(clicked()),
1412                         this, SLOT(change_adaptor()));
1413                 ++packnum;
1414         }
1415         connect(mathsModule->allPackagesAutoPB, SIGNAL(clicked()),
1416                 this, SLOT(allPackagesAuto()));
1417         connect(mathsModule->allPackagesAlwaysPB, SIGNAL(clicked()),
1418                 this, SLOT(allPackagesAlways()));
1419         connect(mathsModule->allPackagesNotPB, SIGNAL(clicked()),
1420                 this, SLOT(allPackagesNot()));
1421         connect(mathsModule->allPackagesAutoPB, SIGNAL(clicked()),
1422                 this, SLOT(change_adaptor()));
1423         connect(mathsModule->allPackagesAlwaysPB, SIGNAL(clicked()),
1424                 this, SLOT(change_adaptor()));
1425         connect(mathsModule->allPackagesNotPB, SIGNAL(clicked()),
1426                 this, SLOT(change_adaptor()));
1427         connect(mathsModule->MathNumberingPosCO, SIGNAL(activated(int)),
1428                 this, SLOT(change_adaptor()));
1429
1430         connect(mathsModule->MathIndentCB, SIGNAL(toggled(bool)),
1431                 this, SLOT(change_adaptor()));
1432         connect(mathsModule->MathIndentCB, SIGNAL(toggled(bool)),
1433                 this, SLOT(allowMathIndent()));
1434         connect(mathsModule->MathIndentCO, SIGNAL(activated(int)),
1435                 this, SLOT(change_adaptor()));
1436         connect(mathsModule->MathIndentCO, SIGNAL(activated(int)),
1437                 this, SLOT(enableMathIndent(int)));
1438         connect(mathsModule->MathIndentLE, SIGNAL(textChanged(const QString &)),
1439                 this, SLOT(change_adaptor()));
1440         connect(mathsModule->MathIndentLengthCO, SIGNAL(activated(int)),
1441                 this, SLOT(change_adaptor()));
1442
1443
1444         mathsModule->MathIndentCO->addItem(qt_("Default"));
1445         mathsModule->MathIndentCO->addItem(qt_("Custom"));
1446         mathsModule->MathIndentLE->setValidator(new LengthValidator(
1447                 mathsModule->MathIndentLE));
1448         // initialize the length validator
1449         bc().addCheckedLineEdit(mathsModule->MathIndentLE);
1450         mathsModule->MathNumberingPosCO->addItem(qt_("Left"));
1451         mathsModule->MathNumberingPosCO->addItem(qt_("Default"));
1452         mathsModule->MathNumberingPosCO->addItem(qt_("Right"));
1453         mathsModule->MathNumberingPosCO->setCurrentIndex(1);
1454
1455
1456         // latex class
1457         latexModule = new UiWidget<Ui::LaTeXUi>(this);
1458         connect(latexModule->optionsLE, SIGNAL(textChanged(QString)),
1459                 this, SLOT(change_adaptor()));
1460         connect(latexModule->defaultOptionsCB, SIGNAL(clicked()),
1461                 this, SLOT(change_adaptor()));
1462         connect(latexModule->psdriverCO, SIGNAL(activated(int)),
1463                 this, SLOT(change_adaptor()));
1464         connect(latexModule->classCO, SIGNAL(activated(int)),
1465                 this, SLOT(classChanged_adaptor()));
1466         connect(latexModule->classCO, SIGNAL(activated(int)),
1467                 this, SLOT(change_adaptor()));
1468         connect(latexModule->layoutPB, SIGNAL(clicked()),
1469                 this, SLOT(browseLayout()));
1470         connect(latexModule->layoutPB, SIGNAL(clicked()),
1471                 this, SLOT(change_adaptor()));
1472         connect(latexModule->childDocGB, SIGNAL(clicked()),
1473                 this, SLOT(change_adaptor()));
1474         connect(latexModule->childDocLE, SIGNAL(textChanged(QString)),
1475                 this, SLOT(change_adaptor()));
1476         connect(latexModule->childDocPB, SIGNAL(clicked()),
1477                 this, SLOT(browseMaster()));
1478         connect(latexModule->suppressDateCB, SIGNAL(clicked()),
1479                 this, SLOT(change_adaptor()));
1480         connect(latexModule->refstyleCB, SIGNAL(clicked()),
1481                 this, SLOT(change_adaptor()));
1482
1483         latexModule->optionsLE->setValidator(new NoNewLineValidator(
1484                 latexModule->optionsLE));
1485         latexModule->childDocLE->setValidator(new NoNewLineValidator(
1486                 latexModule->childDocLE));
1487
1488         // postscript drivers
1489         for (int n = 0; tex_graphics[n][0]; ++n) {
1490                 QString enc = qt_(tex_graphics_gui[n]);
1491                 latexModule->psdriverCO->addItem(enc);
1492         }
1493         // latex classes
1494         LayoutFileList const & bcl = LayoutFileList::get();
1495         vector<LayoutFileIndex> classList = bcl.classList();
1496         sort(classList.begin(), classList.end(), less_textclass_avail_desc());
1497
1498         for (auto const & cvar : classList) {
1499                 LayoutFile const & tc = bcl[cvar];
1500                 bool const available = tc.isTeXClassAvailable();
1501                 docstring const guiname = translateIfPossible(from_utf8(tc.description()));
1502                 // tooltip sensu "KOMA-Script Article [Class 'scrartcl']"
1503                 QString tooltip = toqstr(bformat(_("%1$s [Class '%2$s']"), guiname, from_utf8(tc.latexname())));
1504                 if (!available) {
1505                         docstring const output_type = (tc.outputType() == lyx::DOCBOOK) ? _("DocBook") : _("LaTeX");
1506                         tooltip += '\n' + toqstr(bformat(_("Class not found by LyX. "
1507                                                            "Please check if you have the matching %1$s class "
1508                                                            "and all required packages (%2$s) installed."),
1509                                                          output_type, from_utf8(tc.prerequisites(", "))));
1510                 }
1511                 latexModule->classCO->addItemSort(toqstr(tc.name()),
1512                                                   toqstr(guiname),
1513                                                   toqstr(translateIfPossible(from_utf8(tc.category()))),
1514                                                   tooltip,
1515                                                   true, true, true, available);
1516         }
1517
1518
1519         // branches
1520         branchesModule = new GuiBranches(this);
1521         connect(branchesModule, SIGNAL(changed()),
1522                 this, SLOT(change_adaptor()));
1523         connect(branchesModule, SIGNAL(renameBranches(docstring const &, docstring const &)),
1524                 this, SLOT(branchesRename(docstring const &, docstring const &)));
1525         connect(branchesModule, SIGNAL(okPressed()), this, SLOT(slotOK()));
1526         updateUnknownBranches();
1527
1528
1529         // preamble
1530         preambleModule = new PreambleModule(this);
1531         connect(preambleModule, SIGNAL(changed()),
1532                 this, SLOT(change_adaptor()));
1533
1534         localLayout = new LocalLayout(this);
1535         connect(localLayout, SIGNAL(changed()),
1536                 this, SLOT(change_adaptor()));
1537
1538
1539         // bullets
1540         bulletsModule = new BulletsModule(this);
1541         connect(bulletsModule, SIGNAL(changed()),
1542                 this, SLOT(change_adaptor()));
1543
1544
1545         // Modules
1546         modulesModule = new UiWidget<Ui::ModulesUi>(this);
1547         modulesModule->availableLV->header()->setVisible(false);
1548         setSectionResizeMode(modulesModule->availableLV->header(), QHeaderView::ResizeToContents);
1549         modulesModule->availableLV->header()->setStretchLastSection(false);
1550         modulesModule->selectedLV->header()->setVisible(false);
1551         setSectionResizeMode(modulesModule->selectedLV->header(), QHeaderView::ResizeToContents);
1552         modulesModule->selectedLV->header()->setStretchLastSection(false);
1553         selectionManager =
1554                 new ModuleSelectionManager(this, modulesModule->availableLV,
1555                                            modulesModule->selectedLV,
1556                                            modulesModule->addPB,
1557                                            modulesModule->deletePB,
1558                                            modulesModule->upPB,
1559                                            modulesModule->downPB,
1560                                            availableModel(), selectedModel(), this);
1561         connect(selectionManager, SIGNAL(updateHook()),
1562                 this, SLOT(updateModuleInfo()));
1563         connect(selectionManager, SIGNAL(selectionChanged()),
1564                 this, SLOT(modulesChanged()));
1565         // The filter bar
1566         filter_ = new FancyLineEdit(this);
1567         filter_->setButtonPixmap(FancyLineEdit::Right, getPixmap("images/", "editclear", "svgz,png"));
1568         filter_->setButtonVisible(FancyLineEdit::Right, true);
1569         filter_->setButtonToolTip(FancyLineEdit::Right, qt_("Clear text"));
1570         filter_->setAutoHideButton(FancyLineEdit::Right, true);
1571         filter_->setPlaceholderText(qt_("All avail. modules"));
1572         modulesModule->moduleFilterBarL->addWidget(filter_, 0);
1573         modulesModule->findModulesLA->setBuddy(filter_);
1574
1575         connect(filter_, SIGNAL(rightButtonClicked()),
1576                 this, SLOT(resetModuleFilter()));
1577         connect(filter_, SIGNAL(textEdited(QString)),
1578                 this, SLOT(moduleFilterChanged(QString)));
1579         connect(filter_, SIGNAL(returnPressed()),
1580                 this, SLOT(moduleFilterPressed()));
1581 #if (QT_VERSION < 0x050000)
1582         connect(filter_, SIGNAL(downPressed()),
1583                 modulesModule->availableLV, SLOT(setFocus()));
1584 #else
1585         connect(filter_, &FancyLineEdit::downPressed,
1586                 modulesModule->availableLV, [=](){ focusAndHighlight(modulesModule->availableLV); });
1587 #endif
1588
1589
1590         // PDF support
1591         pdfSupportModule = new UiWidget<Ui::PDFSupportUi>(this);
1592         connect(pdfSupportModule->use_hyperrefGB, SIGNAL(toggled(bool)),
1593                 this, SLOT(change_adaptor()));
1594         connect(pdfSupportModule->titleLE, SIGNAL(textChanged(QString)),
1595                 this, SLOT(change_adaptor()));
1596         connect(pdfSupportModule->authorLE, SIGNAL(textChanged(QString)),
1597                 this, SLOT(change_adaptor()));
1598         connect(pdfSupportModule->subjectLE, SIGNAL(textChanged(QString)),
1599                 this, SLOT(change_adaptor()));
1600         connect(pdfSupportModule->keywordsLE, SIGNAL(textChanged(QString)),
1601                 this, SLOT(change_adaptor()));
1602         connect(pdfSupportModule->bookmarksGB, SIGNAL(toggled(bool)),
1603                 this, SLOT(change_adaptor()));
1604         connect(pdfSupportModule->bookmarksnumberedCB, SIGNAL(toggled(bool)),
1605                 this, SLOT(change_adaptor()));
1606         connect(pdfSupportModule->bookmarksopenGB, SIGNAL(toggled(bool)),
1607                 this, SLOT(change_adaptor()));
1608         connect(pdfSupportModule->bookmarksopenlevelSB, SIGNAL(valueChanged(int)),
1609                 this, SLOT(change_adaptor()));
1610         connect(pdfSupportModule->breaklinksCB, SIGNAL(toggled(bool)),
1611                 this, SLOT(change_adaptor()));
1612         connect(pdfSupportModule->pdfborderCB, SIGNAL(toggled(bool)),
1613                 this, SLOT(change_adaptor()));
1614         connect(pdfSupportModule->colorlinksCB, SIGNAL(toggled(bool)),
1615                 this, SLOT(change_adaptor()));
1616         connect(pdfSupportModule->backrefCO, SIGNAL(activated(int)),
1617                 this, SLOT(change_adaptor()));
1618         connect(pdfSupportModule->pdfusetitleCB, SIGNAL(toggled(bool)),
1619                 this, SLOT(change_adaptor()));
1620         connect(pdfSupportModule->fullscreenCB, SIGNAL(toggled(bool)),
1621                 this, SLOT(change_adaptor()));
1622         connect(pdfSupportModule->optionsLE, SIGNAL(textChanged(QString)),
1623                 this, SLOT(change_adaptor()));
1624
1625         pdfSupportModule->titleLE->setValidator(new NoNewLineValidator(
1626                 pdfSupportModule->titleLE));
1627         pdfSupportModule->authorLE->setValidator(new NoNewLineValidator(
1628                 pdfSupportModule->authorLE));
1629         pdfSupportModule->subjectLE->setValidator(new NoNewLineValidator(
1630                 pdfSupportModule->subjectLE));
1631         pdfSupportModule->keywordsLE->setValidator(new NoNewLineValidator(
1632                 pdfSupportModule->keywordsLE));
1633         pdfSupportModule->optionsLE->setValidator(new NoNewLineValidator(
1634                 pdfSupportModule->optionsLE));
1635
1636         for (int i = 0; backref_opts[i][0]; ++i)
1637                 pdfSupportModule->backrefCO->addItem(qt_(backref_opts_gui[i]));
1638
1639
1640         // float
1641         floatModule = new FloatPlacement;
1642         connect(floatModule, SIGNAL(changed()),
1643                 this, SLOT(change_adaptor()));
1644
1645
1646         // listings
1647         listingsModule = new UiWidget<Ui::ListingsSettingsUi>(this);
1648         connect(listingsModule->listingsED, SIGNAL(textChanged()),
1649                 this, SLOT(change_adaptor()));
1650         connect(listingsModule->bypassCB, SIGNAL(clicked()),
1651                 this, SLOT(change_adaptor()));
1652         connect(listingsModule->bypassCB, SIGNAL(clicked()),
1653                 this, SLOT(setListingsMessage()));
1654         connect(listingsModule->packageCO, SIGNAL(activated(int)),
1655                 this, SLOT(change_adaptor()));
1656         connect(listingsModule->packageCO, SIGNAL(activated(int)),
1657                 this, SLOT(listingsPackageChanged(int)));
1658         connect(listingsModule->listingsED, SIGNAL(textChanged()),
1659                 this, SLOT(setListingsMessage()));
1660         listingsModule->listingsTB->setPlainText(
1661                 qt_("Input listings parameters below. Enter ? for a list of parameters."));
1662
1663         for (int i = 0; lst_packages[i][0]; ++i)
1664             listingsModule->packageCO->addItem(lst_packages[i]);
1665
1666
1667         // add the panels
1668         docPS->addPanel(latexModule, N_("Document Class"));
1669         docPS->addPanel(masterChildModule, N_("Child Documents"));
1670         docPS->addPanel(modulesModule, N_("Modules"));
1671         docPS->addPanel(localLayout, N_("Local Layout"));
1672         docPS->addPanel(fontModule, N_("Fonts"));
1673         docPS->addPanel(textLayoutModule, N_("Text Layout"));
1674         docPS->addPanel(pageLayoutModule, N_("Page Layout"));
1675         docPS->addPanel(marginsModule, N_("Page Margins"));
1676         docPS->addPanel(langModule, N_("Language"));
1677         docPS->addPanel(colorModule, N_("Colors"));
1678         docPS->addPanel(numberingModule, N_("Numbering & TOC"));
1679         docPS->addPanel(biblioModule, N_("Bibliography"));
1680         docPS->addPanel(indicesModule, N_("Indexes"));
1681         docPS->addPanel(pdfSupportModule, N_("PDF Properties"));
1682         docPS->addPanel(mathsModule, N_("Math Options"));
1683         docPS->addPanel(floatModule, N_("Float Settings"));
1684         docPS->addPanel(listingsModule, N_("Listings[[inset]]"));
1685         docPS->addPanel(bulletsModule, N_("Bullets"));
1686         docPS->addPanel(branchesModule, N_("Branches"));
1687         docPS->addPanel(outputModule, N_("Formats[[output]]"));
1688         docPS->addPanel(preambleModule, N_("LaTeX Preamble"));
1689         docPS->setCurrentPanel("Document Class");
1690 // FIXME: hack to work around resizing bug in Qt >= 4.2
1691 // bug verified with Qt 4.2.{0-3} (JSpitzm)
1692 #if QT_VERSION >= 0x040200
1693         docPS->updateGeometry();
1694 #endif
1695 }
1696
1697
1698 void GuiDocument::onBufferViewChanged()
1699 {
1700         if (isVisibleView())
1701                 initialiseParams("");
1702 }
1703
1704
1705 void GuiDocument::saveDefaultClicked()
1706 {
1707         saveDocDefault();
1708 }
1709
1710
1711 void GuiDocument::useDefaultsClicked()
1712 {
1713         useClassDefaults();
1714 }
1715
1716
1717 void GuiDocument::change_adaptor()
1718 {
1719         nonModuleChanged_ = true;
1720         changed();
1721 }
1722
1723
1724 void GuiDocument::shellescapeChanged()
1725 {
1726         shellescapeChanged_ = true;
1727         changed();
1728 }
1729
1730
1731 void GuiDocument::slotApply()
1732 {
1733         bool only_shellescape_changed = !nonModuleChanged_ && !modulesChanged_;
1734         bool wasclean = buffer().isClean();
1735         GuiDialog::slotApply();
1736         if (wasclean && only_shellescape_changed)
1737                 buffer().markClean();
1738         modulesChanged_ = false;
1739 }
1740
1741
1742 void GuiDocument::slotOK()
1743 {
1744         bool only_shellescape_changed = !nonModuleChanged_ && !modulesChanged_;
1745         bool wasclean = buffer().isClean();
1746         GuiDialog::slotOK();
1747         if (wasclean && only_shellescape_changed)
1748                 buffer().markClean();
1749         modulesChanged_ = false;
1750 }
1751
1752
1753 void GuiDocument::slotButtonBox(QAbstractButton * button)
1754 {
1755         switch (buttonBox->standardButton(button)) {
1756         case QDialogButtonBox::Ok:
1757                 slotOK();
1758                 break;
1759         case QDialogButtonBox::Apply:
1760                 slotApply();
1761                 break;
1762         case QDialogButtonBox::Cancel:
1763                 slotClose();
1764                 break;
1765         case QDialogButtonBox::Reset:
1766         case QDialogButtonBox::RestoreDefaults:
1767                 slotRestore();
1768                 break;
1769         default:
1770                 break;
1771         }
1772 }
1773
1774
1775 void GuiDocument::filterModules(QString const & str)
1776 {
1777         updateAvailableModules();
1778         if (str.isEmpty())
1779                 return;
1780
1781         modules_av_model_.clear();
1782         list<modInfoStruct> modInfoList = getModuleInfo();
1783         // Sort names according to the locale
1784         modInfoList.sort([](modInfoStruct const & a, modInfoStruct const & b) {
1785                         return 0 < b.name.localeAwareCompare(a.name);
1786                 });
1787
1788         QIcon user_icon(getPixmap("images/", "lyxfiles-user", "svgz,png"));
1789         QIcon system_icon(getPixmap("images/", "lyxfiles-system", "svgz,png"));
1790
1791         int i = 0;
1792         for (modInfoStruct const & m : modInfoList) {
1793                 if (m.name.contains(str, Qt::CaseInsensitive) || contains(m.id, fromqstr(str))) {
1794                         QStandardItem * item = new QStandardItem();
1795                         item->setData(m.name, Qt::DisplayRole);
1796                         item->setData(toqstr(m.id), Qt::UserRole);
1797                         item->setData(m.description, Qt::ToolTipRole);
1798                         if (m.local)
1799                                 item->setIcon(user_icon);
1800                         else
1801                                 item->setIcon(system_icon);
1802                         modules_av_model_.insertRow(i, item);
1803                         ++i;
1804                 }
1805         }
1806 }
1807
1808
1809 void GuiDocument::moduleFilterChanged(const QString & text)
1810 {
1811         if (!text.isEmpty()) {
1812                 filterModules(filter_->text());
1813                 return;
1814         }
1815         filterModules(filter_->text());
1816         filter_->setFocus();
1817 }
1818
1819
1820 void GuiDocument::moduleFilterPressed()
1821 {
1822         filterModules(filter_->text());
1823 }
1824
1825
1826 void GuiDocument::resetModuleFilter()
1827 {
1828         filter_->setText(QString());
1829         filterModules(filter_->text());
1830 }
1831
1832
1833 void GuiDocument::includeonlyClicked(QTreeWidgetItem * item, int)
1834 {
1835         if (item == 0)
1836                 return;
1837
1838         string child = fromqstr(item->text(0));
1839         if (child.empty())
1840                 return;
1841
1842         if (std::find(includeonlys_.begin(),
1843                       includeonlys_.end(), child) != includeonlys_.end())
1844                 includeonlys_.remove(child);
1845         else
1846                 includeonlys_.push_back(child);
1847
1848         updateIncludeonlys();
1849         change_adaptor();
1850 }
1851
1852
1853 QString GuiDocument::validateListingsParameters()
1854 {
1855         if (listingsModule->bypassCB->isChecked())
1856                 return QString();
1857         string const package =
1858             lst_packages[listingsModule->packageCO->currentIndex()];
1859         string params = fromqstr(listingsModule->listingsED->toPlainText());
1860         InsetListingsParams lstparams(params);
1861         lstparams.setMinted(package == "Minted");
1862         return toqstr(lstparams.validate());
1863 }
1864
1865
1866 void GuiDocument::setListingsMessage()
1867 {
1868         // FIXME THREAD
1869         static bool isOK = true;
1870         QString msg = validateListingsParameters();
1871         if (msg.isEmpty()) {
1872                 if (isOK)
1873                         return;
1874                 isOK = true;
1875                 // listingsTB->setTextColor("black");
1876                 listingsModule->listingsTB->setPlainText(
1877                         qt_("Input listings parameters below. "
1878                             "Enter ? for a list of parameters."));
1879         } else {
1880                 isOK = false;
1881                 // listingsTB->setTextColor("red");
1882                 listingsModule->listingsTB->setPlainText(msg);
1883         }
1884 }
1885
1886
1887 void GuiDocument::listingsPackageChanged(int index)
1888 {
1889         string const package = lst_packages[index];
1890         if (package == "Minted" && lyxrc.pygmentize_command.empty()) {
1891                 Alert::warning(_("Pygments driver command not found!"),
1892                     _("The driver command necessary to use the minted package\n"
1893                       "(pygmentize) has not been found. Make sure you have\n"
1894                       "the python-pygments module installed or, if the driver\n"
1895                       "is named differently, to add the following line to the\n"
1896                       "document preamble:\n\n"
1897                       "\\AtBeginDocument{\\renewcommand{\\MintedPygmentize}{driver}}\n\n"
1898                       "where 'driver' is name of the driver command."));
1899         }
1900 }
1901
1902
1903 void GuiDocument::setLSpacing(int item)
1904 {
1905         textLayoutModule->lspacingLE->setEnabled(item == 3);
1906 }
1907
1908
1909 void GuiDocument::setIndent(int item)
1910 {
1911         bool const enable = (item == 1);
1912         textLayoutModule->indentLE->setEnabled(enable);
1913         textLayoutModule->indentLengthCO->setEnabled(enable);
1914         textLayoutModule->skipLE->setEnabled(false);
1915         textLayoutModule->skipLengthCO->setEnabled(false);
1916         isValid();
1917 }
1918
1919
1920 void GuiDocument::enableIndent(bool indent)
1921 {
1922         textLayoutModule->skipLE->setEnabled(!indent);
1923         textLayoutModule->skipLengthCO->setEnabled(!indent);
1924         if (indent)
1925                 setIndent(textLayoutModule->indentCO->currentIndex());
1926 }
1927
1928
1929 void GuiDocument::setSkip(int item)
1930 {
1931         bool const enable = (item == 3);
1932         textLayoutModule->skipLE->setEnabled(enable);
1933         textLayoutModule->skipLengthCO->setEnabled(enable);
1934         isValid();
1935 }
1936
1937
1938 void GuiDocument::enableSkip(bool skip)
1939 {
1940         textLayoutModule->indentLE->setEnabled(!skip);
1941         textLayoutModule->indentLengthCO->setEnabled(!skip);
1942         if (skip)
1943                 setSkip(textLayoutModule->skipCO->currentIndex());
1944 }
1945
1946 void GuiDocument::allowMathIndent() {
1947         // only disable when not checked, checked does not always allow enabling
1948         if (!mathsModule->MathIndentCB->isChecked()) {
1949                 mathsModule->MathIndentLE->setEnabled(false);
1950                 mathsModule->MathIndentLengthCO->setEnabled(false);
1951         }
1952         if (mathsModule->MathIndentCB->isChecked()
1953             && mathsModule->MathIndentCO->currentIndex() == 1) {
1954                         mathsModule->MathIndentLE->setEnabled(true);
1955                         mathsModule->MathIndentLengthCO->setEnabled(true);
1956         }
1957         isValid();
1958 }
1959
1960 void GuiDocument::enableMathIndent(int item)
1961 {
1962         bool const enable = (item == 1);
1963         mathsModule->MathIndentLE->setEnabled(enable);
1964         mathsModule->MathIndentLengthCO->setEnabled(enable);
1965         isValid();
1966 }
1967
1968
1969 void GuiDocument::setMargins()
1970 {
1971         bool const extern_geometry =
1972                 documentClass().provides("geometry");
1973         marginsModule->marginCB->setEnabled(!extern_geometry);
1974         if (extern_geometry) {
1975                 marginsModule->marginCB->setChecked(false);
1976                 setCustomMargins(true);
1977         } else {
1978                 marginsModule->marginCB->setChecked(!bp_.use_geometry);
1979                 setCustomMargins(!bp_.use_geometry);
1980         }
1981 }
1982
1983
1984 void GuiDocument::papersizeChanged(int paper_size)
1985 {
1986         setCustomPapersize(paper_size == 1);
1987 }
1988
1989
1990 void GuiDocument::setCustomPapersize(bool custom)
1991 {
1992         pageLayoutModule->paperwidthL->setEnabled(custom);
1993         pageLayoutModule->paperwidthLE->setEnabled(custom);
1994         pageLayoutModule->paperwidthUnitCO->setEnabled(custom);
1995         pageLayoutModule->paperheightL->setEnabled(custom);
1996         pageLayoutModule->paperheightLE->setEnabled(custom);
1997         pageLayoutModule->paperheightLE->setFocus();
1998         pageLayoutModule->paperheightUnitCO->setEnabled(custom);
1999 }
2000
2001
2002 void GuiDocument::setColSep()
2003 {
2004         setCustomMargins(marginsModule->marginCB->checkState() == Qt::Checked);
2005 }
2006
2007
2008 void GuiDocument::setCustomMargins(bool custom)
2009 {
2010         marginsModule->topL->setEnabled(!custom);
2011         marginsModule->topLE->setEnabled(!custom);
2012         marginsModule->topUnit->setEnabled(!custom);
2013
2014         marginsModule->bottomL->setEnabled(!custom);
2015         marginsModule->bottomLE->setEnabled(!custom);
2016         marginsModule->bottomUnit->setEnabled(!custom);
2017
2018         marginsModule->innerL->setEnabled(!custom);
2019         marginsModule->innerLE->setEnabled(!custom);
2020         marginsModule->innerUnit->setEnabled(!custom);
2021
2022         marginsModule->outerL->setEnabled(!custom);
2023         marginsModule->outerLE->setEnabled(!custom);
2024         marginsModule->outerUnit->setEnabled(!custom);
2025
2026         marginsModule->headheightL->setEnabled(!custom);
2027         marginsModule->headheightLE->setEnabled(!custom);
2028         marginsModule->headheightUnit->setEnabled(!custom);
2029
2030         marginsModule->headsepL->setEnabled(!custom);
2031         marginsModule->headsepLE->setEnabled(!custom);
2032         marginsModule->headsepUnit->setEnabled(!custom);
2033
2034         marginsModule->footskipL->setEnabled(!custom);
2035         marginsModule->footskipLE->setEnabled(!custom);
2036         marginsModule->footskipUnit->setEnabled(!custom);
2037
2038         bool const enableColSep = !custom &&
2039                         textLayoutModule->twoColumnCB->checkState() == Qt::Checked;
2040         marginsModule->columnsepL->setEnabled(enableColSep);
2041         marginsModule->columnsepLE->setEnabled(enableColSep);
2042         marginsModule->columnsepUnit->setEnabled(enableColSep);
2043 }
2044
2045
2046 void GuiDocument::changeBackgroundColor()
2047 {
2048         QColor const & newColor = QColorDialog::getColor(
2049                 rgb2qcolor(set_backgroundcolor), asQWidget());
2050         if (!newColor.isValid())
2051                 return;
2052         // set the button color and text
2053         colorModule->backgroundPB->setStyleSheet(
2054                 colorButtonStyleSheet(newColor));
2055         colorModule->backgroundPB->setText(qt_("&Change..."));
2056         // save color
2057         set_backgroundcolor = rgbFromHexName(fromqstr(newColor.name()));
2058         is_backgroundcolor = true;
2059         change_adaptor();
2060 }
2061
2062
2063 void GuiDocument::deleteBackgroundColor()
2064 {
2065         // set the button color back to default by setting an empty StyleSheet
2066         colorModule->backgroundPB->setStyleSheet(QLatin1String(""));
2067         // change button text
2068         colorModule->backgroundPB->setText(qt_("&Default..."));
2069         // save default color (white)
2070         set_backgroundcolor = rgbFromHexName("#ffffff");
2071         is_backgroundcolor = false;
2072         change_adaptor();
2073 }
2074
2075
2076 void GuiDocument::changeFontColor()
2077 {
2078         QColor const & newColor = QColorDialog::getColor(
2079                 rgb2qcolor(set_fontcolor), asQWidget());
2080         if (!newColor.isValid())
2081                 return;
2082         // set the button color and text
2083         colorModule->fontColorPB->setStyleSheet(
2084                 colorButtonStyleSheet(newColor));
2085         colorModule->fontColorPB->setText(qt_("&Change..."));
2086         // save color
2087         set_fontcolor = rgbFromHexName(fromqstr(newColor.name()));
2088         is_fontcolor = true;
2089         change_adaptor();
2090 }
2091
2092
2093 void GuiDocument::deleteFontColor()
2094 {
2095         // set the button color back to default by setting an empty StyleSheet
2096         colorModule->fontColorPB->setStyleSheet(QLatin1String(""));
2097         // change button text
2098         colorModule->fontColorPB->setText(qt_("&Default..."));
2099         // save default color (black)
2100         set_fontcolor = rgbFromHexName("#000000");
2101         is_fontcolor = false;
2102         change_adaptor();
2103 }
2104
2105
2106 void GuiDocument::changeNoteFontColor()
2107 {
2108         QColor const & newColor = QColorDialog::getColor(
2109                 rgb2qcolor(set_notefontcolor), asQWidget());
2110         if (!newColor.isValid())
2111                 return;
2112         // set the button color
2113         colorModule->noteFontColorPB->setStyleSheet(
2114                 colorButtonStyleSheet(newColor));
2115         // save color
2116         set_notefontcolor = rgbFromHexName(fromqstr(newColor.name()));
2117         change_adaptor();
2118 }
2119
2120
2121 void GuiDocument::deleteNoteFontColor()
2122 {
2123         // set the button color back to pref
2124         theApp()->getRgbColor(Color_greyedouttext, set_notefontcolor);
2125         colorModule->noteFontColorPB->setStyleSheet(
2126                 colorButtonStyleSheet(rgb2qcolor(set_notefontcolor)));
2127         change_adaptor();
2128 }
2129
2130
2131 void GuiDocument::changeBoxBackgroundColor()
2132 {
2133         QColor const & newColor = QColorDialog::getColor(
2134                 rgb2qcolor(set_boxbgcolor), asQWidget());
2135         if (!newColor.isValid())
2136                 return;
2137         // set the button color
2138         colorModule->boxBackgroundPB->setStyleSheet(
2139                 colorButtonStyleSheet(newColor));
2140         // save color
2141         set_boxbgcolor = rgbFromHexName(fromqstr(newColor.name()));
2142         change_adaptor();
2143 }
2144
2145
2146 void GuiDocument::deleteBoxBackgroundColor()
2147 {
2148         // set the button color back to pref
2149         theApp()->getRgbColor(Color_shadedbg, set_boxbgcolor);
2150         colorModule->boxBackgroundPB->setStyleSheet(
2151                 colorButtonStyleSheet(rgb2qcolor(set_boxbgcolor)));
2152         change_adaptor();
2153 }
2154
2155
2156 void GuiDocument::updateQuoteStyles(bool const set)
2157 {
2158         Language const * lang = lyx::languages.getLanguage(
2159                 fromqstr(langModule->languageCO->itemData(
2160                         langModule->languageCO->currentIndex()).toString()));
2161
2162         InsetQuotesParams::QuoteStyle def = bp_.getQuoteStyle(lang->quoteStyle());
2163
2164         langModule->quoteStyleCO->clear();
2165
2166         bool has_default = false;
2167         for (int i = 0; i < quoteparams.stylescount(); ++i) {
2168                 InsetQuotesParams::QuoteStyle qs = InsetQuotesParams::QuoteStyle(i);
2169                 if (qs == InsetQuotesParams::DynamicQuotes)
2170                         continue;
2171                 bool const langdef = (qs == def);
2172                 if (langdef) {
2173                         // add the default style on top
2174                         langModule->quoteStyleCO->insertItem(0,
2175                                 toqstr(quoteparams.getGuiLabel(qs, langdef)), qs);
2176                         has_default = true;
2177                 }
2178                 else
2179                         langModule->quoteStyleCO->addItem(
2180                                 toqstr(quoteparams.getGuiLabel(qs, langdef)), qs);
2181         }
2182         if (set && has_default)
2183                 // (re)set to the default style
2184                 langModule->quoteStyleCO->setCurrentIndex(0);
2185 }
2186
2187
2188 void GuiDocument::languageChanged(int i)
2189 {
2190         // some languages only work with Polyglossia
2191         Language const * lang = lyx::languages.getLanguage(
2192                 fromqstr(langModule->languageCO->itemData(i).toString()));
2193         if (lang->babel().empty() && !lang->polyglossia().empty()) {
2194                         // If we force to switch fontspec on, store
2195                         // current state (#8717)
2196                         if (fontModule->osFontsCB->isEnabled())
2197                                 forced_fontspec_activation =
2198                                         !fontModule->osFontsCB->isChecked();
2199                         fontModule->osFontsCB->setChecked(true);
2200                         fontModule->osFontsCB->setEnabled(false);
2201         }
2202         else {
2203                 fontModule->osFontsCB->setEnabled(true);
2204                 // If we have forced to switch fontspec on,
2205                 // restore previous state (#8717)
2206                 if (forced_fontspec_activation)
2207                         fontModule->osFontsCB->setChecked(false);
2208                 forced_fontspec_activation = false;
2209         }
2210
2211         // set appropriate quotation mark style
2212         updateQuoteStyles(true);
2213 }
2214
2215
2216 void GuiDocument::osFontsChanged(bool nontexfonts)
2217 {
2218         bool const tex_fonts = !nontexfonts;
2219         // store current fonts
2220         QString const font_roman = fontModule->fontsRomanCO->itemData(
2221                         fontModule->fontsRomanCO->currentIndex()).toString();
2222         QString const font_sans = fontModule->fontsSansCO->itemData(
2223                         fontModule->fontsSansCO->currentIndex()).toString();
2224         QString const font_typewriter = fontModule->fontsTypewriterCO->itemData(
2225                         fontModule->fontsTypewriterCO->currentIndex()).toString();
2226         QString const font_math = fontModule->fontsMathCO->itemData(
2227                         fontModule->fontsMathCO->currentIndex()).toString();
2228         int const font_sf_scale = fontModule->scaleSansSB->value();
2229         int const font_tt_scale = fontModule->scaleTypewriterSB->value();
2230
2231         updateFontlist();
2232         // store default format
2233         QString const dformat = outputModule->defaultFormatCO->itemData(
2234                 outputModule->defaultFormatCO->currentIndex()).toString();
2235         updateDefaultFormat();
2236         // try to restore default format
2237         int index = outputModule->defaultFormatCO->findData(dformat);
2238         // set to default if format is not found
2239         if (index == -1)
2240                 index = 0;
2241         outputModule->defaultFormatCO->setCurrentIndex(index);
2242
2243         // try to restore fonts which were selected two toggles ago
2244         index = fontModule->fontsRomanCO->findData(fontModule->font_roman);
2245         if (index != -1)
2246                 fontModule->fontsRomanCO->setCurrentIndex(index);
2247         index = fontModule->fontsSansCO->findData(fontModule->font_sans);
2248         if (index != -1)
2249                 fontModule->fontsSansCO->setCurrentIndex(index);
2250         index = fontModule->fontsTypewriterCO->findData(fontModule->font_typewriter);
2251         if (index != -1)
2252                 fontModule->fontsTypewriterCO->setCurrentIndex(index);
2253         index = fontModule->fontsMathCO->findData(fontModule->font_math);
2254         if (index != -1)
2255                 fontModule->fontsMathCO->setCurrentIndex(index);
2256         // save fonts for next next toggle
2257         fontModule->font_roman = font_roman;
2258         fontModule->font_sans = font_sans;
2259         fontModule->font_typewriter = font_typewriter;
2260         fontModule->font_math = font_math;
2261         fontModule->font_sf_scale = font_sf_scale;
2262         fontModule->font_tt_scale = font_tt_scale;
2263
2264         langModule->customEncodingCO->setEnabled(tex_fonts &&
2265                 langModule->encodingCO->itemData(
2266                         langModule->encodingCO->currentIndex()).toString() == "custom");
2267         langModule->encodingCO->setEnabled(tex_fonts);
2268         langModule->noInputencCB->setEnabled(tex_fonts
2269                                              && langModule->encodingCO->currentIndex() < 2);
2270         if (!tex_fonts)
2271                 langModule->noInputencCB->setChecked(false);
2272
2273         fontModule->fontsDefaultCO->setEnabled(tex_fonts);
2274         fontModule->fontsDefaultLA->setEnabled(tex_fonts);
2275         fontModule->cjkFontLE->setEnabled(tex_fonts);
2276         fontModule->cjkFontLA->setEnabled(tex_fonts);
2277
2278         updateFontOptions();
2279
2280         fontModule->fontencLA->setEnabled(tex_fonts);
2281         fontModule->fontencCO->setEnabled(tex_fonts);
2282         if (!tex_fonts)
2283                 fontModule->fontencLE->setEnabled(false);
2284         else
2285                 fontencChanged(fontModule->fontencCO->currentIndex());
2286 }
2287
2288
2289 void GuiDocument::encodingSwitched(int i)
2290 {
2291         langModule->customEncodingCO->setEnabled(
2292                                 !fontModule->osFontsCB->isChecked()
2293                                 && langModule->encodingCO->itemData(i).toString() == "custom");
2294         langModule->noInputencCB->setEnabled(!fontModule->osFontsCB->isChecked()
2295                                              && langModule->encodingCO->currentIndex() < 2);
2296         if (!langModule->noInputencCB->isEnabled())
2297                 langModule->noInputencCB->setChecked(false);
2298
2299 }
2300
2301
2302 void GuiDocument::mathFontChanged(int)
2303 {
2304         updateFontOptions();
2305 }
2306
2307 void GuiDocument::fontOsfToggled(bool state)
2308 {
2309         if (fontModule->osFontsCB->isChecked())
2310                 return;
2311         QString font = fontModule->fontsRomanCO->itemData(
2312                         fontModule->fontsRomanCO->currentIndex()).toString();
2313         if (hasMonolithicExpertSet(font))
2314                 fontModule->fontScCB->setChecked(state);
2315 }
2316
2317
2318 void GuiDocument::fontScToggled(bool state)
2319 {
2320         if (fontModule->osFontsCB->isChecked())
2321                 return;
2322         QString font = fontModule->fontsRomanCO->itemData(
2323                         fontModule->fontsRomanCO->currentIndex()).toString();
2324         if (hasMonolithicExpertSet(font))
2325                 fontModule->fontOsfCB->setChecked(state);
2326 }
2327
2328
2329 void GuiDocument::updateFontOptions()
2330 {
2331         bool const tex_fonts = !fontModule->osFontsCB->isChecked();
2332         QString font;
2333         if (tex_fonts)
2334                 font = fontModule->fontsSansCO->itemData(
2335                                 fontModule->fontsSansCO->currentIndex()).toString();
2336         bool scaleable = providesScale(font);
2337         fontModule->scaleSansSB->setEnabled(scaleable);
2338         fontModule->scaleSansLA->setEnabled(scaleable);
2339         if (tex_fonts)
2340                 font = fontModule->fontsTypewriterCO->itemData(
2341                                 fontModule->fontsTypewriterCO->currentIndex()).toString();
2342         scaleable = providesScale(font);
2343         fontModule->scaleTypewriterSB->setEnabled(scaleable);
2344         fontModule->scaleTypewriterLA->setEnabled(scaleable);
2345         if (tex_fonts)
2346                 font = fontModule->fontsRomanCO->itemData(
2347                                 fontModule->fontsRomanCO->currentIndex()).toString();
2348         fontModule->fontScCB->setEnabled(providesSC(font));
2349         fontModule->fontOsfCB->setEnabled(providesOSF(font));
2350         updateMathFonts(font);
2351 }
2352
2353
2354 void GuiDocument::updateFontsize(string const & items, string const & sel)
2355 {
2356         fontModule->fontsizeCO->clear();
2357         fontModule->fontsizeCO->addItem(qt_("Default"));
2358
2359         for (int n = 0; !token(items,'|',n).empty(); ++n)
2360                 fontModule->fontsizeCO->
2361                         addItem(toqstr(token(items,'|',n)));
2362
2363         for (int n = 0; n < fontModule->fontsizeCO->count(); ++n) {
2364                 if (fromqstr(fontModule->fontsizeCO->itemText(n)) == sel) {
2365                         fontModule->fontsizeCO->setCurrentIndex(n);
2366                         break;
2367                 }
2368         }
2369 }
2370
2371
2372 bool GuiDocument::ot1() const
2373 {
2374         QString const fontenc =
2375                 fontModule->fontencCO->itemData(fontModule->fontencCO->currentIndex()).toString();
2376         int const i = langModule->languageCO->currentIndex();
2377         if (i == -1)
2378                 return false;
2379         QString const langname = langModule->languageCO->itemData(i).toString();
2380         Language const * newlang = lyx::languages.getLanguage(fromqstr(langname));
2381         return (fontenc == "default"
2382                 || (fontenc == "auto" && newlang->fontenc(buffer().params()) == "OT1")
2383                 || (fontenc == "custom" && fontModule->fontencLE->text() == "OT1"));
2384 }
2385
2386
2387 bool GuiDocument::completeFontset() const
2388 {
2389         return (fontModule->fontsSansCO->itemData(
2390                         fontModule->fontsSansCO->currentIndex()).toString() == "default"
2391                 && fontModule->fontsSansCO->itemData(
2392                         fontModule->fontsTypewriterCO->currentIndex()).toString() == "default");
2393 }
2394
2395
2396 bool GuiDocument::noMathFont() const
2397 {
2398         return (fontModule->fontsMathCO->itemData(
2399                 fontModule->fontsMathCO->currentIndex()).toString() == "default");
2400 }
2401
2402
2403 void GuiDocument::updateTexFonts()
2404 {
2405         LaTeXFonts::TexFontMap texfontmap = theLaTeXFonts().getLaTeXFonts();
2406
2407         LaTeXFonts::TexFontMap::const_iterator it = texfontmap.begin();
2408         LaTeXFonts::TexFontMap::const_iterator end = texfontmap.end();
2409         for (; it != end; ++it) {
2410                 LaTeXFont lf = it->second;
2411                 if (lf.name().empty()) {
2412                         LYXERR0("Error: Unnamed font: " << it->first);
2413                         continue;
2414                 }
2415                 docstring const family = lf.family();
2416                 docstring guiname = translateIfPossible(lf.guiname());
2417                 if (!lf.available(ot1(), noMathFont()))
2418                         guiname += _(" (not installed)");
2419                 if (family == "rm")
2420                         rmfonts_.insert(toqstr(guiname), toqstr(it->first));
2421                 else if (family == "sf")
2422                         sffonts_.insert(toqstr(guiname), toqstr(it->first));
2423                 else if (family == "tt")
2424                         ttfonts_.insert(toqstr(guiname), toqstr(it->first));
2425                 else if (family == "math")
2426                         mathfonts_.insert(toqstr(guiname), toqstr(it->first));
2427         }
2428 }
2429
2430
2431 void GuiDocument::updateFontlist()
2432 {
2433         fontModule->fontsRomanCO->clear();
2434         fontModule->fontsSansCO->clear();
2435         fontModule->fontsTypewriterCO->clear();
2436         fontModule->fontsMathCO->clear();
2437
2438         // With fontspec (XeTeX, LuaTeX), we have access to all system fonts, but not the LaTeX fonts
2439         if (fontModule->osFontsCB->isChecked()) {
2440                 fontModule->fontsRomanCO->addItem(qt_("Default"), QString("default"));
2441                 fontModule->fontsSansCO->addItem(qt_("Default"), QString("default"));
2442                 fontModule->fontsTypewriterCO->addItem(qt_("Default"), QString("default"));
2443                 QString unimath = qt_("Non-TeX Fonts Default");
2444                 if (!LaTeXFeatures::isAvailable("unicode-math"))
2445                         unimath += qt_(" (not available)");
2446                 fontModule->fontsMathCO->addItem(qt_("Class Default (TeX Fonts)"), QString("auto"));
2447                 fontModule->fontsMathCO->addItem(unimath, QString("default"));
2448
2449                 QFontDatabase fontdb;
2450                 QStringList families(fontdb.families());
2451                 for (QStringList::Iterator it = families.begin(); it != families.end(); ++it) {
2452                         fontModule->fontsRomanCO->addItem(*it, *it);
2453                         fontModule->fontsSansCO->addItem(*it, *it);
2454                         fontModule->fontsTypewriterCO->addItem(*it, *it);
2455                 }
2456                 return;
2457         }
2458
2459         if (rmfonts_.empty())
2460                 updateTexFonts();
2461
2462         fontModule->fontsRomanCO->addItem(qt_("Default"), QString("default"));
2463         QMap<QString, QString>::const_iterator rmi = rmfonts_.constBegin();
2464         while (rmi != rmfonts_.constEnd()) {
2465                 fontModule->fontsRomanCO->addItem(rmi.key(), rmi.value());
2466                 ++rmi;
2467         }
2468
2469         fontModule->fontsSansCO->addItem(qt_("Default"), QString("default"));
2470         QMap<QString, QString>::const_iterator sfi = sffonts_.constBegin();
2471         while (sfi != sffonts_.constEnd()) {
2472                 fontModule->fontsSansCO->addItem(sfi.key(), sfi.value());
2473                 ++sfi;
2474         }
2475
2476         fontModule->fontsTypewriterCO->addItem(qt_("Default"), QString("default"));
2477         QMap<QString, QString>::const_iterator tti = ttfonts_.constBegin();
2478         while (tti != ttfonts_.constEnd()) {
2479                 fontModule->fontsTypewriterCO->addItem(tti.key(), tti.value());
2480                 ++tti;
2481         }
2482
2483         fontModule->fontsMathCO->addItem(qt_("Automatic"), QString("auto"));
2484         fontModule->fontsMathCO->addItem(qt_("Class Default"), QString("default"));
2485         QMap<QString, QString>::const_iterator mmi = mathfonts_.constBegin();
2486         while (mmi != mathfonts_.constEnd()) {
2487                 fontModule->fontsMathCO->addItem(mmi.key(), mmi.value());
2488                 ++mmi;
2489         }
2490 }
2491
2492
2493 void GuiDocument::fontencChanged(int item)
2494 {
2495         fontModule->fontencLE->setEnabled(
2496                 fontModule->fontencCO->itemData(item).toString() == "custom");
2497         // The availability of TeX fonts depends on the font encoding
2498         updateTexFonts();
2499         updateFontOptions();
2500 }
2501
2502
2503 void GuiDocument::updateMathFonts(QString const & rm)
2504 {
2505         if (fontModule->osFontsCB->isChecked())
2506                 return;
2507         QString const math =
2508                 fontModule->fontsMathCO->itemData(fontModule->fontsMathCO->currentIndex()).toString();
2509         int const i = fontModule->fontsMathCO->findData("default");
2510         if (providesNoMath(rm) && i == -1)
2511                 fontModule->fontsMathCO->insertItem(1, qt_("Class Default"), QString("default"));
2512         else if (!providesNoMath(rm) && i != -1) {
2513                 int const c = fontModule->fontsMathCO->currentIndex();
2514                 fontModule->fontsMathCO->removeItem(i);
2515                 if (c == i)
2516                         fontModule->fontsMathCO->setCurrentIndex(0);
2517         }
2518 }
2519
2520
2521 void GuiDocument::romanChanged(int item)
2522 {
2523         if (fontModule->osFontsCB->isChecked())
2524                 return;
2525         QString const font =
2526                 fontModule->fontsRomanCO->itemData(item).toString();
2527         fontModule->fontScCB->setEnabled(providesSC(font));
2528         fontModule->fontOsfCB->setEnabled(providesOSF(font));
2529         updateMathFonts(font);
2530 }
2531
2532
2533 void GuiDocument::sansChanged(int item)
2534 {
2535         if (fontModule->osFontsCB->isChecked())
2536                 return;
2537         QString const font =
2538                 fontModule->fontsSansCO->itemData(item).toString();
2539         bool scaleable = providesScale(font);
2540         fontModule->scaleSansSB->setEnabled(scaleable);
2541         fontModule->scaleSansLA->setEnabled(scaleable);
2542 }
2543
2544
2545 void GuiDocument::ttChanged(int item)
2546 {
2547         if (fontModule->osFontsCB->isChecked())
2548                 return;
2549         QString const font =
2550                 fontModule->fontsTypewriterCO->itemData(item).toString();
2551         bool scaleable = providesScale(font);
2552         fontModule->scaleTypewriterSB->setEnabled(scaleable);
2553         fontModule->scaleTypewriterLA->setEnabled(scaleable);
2554 }
2555
2556
2557 void GuiDocument::updatePagestyle(string const & items, string const & sel)
2558 {
2559         pagestyles.clear();
2560         pageLayoutModule->pagestyleCO->clear();
2561         pageLayoutModule->pagestyleCO->addItem(qt_("Default"));
2562
2563         for (int n = 0; !token(items, '|', n).empty(); ++n) {
2564                 string style = token(items, '|', n);
2565                 QString style_gui = qt_(style);
2566                 pagestyles.push_back(pair<string, QString>(style, style_gui));
2567                 pageLayoutModule->pagestyleCO->addItem(style_gui);
2568         }
2569
2570         if (sel == "default") {
2571                 pageLayoutModule->pagestyleCO->setCurrentIndex(0);
2572                 return;
2573         }
2574
2575         int nn = 0;
2576
2577         for (size_t i = 0; i < pagestyles.size(); ++i)
2578                 if (pagestyles[i].first == sel)
2579                         nn = pageLayoutModule->pagestyleCO->findText(pagestyles[i].second);
2580
2581         if (nn > 0)
2582                 pageLayoutModule->pagestyleCO->setCurrentIndex(nn);
2583 }
2584
2585
2586 void GuiDocument::browseLayout()
2587 {
2588         QString const label1 = qt_("Lay&outs");
2589         QString const dir1 = toqstr(lyxrc.document_path);
2590         QStringList const filter(qt_("LyX Layout (*.layout)"));
2591         QString file = browseRelToParent(QString(), bufferFilePath(),
2592                 qt_("Local layout file"), filter, false,
2593                 label1, dir1);
2594
2595         if (!file.endsWith(".layout"))
2596                 return;
2597
2598         FileName layoutFile = support::makeAbsPath(fromqstr(file),
2599                 fromqstr(bufferFilePath()));
2600
2601         int const ret = Alert::prompt(_("Local layout file"),
2602                 _("The layout file you have selected is a local layout\n"
2603                   "file, not one in the system or user directory.\n"
2604                   "Your document will not work with this layout if you\n"
2605                   "move the layout file to a different directory."),
2606                   1, 1, _("&Set Layout"), _("&Cancel"));
2607         if (ret == 1)
2608                 return;
2609
2610         // load the layout file
2611         LayoutFileList & bcl = LayoutFileList::get();
2612         string classname = layoutFile.onlyFileName();
2613         // this will update an existing layout if that layout has been loaded before.
2614         LayoutFileIndex name = support::onlyFileName(bcl.addLocalLayout(
2615                 classname.substr(0, classname.size() - 7),
2616                 layoutFile.onlyPath().absFileName()));
2617
2618         if (name.empty()) {
2619                 Alert::error(_("Error"),
2620                         _("Unable to read local layout file."));
2621                 return;
2622         }
2623
2624         const_cast<Buffer &>(buffer()).setLayoutPos(layoutFile.onlyPath().absFileName());
2625
2626         // do not trigger classChanged if there is no change.
2627         if (latexModule->classCO->currentText() == toqstr(name))
2628                 return;
2629
2630         // add to combo box
2631         bool const avail = latexModule->classCO->set(toqstr(name));
2632         if (!avail) {
2633                 LayoutFile const & tc = bcl[name];
2634                 docstring const guiname = translateIfPossible(from_utf8(tc.description()));
2635                 // tooltip sensu "KOMA-Script Article [Class 'scrartcl']"
2636                 QString tooltip = toqstr(bformat(_("%1$s [Class '%2$s']"), guiname, from_utf8(tc.latexname())));
2637                 tooltip += '\n' + qt_("This is a local layout file.");
2638                 latexModule->classCO->addItemSort(toqstr(tc.name()), toqstr(guiname),
2639                                                   toqstr(translateIfPossible(from_utf8(tc.category()))),
2640                                                   tooltip,
2641                                                   true, true, true, true);
2642                 latexModule->classCO->set(toqstr(name));
2643         }
2644
2645         classChanged();
2646 }
2647
2648
2649 void GuiDocument::browseMaster()
2650 {
2651         QString const title = qt_("Select master document");
2652         QString const dir1 = toqstr(lyxrc.document_path);
2653         QString const old = latexModule->childDocLE->text();
2654         QString const docpath = toqstr(support::onlyPath(buffer().absFileName()));
2655         QStringList const filter(qt_("LyX Files (*.lyx)"));
2656         QString file = browseRelToSub(old, docpath, title, filter, false,
2657                 qt_("D&ocuments"), toqstr(lyxrc.document_path));
2658
2659         if (!file.isEmpty())
2660                 latexModule->childDocLE->setText(file);
2661 }
2662
2663
2664 void GuiDocument::classChanged_adaptor()
2665 {
2666         const_cast<Buffer &>(buffer()).setLayoutPos(string());
2667         classChanged();
2668 }
2669
2670
2671 void GuiDocument::classChanged()
2672 {
2673         int idx = latexModule->classCO->currentIndex();
2674         if (idx < 0)
2675                 return;
2676         string const classname = fromqstr(latexModule->classCO->getData(idx));
2677
2678         if (buttonBox->button(QDialogButtonBox::Apply)->isEnabled()) {
2679                 int const ret = Alert::prompt(_("Unapplied changes"),
2680                                 _("Some changes in the dialog were not yet applied.\n"
2681                                 "If you do not apply now, they will be lost after this action."),
2682                                 1, 1, _("&Apply"), _("&Dismiss"));
2683                 if (ret == 0)
2684                         applyView();
2685         }
2686
2687         // We load the TextClass as soon as it is selected. This is
2688         // necessary so that other options in the dialog can be updated
2689         // according to the new class. Note, however, that, if you use
2690         // the scroll wheel when sitting on the combo box, we'll load a
2691         // lot of TextClass objects very quickly....
2692         if (!bp_.setBaseClass(classname, buffer().layoutPos())) {
2693                 Alert::error(_("Error"), _("Unable to set document class."));
2694                 return;
2695         }
2696         if (lyxrc.auto_reset_options)
2697                 bp_.useClassDefaults();
2698
2699         // With the introduction of modules came a distinction between the base
2700         // class and the document class. The former corresponds to the main layout
2701         // file; the latter is that plus the modules (or the document-specific layout,
2702         // or  whatever else there could be). Our parameters come from the document
2703         // class. So when we set the base class, we also need to recreate the document
2704         // class. Otherwise, we still have the old one.
2705         bp_.makeDocumentClass();
2706         paramsToDialog();
2707 }
2708
2709
2710 void GuiDocument::languagePackageChanged(int i)
2711 {
2712          langModule->languagePackageLE->setEnabled(
2713                 langModule->languagePackageCO->itemData(i).toString() == "custom");
2714 }
2715
2716
2717 void GuiDocument::biblioChanged()
2718 {
2719         biblioChanged_ = true;
2720         change_adaptor();
2721 }
2722
2723
2724 void GuiDocument::checkPossibleCiteEngines()
2725 {
2726         // Check if the class provides a specific engine,
2727         // and if so, enforce this.
2728         string force_engine;
2729         if (documentClass().provides("natbib")
2730             || documentClass().provides("natbib-internal"))
2731                 force_engine = "natbib";
2732         else if (documentClass().provides("jurabib"))
2733                 force_engine = "jurabib";
2734         else if (documentClass().provides("biblatex"))
2735                 force_engine = "biblatex";
2736         else if (documentClass().provides("biblatex-natbib"))
2737                 force_engine = "biblatex-natbib";
2738
2739         if (!force_engine.empty())
2740                 biblioModule->citeEngineCO->setCurrentIndex(
2741                         biblioModule->citeEngineCO->findData(toqstr(force_engine)));
2742         biblioModule->citeEngineCO->setEnabled(force_engine.empty());
2743 }
2744
2745
2746 void GuiDocument::rescanBibFiles()
2747 {
2748         if (isBiblatex())
2749                 rescanTexStyles("bbx cbx");
2750         else
2751                 rescanTexStyles("bst");
2752 }
2753
2754
2755 void GuiDocument::resetDefaultBibfile(string const & which)
2756 {
2757         QString const engine =
2758                 biblioModule->citeEngineCO->itemData(
2759                                 biblioModule->citeEngineCO->currentIndex()).toString();
2760
2761         CiteEngineType const cet =
2762                 CiteEngineType(biblioModule->citeStyleCO->itemData(
2763                                                           biblioModule->citeStyleCO->currentIndex()).toInt());
2764
2765         updateDefaultBiblio(theCiteEnginesList[fromqstr(engine)]->getDefaultBiblio(cet), which);
2766 }
2767
2768
2769 void GuiDocument::resetDefaultBbxBibfile()
2770 {
2771         resetDefaultBibfile("bbx");
2772 }
2773
2774
2775 void GuiDocument::resetDefaultCbxBibfile()
2776 {
2777         resetDefaultBibfile("cbx");
2778 }
2779
2780
2781 void GuiDocument::citeEngineChanged(int n)
2782 {
2783         QString const engine =
2784                 biblioModule->citeEngineCO->itemData(n).toString();
2785
2786         vector<string> const engs =
2787                 theCiteEnginesList[fromqstr(engine)]->getEngineType();
2788
2789         updateCiteStyles(engs);
2790         updateEngineDependends();
2791         resetDefaultBibfile();
2792         biblioChanged();
2793 }
2794
2795
2796 void GuiDocument::updateEngineDependends()
2797 {
2798         bool const biblatex = isBiblatex();
2799
2800         // These are only useful with BibTeX
2801         biblioModule->defaultBiblioCO->setEnabled(!biblatex);
2802         biblioModule->bibtexStyleLA->setEnabled(!biblatex);
2803         biblioModule->resetDefaultBiblioPB->setEnabled(!biblatex);
2804         biblioModule->bibtopicCB->setEnabled(!biblatex);
2805
2806         // These are only useful with Biblatex
2807         biblioModule->biblatexBbxCO->setEnabled(biblatex);
2808         biblioModule->biblatexBbxLA->setEnabled(biblatex);
2809         biblioModule->biblatexCbxCO->setEnabled(biblatex);
2810         biblioModule->biblatexCbxLA->setEnabled(biblatex);
2811         biblioModule->resetBbxPB->setEnabled(biblatex);
2812         biblioModule->resetCbxPB->setEnabled(biblatex);
2813         biblioModule->matchBbxPB->setEnabled(biblatex);
2814
2815         // These are useful with biblatex, jurabib and natbib
2816         QString const engine =
2817                 biblioModule->citeEngineCO->itemData(
2818                                 biblioModule->citeEngineCO->currentIndex()).toString();
2819         LyXCiteEngine const * ce = theCiteEnginesList[fromqstr(engine)];
2820
2821         bool const citepack = ce->requires("biblatex.sty") || ce->requires("jurabib.sty")
2822                         || ce->requires("natbib.sty");
2823         biblioModule->citePackageOptionsLE->setEnabled(citepack);
2824         biblioModule->citePackageOptionsL->setEnabled(citepack);
2825 }
2826
2827
2828 void GuiDocument::citeStyleChanged()
2829 {
2830         QString const engine =
2831                 biblioModule->citeEngineCO->itemData(
2832                                 biblioModule->citeEngineCO->currentIndex()).toString();
2833         QString const currentDef = isBiblatex() ?
2834                 biblioModule->biblatexBbxCO->currentText()
2835                 : biblioModule->defaultBiblioCO->currentText();
2836         if (theCiteEnginesList[fromqstr(engine)]->isDefaultBiblio(fromqstr(currentDef)))
2837                 resetDefaultBibfile();
2838
2839         biblioChanged();
2840 }
2841
2842
2843 void GuiDocument::bibtexChanged(int n)
2844 {
2845         biblioModule->bibtexOptionsLE->setEnabled(
2846                 biblioModule->bibtexCO->itemData(n).toString() != "default");
2847         biblioChanged();
2848 }
2849
2850
2851 void GuiDocument::updateCiteStyles(vector<string> const & engs, CiteEngineType const & sel)
2852 {
2853         biblioModule->citeStyleCO->clear();
2854
2855         vector<string>::const_iterator it  = engs.begin();
2856         vector<string>::const_iterator end = engs.end();
2857         for (; it != end; ++it) {
2858                 if (*it == "default")
2859                         biblioModule->citeStyleCO->addItem(qt_("Basic numerical"),
2860                                                            ENGINE_TYPE_DEFAULT);
2861                 else if (*it == "authoryear")
2862                         biblioModule->citeStyleCO->addItem(qt_("Author-year"),
2863                                                            ENGINE_TYPE_AUTHORYEAR);
2864                 else if (*it == "numerical")
2865                         biblioModule->citeStyleCO->addItem(qt_("Author-number"),
2866                                                            ENGINE_TYPE_NUMERICAL);
2867         }
2868         int i = biblioModule->citeStyleCO->findData(sel);
2869         if (biblioModule->citeStyleCO->findData(sel) == -1)
2870                 i = 0;
2871         biblioModule->citeStyleCO->setCurrentIndex(i);
2872
2873         biblioModule->citationStyleL->setEnabled(engs.size() > 1);
2874         biblioModule->citeStyleCO->setEnabled(engs.size() > 1);
2875 }
2876
2877
2878 void GuiDocument::updateEngineType(string const & items, CiteEngineType const & sel)
2879 {
2880         engine_types_.clear();
2881
2882         int nn = 0;
2883
2884         for (int n = 0; !token(items, '|', n).empty(); ++n) {
2885                 nn += 1;
2886                 string style = token(items, '|', n);
2887                 engine_types_.push_back(style);
2888         }
2889
2890         updateCiteStyles(engine_types_, sel);
2891 }
2892
2893
2894 namespace {
2895         // FIXME unicode
2896         // both of these should take a vector<docstring>
2897
2898         // This is an insanely complicated attempt to make this sort of thing
2899         // work with RTL languages.
2900         docstring formatStrVec(vector<string> const & v, docstring const & s)
2901         {
2902                 //this mess formats the list as "v[0], v[1], ..., [s] v[n]"
2903                 if (v.empty())
2904                         return docstring();
2905                 if (v.size() == 1)
2906                         return translateIfPossible(from_utf8(v[0]));
2907                 if (v.size() == 2) {
2908                         docstring retval = _("%1$s and %2$s");
2909                         retval = subst(retval, _("and"), s);
2910                         return bformat(retval, translateIfPossible(from_utf8(v[0])),
2911                                        translateIfPossible(from_utf8(v[1])));
2912                 }
2913                 // The idea here is to format all but the last two items...
2914                 int const vSize = v.size();
2915                 docstring t2 = _("%1$s, %2$s");
2916                 docstring retval = translateIfPossible(from_utf8(v[0]));
2917                 for (int i = 1; i < vSize - 2; ++i)
2918                         retval = bformat(t2, retval, translateIfPossible(from_utf8(v[i])));
2919                 //...and then to  plug them, and the last two, into this schema
2920                 docstring t = _("%1$s, %2$s, and %3$s");
2921                 t = subst(t, _("and"), s);
2922                 return bformat(t, retval, translateIfPossible(from_utf8(v[vSize - 2])),
2923                                translateIfPossible(from_utf8(v[vSize - 1])));
2924         }
2925
2926         vector<string> idsToNames(vector<string> const & idList)
2927         {
2928                 vector<string> retval;
2929                 vector<string>::const_iterator it  = idList.begin();
2930                 vector<string>::const_iterator end = idList.end();
2931                 for (; it != end; ++it) {
2932                         LyXModule const * const mod = theModuleList[*it];
2933                         if (!mod)
2934                                 retval.push_back(to_utf8(bformat(_("%1$s (unavailable)"),
2935                                                 translateIfPossible(from_utf8(*it)))));
2936                         else
2937                                 retval.push_back(mod->getName());
2938                 }
2939                 return retval;
2940         }
2941 } // end anonymous namespace
2942
2943
2944 void GuiDocument::modulesToParams(BufferParams & bp)
2945 {
2946         // update list of loaded modules
2947         bp.clearLayoutModules();
2948         int const srows = modules_sel_model_.rowCount();
2949         for (int i = 0; i < srows; ++i)
2950                 bp.addLayoutModule(modules_sel_model_.getIDString(i));
2951         updateSelectedModules();
2952
2953         // update the list of removed modules
2954         bp.clearRemovedModules();
2955         LayoutModuleList const & reqmods = bp.baseClass()->defaultModules();
2956         list<string>::const_iterator rit = reqmods.begin();
2957         list<string>::const_iterator ren = reqmods.end();
2958
2959         // check each of the default modules
2960         for (; rit != ren; ++rit) {
2961                 list<string>::const_iterator mit = bp.getModules().begin();
2962                 list<string>::const_iterator men = bp.getModules().end();
2963                 bool found = false;
2964                 for (; mit != men; ++mit) {
2965                         if (*rit == *mit) {
2966                                 found = true;
2967                                 break;
2968                         }
2969                 }
2970                 if (!found) {
2971                         // the module isn't present so must have been removed by the user
2972                         bp.addRemovedModule(*rit);
2973                 }
2974         }
2975 }
2976
2977 void GuiDocument::modulesChanged()
2978 {
2979         modulesToParams(bp_);
2980
2981         if (buttonBox->button(QDialogButtonBox::Apply)->isEnabled()
2982             && (nonModuleChanged_ || shellescapeChanged_)) {
2983                 int const ret = Alert::prompt(_("Unapplied changes"),
2984                                 _("Some changes in the dialog were not yet applied.\n"
2985                                 "If you do not apply now, they will be lost after this action."),
2986                                 1, 1, _("&Apply"), _("&Dismiss"));
2987                 if (ret == 0)
2988                         applyView();
2989         }
2990
2991         modulesChanged_ = true;
2992         bp_.makeDocumentClass();
2993         paramsToDialog();
2994         changed();
2995 }
2996
2997
2998 void GuiDocument::updateModuleInfo()
2999 {
3000         selectionManager->update();
3001
3002         //Module description
3003         bool const focus_on_selected = selectionManager->selectedFocused();
3004         QAbstractItemView * lv;
3005         bool category = false;
3006         if (focus_on_selected) {
3007                 lv = modulesModule->selectedLV;
3008                 category = true;
3009         } else
3010                 lv = modulesModule->availableLV;
3011         if (lv->selectionModel()->selectedIndexes().isEmpty()) {
3012                 modulesModule->infoML->document()->clear();
3013                 return;
3014         }
3015         QModelIndex const & idx = lv->selectionModel()->currentIndex();
3016
3017         if (!focus_on_selected
3018             && modules_av_model_.itemFromIndex(idx)->hasChildren()) {
3019                 // This is a category header
3020                 modulesModule->infoML->document()->clear();
3021                 return;
3022         }
3023
3024         string const modName = focus_on_selected ?
3025                                 modules_sel_model_.getIDString(idx.row())
3026                               : fromqstr(modules_av_model_.data(idx, Qt::UserRole).toString());
3027         docstring desc = getModuleDescription(modName);
3028
3029         LayoutModuleList const & provmods = bp_.baseClass()->providedModules();
3030         if (std::find(provmods.begin(), provmods.end(), modName) != provmods.end()) {
3031                 if (!desc.empty())
3032                         desc += "\n";
3033                 desc += _("Module provided by document class.");
3034         }
3035
3036         if (category) {
3037                 docstring cat = getModuleCategory(modName);
3038                 if (!cat.empty()) {
3039                         if (!desc.empty())
3040                                 desc += "\n";
3041                         desc += bformat(_("<p><b>Category:</b> %1$s.</p>"),
3042                                         translateIfPossible(cat));
3043                 }
3044         }
3045
3046         vector<string> pkglist = getPackageList(modName);
3047         docstring pkgdesc = formatStrVec(pkglist, _("and"));
3048         if (!pkgdesc.empty()) {
3049                 if (!desc.empty())
3050                         desc += "\n";
3051                 desc += bformat(_("<p><b>Package(s) required:</b> %1$s.</p>"), pkgdesc);
3052         }
3053
3054         pkglist = getRequiredList(modName);
3055         if (!pkglist.empty()) {
3056                 vector<string> const reqdescs = idsToNames(pkglist);
3057                 pkgdesc = formatStrVec(reqdescs, _("or"));
3058                 if (!desc.empty())
3059                         desc += "\n";
3060                 desc += bformat(_("<p><b>Modules required:</b> %1$s.</p>"), pkgdesc);
3061         }
3062
3063         pkglist = getExcludedList(modName);
3064         if (!pkglist.empty()) {
3065                 vector<string> const reqdescs = idsToNames(pkglist);
3066                 pkgdesc = formatStrVec(reqdescs, _( "and"));
3067                 if (!desc.empty())
3068                         desc += "\n";
3069                 desc += bformat(_("<p><b>Modules excluded:</b> %1$s.</p>"), pkgdesc);
3070         }
3071
3072         if (!desc.empty())
3073                 desc += "\n";
3074         desc += bformat(_("<p><b>Filename:</b> <tt>%1$s.module</tt>.</p>"), from_utf8(modName));
3075
3076         if (!isModuleAvailable(modName)) {
3077                 if (!desc.empty())
3078                         desc += "\n";
3079                 desc += _("<p><font color=red><b>WARNING: Some required packages are unavailable!</b></font></p>");
3080         }
3081
3082         modulesModule->infoML->document()->setHtml(toqstr(desc));
3083 }
3084
3085
3086 void GuiDocument::updateNumbering()
3087 {
3088         DocumentClass const & tclass = documentClass();
3089
3090         numberingModule->tocTW->setUpdatesEnabled(false);
3091         numberingModule->tocTW->clear();
3092
3093         int const depth = numberingModule->depthSL->value();
3094         int const toc = numberingModule->tocSL->value();
3095         QString const no = qt_("No");
3096         QString const yes = qt_("Yes");
3097         QTreeWidgetItem * item = 0;
3098
3099         DocumentClass::const_iterator lit = tclass.begin();
3100         DocumentClass::const_iterator len = tclass.end();
3101         for (; lit != len; ++lit) {
3102                 int const toclevel = lit->toclevel;
3103                 if (toclevel != Layout::NOT_IN_TOC && !lit->counter.empty()) {
3104                         item = new QTreeWidgetItem(numberingModule->tocTW);
3105                         item->setText(0, toqstr(translateIfPossible(lit->name())));
3106                         item->setText(1, (toclevel <= depth) ? yes : no);
3107                         item->setText(2, (toclevel <= toc) ? yes : no);
3108                 }
3109         }
3110
3111         numberingModule->tocTW->setUpdatesEnabled(true);
3112         numberingModule->tocTW->update();
3113 }
3114
3115
3116 void GuiDocument::getTableStyles()
3117 {
3118         // We look for lyx files in the subdirectory dir of
3119         //   1) user_lyxdir
3120         //   2) build_lyxdir (if not empty)
3121         //   3) system_lyxdir
3122         // in this order. Files with a given sub-hierarchy will
3123         // only be listed once.
3124         // We also consider i18n subdirectories and store them separately.
3125         QStringList dirs;
3126
3127         // The three locations to look at.
3128         string const user = addPath(package().user_support().absFileName(), "tabletemplates");
3129         string const build = addPath(package().build_support().absFileName(), "tabletemplates");
3130         string const system = addPath(package().system_support().absFileName(), "tabletemplates");
3131
3132         dirs << toqstr(user)
3133              << toqstr(build)
3134              << toqstr(system);
3135
3136         for (int i = 0; i < dirs.size(); ++i) {
3137                 QString const dir = dirs.at(i);
3138                 QDirIterator it(dir, QDir::Files, QDirIterator::Subdirectories);
3139                 while (it.hasNext()) {
3140                         QString fn = QFileInfo(it.next()).fileName();
3141                         if (!fn.endsWith(".lyx") || fn.contains("_1x"))
3142                                 continue;
3143                         QString data = fn.left(fn.lastIndexOf(".lyx"));
3144                         QString guiname = data;
3145                         guiname = toqstr(translateIfPossible(qstring_to_ucs4(guiname.replace('_', ' '))));
3146                         QString relpath = toqstr(makeRelPath(qstring_to_ucs4(fn),
3147                                                              qstring_to_ucs4(dir)));
3148                         if (textLayoutModule->tableStyleCO->findData(data) == -1)
3149                                 textLayoutModule->tableStyleCO->addItem(guiname, data);
3150                 }
3151         }
3152 }
3153
3154
3155 void GuiDocument::updateDefaultFormat()
3156 {
3157         if (!bufferview())
3158                 return;
3159         // make a copy in order to consider unapplied changes
3160         BufferParams param_copy = buffer().params();
3161         param_copy.useNonTeXFonts = fontModule->osFontsCB->isChecked();
3162         int const idx = latexModule->classCO->currentIndex();
3163         if (idx >= 0) {
3164                 string const classname = fromqstr(latexModule->classCO->getData(idx));
3165                 param_copy.setBaseClass(classname, buffer().layoutPos());
3166                 param_copy.makeDocumentClass(true);
3167         }
3168         outputModule->defaultFormatCO->blockSignals(true);
3169         outputModule->defaultFormatCO->clear();
3170         outputModule->defaultFormatCO->addItem(qt_("Default"),
3171                                 QVariant(QString("default")));
3172         FormatList const & formats =
3173                                 param_copy.exportableFormats(true);
3174         for (Format const * f : formats)
3175                 outputModule->defaultFormatCO->addItem
3176                         (toqstr(translateIfPossible(f->prettyname())),
3177                          QVariant(toqstr(f->name())));
3178         outputModule->defaultFormatCO->blockSignals(false);
3179 }
3180
3181
3182 bool GuiDocument::isChildIncluded(string const & child)
3183 {
3184         if (includeonlys_.empty())
3185                 return false;
3186         return (std::find(includeonlys_.begin(),
3187                           includeonlys_.end(), child) != includeonlys_.end());
3188 }
3189
3190
3191 void GuiDocument::applyView()
3192 {
3193         // preamble
3194         preambleModule->apply(bp_);
3195         localLayout->apply(bp_);
3196
3197         // date
3198         bp_.suppress_date = latexModule->suppressDateCB->isChecked();
3199         bp_.use_refstyle  = latexModule->refstyleCB->isChecked();
3200
3201         // biblio
3202         string const engine =
3203                 fromqstr(biblioModule->citeEngineCO->itemData(
3204                                 biblioModule->citeEngineCO->currentIndex()).toString());
3205         bp_.setCiteEngine(engine);
3206
3207         CiteEngineType const style = CiteEngineType(biblioModule->citeStyleCO->itemData(
3208                 biblioModule->citeStyleCO->currentIndex()).toInt());
3209         if (theCiteEnginesList[engine]->hasEngineType(style))
3210                 bp_.setCiteEngineType(style);
3211         else
3212                 bp_.setCiteEngineType(ENGINE_TYPE_DEFAULT);
3213
3214         bp_.splitbib(biblioModule->bibtopicCB->isChecked());
3215
3216         bp_.multibib = fromqstr(biblioModule->bibunitsCO->itemData(
3217                                 biblioModule->bibunitsCO->currentIndex()).toString());
3218
3219         bp_.setDefaultBiblioStyle(fromqstr(biblioModule->defaultBiblioCO->currentText()));
3220
3221         bp_.biblatex_bibstyle = fromqstr(biblioModule->biblatexBbxCO->currentText());
3222         bp_.biblatex_citestyle = fromqstr(biblioModule->biblatexCbxCO->currentText());
3223         bp_.biblio_opts = fromqstr(biblioModule->citePackageOptionsLE->text());
3224
3225         string const bibtex_command =
3226                 fromqstr(biblioModule->bibtexCO->itemData(
3227                         biblioModule->bibtexCO->currentIndex()).toString());
3228         string const bibtex_options =
3229                 fromqstr(biblioModule->bibtexOptionsLE->text());
3230         if (bibtex_command == "default" || bibtex_options.empty())
3231                 bp_.bibtex_command = bibtex_command;
3232         else
3233                 bp_.bibtex_command = bibtex_command + " " + bibtex_options;
3234
3235         if (biblioChanged_) {
3236                 buffer().invalidateBibinfoCache();
3237                 buffer().removeBiblioTempFiles();
3238         }
3239
3240         // Indices
3241         indicesModule->apply(bp_);
3242
3243         // language & quotes
3244         QString const encoding = langModule->encodingCO->itemData(
3245                                 langModule->encodingCO->currentIndex()).toString();
3246         if (encoding != "custom")
3247                 bp_.inputenc = fromqstr(encoding);
3248         else
3249                 bp_.inputenc = fromqstr(langModule->customEncodingCO->itemData(
3250                                         langModule->customEncodingCO->currentIndex()).toString());
3251         if (langModule->noInputencCB->isChecked()
3252             && (encoding == "auto-legacy" || encoding == "utf8"))
3253                 bp_.inputenc += "-plain";
3254
3255         bp_.quotes_style = (InsetQuotesParams::QuoteStyle) langModule->quoteStyleCO->itemData(
3256                 langModule->quoteStyleCO->currentIndex()).toInt();
3257         bp_.dynamic_quotes = langModule->dynamicQuotesCB->isChecked();
3258
3259         QString const langname = langModule->languageCO->itemData(
3260                 langModule->languageCO->currentIndex()).toString();
3261         Language const * newlang = lyx::languages.getLanguage(fromqstr(langname));
3262         Cursor & cur = const_cast<BufferView *>(bufferview())->cursor();
3263         // If current cursor language was the document language, then update it too.
3264         if (cur.current_font.language() == bp_.language) {
3265                 cur.current_font.setLanguage(newlang);
3266                 cur.real_current_font.setLanguage(newlang);
3267         }
3268         bp_.language = newlang;
3269
3270         QString const pack = langModule->languagePackageCO->itemData(
3271                 langModule->languagePackageCO->currentIndex()).toString();
3272         if (pack == "custom")
3273                 bp_.lang_package =
3274                         fromqstr(langModule->languagePackageLE->text());
3275         else
3276                 bp_.lang_package = fromqstr(pack);
3277
3278         //color
3279         bp_.backgroundcolor = set_backgroundcolor;
3280         bp_.isbackgroundcolor = is_backgroundcolor;
3281         bp_.fontcolor = set_fontcolor;
3282         bp_.isfontcolor = is_fontcolor;
3283         bp_.notefontcolor = set_notefontcolor;
3284         bp_.boxbgcolor = set_boxbgcolor;
3285
3286         // numbering
3287         if (bp_.documentClass().hasTocLevels()) {
3288                 bp_.tocdepth = numberingModule->tocSL->value();
3289                 bp_.secnumdepth = numberingModule->depthSL->value();
3290         }
3291         bp_.use_lineno = numberingModule->linenoCB->isChecked();
3292         bp_.lineno_opts = fromqstr(numberingModule->linenoLE->text());
3293
3294         // bullets
3295         bp_.user_defined_bullet(0) = bulletsModule->bullet(0);
3296         bp_.user_defined_bullet(1) = bulletsModule->bullet(1);
3297         bp_.user_defined_bullet(2) = bulletsModule->bullet(2);
3298         bp_.user_defined_bullet(3) = bulletsModule->bullet(3);
3299
3300         // packages
3301         bp_.graphics_driver =
3302                 tex_graphics[latexModule->psdriverCO->currentIndex()];
3303
3304         // text layout
3305         int idx = latexModule->classCO->currentIndex();
3306         if (idx >= 0) {
3307                 string const classname = fromqstr(latexModule->classCO->getData(idx));
3308                 bp_.setBaseClass(classname, buffer().layoutPos());
3309         }
3310
3311         // Modules
3312         modulesToParams(bp_);
3313
3314         // Math
3315         map<string, string> const & packages = BufferParams::auto_packages();
3316         for (map<string, string>::const_iterator it = packages.begin();
3317              it != packages.end(); ++it) {
3318                 QTableWidgetItem * item = mathsModule->packagesTW->findItems(toqstr(it->first), Qt::MatchExactly)[0];
3319                 if (!item)
3320                         continue;
3321                 int row = mathsModule->packagesTW->row(item);
3322
3323                 QRadioButton * rb =
3324                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 1)->layout()->itemAt(0)->widget();
3325                 if (rb->isChecked()) {
3326                         bp_.use_package(it->first, BufferParams::package_auto);
3327                         continue;
3328                 }
3329                 rb = (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 2)->layout()->itemAt(0)->widget();
3330                 if (rb->isChecked()) {
3331                         bp_.use_package(it->first, BufferParams::package_on);
3332                         continue;
3333                 }
3334                 rb = (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 3)->layout()->itemAt(0)->widget();
3335                 if (rb->isChecked())
3336                         bp_.use_package(it->first, BufferParams::package_off);
3337         }
3338         // if math is indented
3339         bp_.is_math_indent = mathsModule->MathIndentCB->isChecked();
3340         if (bp_.is_math_indent) {
3341                 // if formulas are indented
3342                 switch (mathsModule->MathIndentCO->currentIndex()) {
3343                 case 0:
3344                         bp_.setMathIndent(Length());
3345                         break;
3346                 case 1: {
3347                         Length mathindent(widgetsToLength(mathsModule->MathIndentLE,
3348                                                           mathsModule->MathIndentLengthCO));
3349                         bp_.setMathIndent(mathindent);
3350                         break;
3351                 }
3352                 default:
3353                         // this should never happen
3354                         bp_.setMathIndent(Length());
3355                         break;
3356                 }
3357         }
3358         switch (mathsModule->MathNumberingPosCO->currentIndex()) {
3359                 case 0:
3360                         bp_.math_numbering_side = BufferParams::LEFT;
3361                         break;
3362                 case 1:
3363                         bp_.math_numbering_side = BufferParams::DEFAULT;
3364                         break;
3365                 case 2:
3366                         bp_.math_numbering_side = BufferParams::RIGHT;
3367                         break;
3368                 default:
3369                         // this should never happen
3370                         bp_.math_numbering_side = BufferParams::DEFAULT;
3371                         break;
3372         }
3373
3374         // Page Layout
3375         if (pageLayoutModule->pagestyleCO->currentIndex() == 0)
3376                 bp_.pagestyle = "default";
3377         else {
3378                 QString style_gui = pageLayoutModule->pagestyleCO->currentText();
3379                 for (size_t i = 0; i != pagestyles.size(); ++i)
3380                         if (pagestyles[i].second == style_gui)
3381                                 bp_.pagestyle = pagestyles[i].first;
3382         }
3383
3384         // Text Layout
3385         switch (textLayoutModule->lspacingCO->currentIndex()) {
3386         case 0:
3387                 bp_.spacing().set(Spacing::Single);
3388                 break;
3389         case 1:
3390                 bp_.spacing().set(Spacing::Onehalf);
3391                 break;
3392         case 2:
3393                 bp_.spacing().set(Spacing::Double);
3394                 break;
3395         case 3: {
3396                 string s = widgetToDoubleStr(textLayoutModule->lspacingLE);
3397                 if (s.empty())
3398                         bp_.spacing().set(Spacing::Single);
3399                 else
3400                         bp_.spacing().set(Spacing::Other, s);
3401                 break;
3402                 }
3403         }
3404
3405         if (textLayoutModule->twoColumnCB->isChecked())
3406                 bp_.columns = 2;
3407         else
3408                 bp_.columns = 1;
3409
3410         bp_.justification = textLayoutModule->justCB->isChecked();
3411
3412         if (textLayoutModule->indentRB->isChecked()) {
3413                 // if paragraphs are separated by an indentation
3414                 bp_.paragraph_separation = BufferParams::ParagraphIndentSeparation;
3415                 switch (textLayoutModule->indentCO->currentIndex()) {
3416                 case 0:
3417                         bp_.setParIndent(Length());
3418                         break;
3419                 case 1: {
3420                         Length parindent(widgetsToLength(textLayoutModule->indentLE,
3421                                                          textLayoutModule->indentLengthCO));
3422                         bp_.setParIndent(parindent);
3423                         break;
3424                 }
3425                 default:
3426                         // this should never happen
3427                         bp_.setParIndent(Length());
3428                         break;
3429                 }
3430         } else {
3431                 // if paragraphs are separated by a skip
3432                 bp_.paragraph_separation = BufferParams::ParagraphSkipSeparation;
3433                 switch (textLayoutModule->skipCO->currentIndex()) {
3434                 case 0:
3435                         bp_.setDefSkip(VSpace(VSpace::SMALLSKIP));
3436                         break;
3437                 case 1:
3438                         bp_.setDefSkip(VSpace(VSpace::MEDSKIP));
3439                         break;
3440                 case 2:
3441                         bp_.setDefSkip(VSpace(VSpace::BIGSKIP));
3442                         break;
3443                 case 3:
3444                         {
3445                         VSpace vs = VSpace(
3446                                 widgetsToLength(textLayoutModule->skipLE,
3447                                 textLayoutModule->skipLengthCO)
3448                                 );
3449                         bp_.setDefSkip(vs);
3450                         break;
3451                         }
3452                 default:
3453                         // this should never happen
3454                         bp_.setDefSkip(VSpace(VSpace::MEDSKIP));
3455                         break;
3456                 }
3457         }
3458         bp_.tablestyle = fromqstr(textLayoutModule->tableStyleCO->itemData(
3459                                       textLayoutModule->tableStyleCO->currentIndex()).toString());
3460
3461         bp_.options =
3462                 fromqstr(latexModule->optionsLE->text());
3463
3464         bp_.use_default_options =
3465                 latexModule->defaultOptionsCB->isChecked();
3466
3467         if (latexModule->childDocGB->isChecked())
3468                 bp_.master =
3469                         fromqstr(latexModule->childDocLE->text());
3470         else
3471                 bp_.master = string();
3472
3473         // Master/Child
3474         bp_.clearIncludedChildren();
3475         if (masterChildModule->includeonlyRB->isChecked()) {
3476                 list<string>::const_iterator it = includeonlys_.begin();
3477                 for (; it != includeonlys_.end() ; ++it) {
3478                         bp_.addIncludedChildren(*it);
3479                 }
3480         }
3481         bp_.maintain_unincluded_children =
3482                 masterChildModule->maintainAuxCB->isChecked();
3483
3484         // Float Settings
3485         bp_.float_placement = floatModule->getPlacement();
3486         bp_.float_alignment = floatModule->getAlignment();
3487
3488         // Listings
3489         // text should have passed validation
3490         idx = listingsModule->packageCO->currentIndex();
3491         bp_.use_minted = string(lst_packages[idx]) == "Minted";
3492         bp_.listings_params =
3493                 InsetListingsParams(fromqstr(listingsModule->listingsED->toPlainText())).params();
3494
3495         // Formats
3496         bp_.default_output_format = fromqstr(outputModule->defaultFormatCO->itemData(
3497                 outputModule->defaultFormatCO->currentIndex()).toString());
3498
3499         bool const nontexfonts = fontModule->osFontsCB->isChecked();
3500         bp_.useNonTeXFonts = nontexfonts;
3501
3502         bp_.shell_escape = outputModule->shellescapeCB->isChecked();
3503         if (!bp_.shell_escape)
3504             theSession().shellescapeFiles().remove(buffer().absFileName());
3505         else if (!theSession().shellescapeFiles().find(buffer().absFileName()))
3506             theSession().shellescapeFiles().insert(buffer().absFileName());
3507         Buffer & buf = const_cast<Buffer &>(buffer());
3508         buf.params().shell_escape = bp_.shell_escape;
3509
3510         bp_.output_sync = outputModule->outputsyncCB->isChecked();
3511
3512         bp_.output_sync_macro = fromqstr(outputModule->synccustomCB->currentText());
3513
3514         int mathfmt = outputModule->mathoutCB->currentIndex();
3515         if (mathfmt == -1)
3516                 mathfmt = 0;
3517         BufferParams::MathOutput const mo =
3518                 static_cast<BufferParams::MathOutput>(mathfmt);
3519         bp_.html_math_output = mo;
3520         bp_.html_be_strict = outputModule->strictCB->isChecked();
3521         bp_.html_css_as_file = outputModule->cssCB->isChecked();
3522         bp_.html_math_img_scale = outputModule->mathimgSB->value();
3523         bp_.display_pixel_ratio = theGuiApp()->pixelRatio();
3524
3525         bp_.save_transient_properties =
3526                 outputModule->saveTransientPropertiesCB->isChecked();
3527
3528         // fonts
3529         bp_.fonts_roman[nontexfonts] =
3530                 fromqstr(fontModule->fontsRomanCO->
3531                         itemData(fontModule->fontsRomanCO->currentIndex()).toString());
3532         bp_.fonts_roman[!nontexfonts] = fromqstr(fontModule->font_roman);
3533
3534         bp_.fonts_sans[nontexfonts] =
3535                 fromqstr(fontModule->fontsSansCO->
3536                         itemData(fontModule->fontsSansCO->currentIndex()).toString());
3537         bp_.fonts_sans[!nontexfonts] = fromqstr(fontModule->font_sans);
3538
3539         bp_.fonts_typewriter[nontexfonts] =
3540                 fromqstr(fontModule->fontsTypewriterCO->
3541                         itemData(fontModule->fontsTypewriterCO->currentIndex()).toString());
3542         bp_.fonts_typewriter[!nontexfonts] = fromqstr(fontModule->font_typewriter);
3543
3544         bp_.fonts_math[nontexfonts] =
3545                 fromqstr(fontModule->fontsMathCO->
3546                         itemData(fontModule->fontsMathCO->currentIndex()).toString());
3547         bp_.fonts_math[!nontexfonts] = fromqstr(fontModule->font_math);
3548
3549         QString const fontenc =
3550                 fontModule->fontencCO->itemData(fontModule->fontencCO->currentIndex()).toString();
3551         if (fontenc == "custom")
3552                 bp_.fontenc = fromqstr(fontModule->fontencLE->text());
3553         else
3554                 bp_.fontenc = fromqstr(fontenc);
3555
3556         bp_.fonts_cjk =
3557                 fromqstr(fontModule->cjkFontLE->text());
3558
3559         bp_.use_microtype = fontModule->microtypeCB->isChecked();
3560         bp_.use_dash_ligatures = !fontModule->dashesCB->isChecked();
3561
3562         bp_.fonts_sans_scale[nontexfonts] = fontModule->scaleSansSB->value();
3563         bp_.fonts_sans_scale[!nontexfonts] = fontModule->font_sf_scale;
3564
3565         bp_.fonts_typewriter_scale[nontexfonts] = fontModule->scaleTypewriterSB->value();
3566         bp_.fonts_typewriter_scale[!nontexfonts] = fontModule->font_tt_scale;
3567
3568         bp_.fonts_expert_sc = fontModule->fontScCB->isChecked();
3569
3570         bp_.fonts_old_figures = fontModule->fontOsfCB->isChecked();
3571
3572         if (nontexfonts)
3573                 bp_.fonts_default_family = "default";
3574         else
3575                 bp_.fonts_default_family = GuiDocument::fontfamilies[
3576                         fontModule->fontsDefaultCO->currentIndex()];
3577
3578         if (fontModule->fontsizeCO->currentIndex() == 0)
3579                 bp_.fontsize = "default";
3580         else
3581                 bp_.fontsize =
3582                         fromqstr(fontModule->fontsizeCO->currentText());
3583
3584         // paper
3585         bp_.papersize = PAPER_SIZE(
3586                 pageLayoutModule->papersizeCO->currentIndex());
3587
3588         bp_.paperwidth = widgetsToLength(pageLayoutModule->paperwidthLE,
3589                 pageLayoutModule->paperwidthUnitCO);
3590
3591         bp_.paperheight = widgetsToLength(pageLayoutModule->paperheightLE,
3592                 pageLayoutModule->paperheightUnitCO);
3593
3594         if (pageLayoutModule->facingPagesCB->isChecked())
3595                 bp_.sides = TwoSides;
3596         else
3597                 bp_.sides = OneSide;
3598
3599         if (pageLayoutModule->landscapeRB->isChecked())
3600                 bp_.orientation = ORIENTATION_LANDSCAPE;
3601         else
3602                 bp_.orientation = ORIENTATION_PORTRAIT;
3603
3604         // margins
3605         bp_.use_geometry = !marginsModule->marginCB->isChecked();
3606
3607         Ui::MarginsUi const * m = marginsModule;
3608
3609         bp_.leftmargin = widgetsToLength(m->innerLE, m->innerUnit);
3610         bp_.topmargin = widgetsToLength(m->topLE, m->topUnit);
3611         bp_.rightmargin = widgetsToLength(m->outerLE, m->outerUnit);
3612         bp_.bottommargin = widgetsToLength(m->bottomLE, m->bottomUnit);
3613         bp_.headheight = widgetsToLength(m->headheightLE, m->headheightUnit);
3614         bp_.headsep = widgetsToLength(m->headsepLE, m->headsepUnit);
3615         bp_.footskip = widgetsToLength(m->footskipLE, m->footskipUnit);
3616         bp_.columnsep = widgetsToLength(m->columnsepLE, m->columnsepUnit);
3617
3618         // branches
3619         branchesModule->apply(bp_);
3620
3621         // PDF support
3622         PDFOptions & pdf = bp_.pdfoptions();
3623         pdf.use_hyperref = pdfSupportModule->use_hyperrefGB->isChecked();
3624         pdf.title = fromqstr(pdfSupportModule->titleLE->text());
3625         pdf.author = fromqstr(pdfSupportModule->authorLE->text());
3626         pdf.subject = fromqstr(pdfSupportModule->subjectLE->text());
3627         pdf.keywords = fromqstr(pdfSupportModule->keywordsLE->text());
3628
3629         pdf.bookmarks = pdfSupportModule->bookmarksGB->isChecked();
3630         pdf.bookmarksnumbered = pdfSupportModule->bookmarksnumberedCB->isChecked();
3631         pdf.bookmarksopen = pdfSupportModule->bookmarksopenGB->isChecked();
3632         pdf.bookmarksopenlevel = pdfSupportModule->bookmarksopenlevelSB->value();
3633
3634         pdf.breaklinks = pdfSupportModule->breaklinksCB->isChecked();
3635         pdf.pdfborder = pdfSupportModule->pdfborderCB->isChecked();
3636         pdf.pdfusetitle = pdfSupportModule->pdfusetitleCB->isChecked();
3637         pdf.colorlinks = pdfSupportModule->colorlinksCB->isChecked();
3638         pdf.backref =
3639                 backref_opts[pdfSupportModule->backrefCO->currentIndex()];
3640         if (pdfSupportModule->fullscreenCB->isChecked())
3641                 pdf.pagemode = pdf.pagemode_fullscreen;
3642         else
3643                 pdf.pagemode.clear();
3644         pdf.quoted_options = pdf.quoted_options_check(
3645                                 fromqstr(pdfSupportModule->optionsLE->text()));
3646
3647         // reset trackers
3648         nonModuleChanged_ = false;
3649         shellescapeChanged_ = false;
3650 }
3651
3652
3653 void GuiDocument::paramsToDialog()
3654 {
3655         // set the default unit
3656         Length::UNIT const default_unit = Length::defaultUnit();
3657
3658         // preamble
3659         preambleModule->update(bp_, id());
3660         localLayout->update(bp_, id());
3661
3662         // date
3663         latexModule->suppressDateCB->setChecked(bp_.suppress_date);
3664         latexModule->refstyleCB->setChecked(bp_.use_refstyle);
3665
3666         // biblio
3667         string const cite_engine = bp_.citeEngine();
3668
3669         biblioModule->citeEngineCO->setCurrentIndex(
3670                 biblioModule->citeEngineCO->findData(toqstr(cite_engine)));
3671
3672         updateEngineType(documentClass().opt_enginetype(),
3673                 bp_.citeEngineType());
3674
3675         checkPossibleCiteEngines();
3676
3677         biblioModule->citeStyleCO->setCurrentIndex(
3678                 biblioModule->citeStyleCO->findData(bp_.citeEngineType()));
3679
3680         biblioModule->bibtopicCB->setChecked(bp_.splitbib());
3681
3682         biblioModule->bibunitsCO->clear();
3683         biblioModule->bibunitsCO->addItem(qt_("No"), QString());
3684         if (documentClass().hasLaTeXLayout("part"))
3685                 biblioModule->bibunitsCO->addItem(qt_("per part"), toqstr("part"));
3686         if (documentClass().hasLaTeXLayout("chapter"))
3687                 biblioModule->bibunitsCO->addItem(qt_("per chapter"), toqstr("chapter"));
3688         if (documentClass().hasLaTeXLayout("section"))
3689                 biblioModule->bibunitsCO->addItem(qt_("per section"), toqstr("section"));
3690         if (documentClass().hasLaTeXLayout("subsection"))
3691                 biblioModule->bibunitsCO->addItem(qt_("per subsection"), toqstr("subsection"));
3692         biblioModule->bibunitsCO->addItem(qt_("per child document"), toqstr("child"));
3693
3694         int const mbpos = biblioModule->bibunitsCO->findData(toqstr(bp_.multibib));
3695         if (mbpos != -1)
3696                 biblioModule->bibunitsCO->setCurrentIndex(mbpos);
3697         else
3698                 biblioModule->bibunitsCO->setCurrentIndex(0);
3699
3700         updateEngineDependends();
3701
3702         if (isBiblatex()) {
3703                 updateDefaultBiblio(bp_.biblatex_bibstyle, "bbx");
3704                 updateDefaultBiblio(bp_.biblatex_citestyle, "cbx");
3705         } else
3706                 updateDefaultBiblio(bp_.defaultBiblioStyle());
3707
3708         biblioModule->citePackageOptionsLE->setText(toqstr(bp_.biblio_opts));
3709
3710         string command;
3711         string options =
3712                 split(bp_.bibtex_command, command, ' ');
3713
3714         int const bpos = biblioModule->bibtexCO->findData(toqstr(command));
3715         if (bpos != -1) {
3716                 biblioModule->bibtexCO->setCurrentIndex(bpos);
3717                 biblioModule->bibtexOptionsLE->setText(toqstr(options).trimmed());
3718         } else {
3719                 // We reset to default if we do not know the specified compiler
3720                 // This is for security reasons
3721                 biblioModule->bibtexCO->setCurrentIndex(
3722                         biblioModule->bibtexCO->findData(toqstr("default")));
3723                 biblioModule->bibtexOptionsLE->clear();
3724         }
3725         biblioModule->bibtexOptionsLE->setEnabled(
3726                 biblioModule->bibtexCO->currentIndex() != 0);
3727
3728         biblioChanged_ = false;
3729
3730         // indices
3731         // We may be called when there is no Buffer, e.g., when
3732         // the last view has just been closed.
3733         bool const isReadOnly = isBufferAvailable() ? buffer().isReadonly() : false;
3734         indicesModule->update(bp_, isReadOnly);
3735
3736         // language & quotes
3737         int const pos = langModule->languageCO->findData(toqstr(
3738                 bp_.language->lang()));
3739         langModule->languageCO->setCurrentIndex(pos);
3740
3741         updateQuoteStyles();
3742
3743         langModule->quoteStyleCO->setCurrentIndex(
3744                 langModule->quoteStyleCO->findData(bp_.quotes_style));
3745         langModule->dynamicQuotesCB->setChecked(bp_.dynamic_quotes);
3746
3747         QString inputenc = toqstr(bp_.inputenc);
3748         bool plain = false;
3749         if (inputenc.endsWith("-plain")) {
3750                 inputenc = inputenc.left(inputenc.lastIndexOf("-plain"));
3751                 plain = true;
3752         }
3753         langModule->noInputencCB->setChecked(plain);
3754         int p = langModule->encodingCO->findData(inputenc);
3755         if (p != -1)
3756                 langModule->encodingCO->setCurrentIndex(p);
3757         else {
3758                 langModule->encodingCO->setCurrentIndex(
3759                           langModule->encodingCO->findData("custom"));
3760                 p = langModule->customEncodingCO->findData(inputenc);
3761                 if (p != -1)
3762                         langModule->customEncodingCO->setCurrentIndex(p);
3763                 else
3764                         langModule->encodingCO->setCurrentIndex(0);
3765         }
3766
3767         p = langModule->languagePackageCO->findData(toqstr(bp_.lang_package));
3768         if (p == -1) {
3769                 langModule->languagePackageCO->setCurrentIndex(
3770                           langModule->languagePackageCO->findData("custom"));
3771                 langModule->languagePackageLE->setText(toqstr(bp_.lang_package));
3772         } else {
3773                 langModule->languagePackageCO->setCurrentIndex(p);
3774                 langModule->languagePackageLE->clear();
3775         }
3776
3777         //color
3778         if (bp_.isfontcolor) {
3779                 colorModule->fontColorPB->setStyleSheet(
3780                         colorButtonStyleSheet(rgb2qcolor(bp_.fontcolor)));
3781         }
3782         set_fontcolor = bp_.fontcolor;
3783         is_fontcolor = bp_.isfontcolor;
3784
3785         colorModule->noteFontColorPB->setStyleSheet(
3786                 colorButtonStyleSheet(rgb2qcolor(bp_.notefontcolor)));
3787         set_notefontcolor = bp_.notefontcolor;
3788
3789         if (bp_.isbackgroundcolor) {
3790                 colorModule->backgroundPB->setStyleSheet(
3791                         colorButtonStyleSheet(rgb2qcolor(bp_.backgroundcolor)));
3792         }
3793         set_backgroundcolor = bp_.backgroundcolor;
3794         is_backgroundcolor = bp_.isbackgroundcolor;
3795
3796         colorModule->boxBackgroundPB->setStyleSheet(
3797                 colorButtonStyleSheet(rgb2qcolor(bp_.boxbgcolor)));
3798         set_boxbgcolor = bp_.boxbgcolor;
3799
3800         // numbering
3801         int const min_toclevel = documentClass().min_toclevel();
3802         int const max_toclevel = documentClass().max_toclevel();
3803         if (documentClass().hasTocLevels()) {
3804                 numberingModule->setEnabled(true);
3805                 numberingModule->depthSL->setMinimum(min_toclevel - 1);
3806                 numberingModule->depthSL->setMaximum(max_toclevel);
3807                 numberingModule->depthSL->setValue(bp_.secnumdepth);
3808                 numberingModule->tocSL->setMaximum(min_toclevel - 1);
3809                 numberingModule->tocSL->setMaximum(max_toclevel);
3810                 numberingModule->tocSL->setValue(bp_.tocdepth);
3811                 updateNumbering();
3812         } else {
3813                 numberingModule->setEnabled(false);
3814                 numberingModule->tocTW->clear();
3815         }
3816
3817         numberingModule->linenoCB->setChecked(bp_.use_lineno);
3818         numberingModule->linenoLE->setEnabled(bp_.use_lineno);
3819         numberingModule->linenoLE->setText(toqstr(bp_.lineno_opts));
3820
3821         // bullets
3822         bulletsModule->setBullet(0, bp_.user_defined_bullet(0));
3823         bulletsModule->setBullet(1, bp_.user_defined_bullet(1));
3824         bulletsModule->setBullet(2, bp_.user_defined_bullet(2));
3825         bulletsModule->setBullet(3, bp_.user_defined_bullet(3));
3826         bulletsModule->init();
3827
3828         // packages
3829         int nitem = findToken(tex_graphics, bp_.graphics_driver);
3830         if (nitem >= 0)
3831                 latexModule->psdriverCO->setCurrentIndex(nitem);
3832         updateModuleInfo();
3833
3834         // math
3835         mathsModule->MathIndentCB->setChecked(bp_.is_math_indent);
3836         if (bp_.is_math_indent) {
3837                 Length const mathindent = bp_.getMathIndent();
3838                 int indent = 0;
3839                 if (!mathindent.empty()) {
3840                         lengthToWidgets(mathsModule->MathIndentLE,
3841                                         mathsModule->MathIndentLengthCO,
3842                                         mathindent, default_unit);
3843                         indent = 1;
3844                 }
3845                 mathsModule->MathIndentCO->setCurrentIndex(indent);
3846                 enableMathIndent(indent);
3847         }
3848         switch(bp_.math_numbering_side) {
3849         case BufferParams::LEFT:
3850                 mathsModule->MathNumberingPosCO->setCurrentIndex(0);
3851                 break;
3852         case BufferParams::DEFAULT:
3853                 mathsModule->MathNumberingPosCO->setCurrentIndex(1);
3854                 break;
3855         case BufferParams::RIGHT:
3856                 mathsModule->MathNumberingPosCO->setCurrentIndex(2);
3857         }
3858
3859         map<string, string> const & packages = BufferParams::auto_packages();
3860         for (map<string, string>::const_iterator it = packages.begin();
3861              it != packages.end(); ++it) {
3862                 QTableWidgetItem * item = mathsModule->packagesTW->findItems(toqstr(it->first), Qt::MatchExactly)[0];
3863                 if (!item)
3864                         continue;
3865                 int row = mathsModule->packagesTW->row(item);
3866                 switch (bp_.use_package(it->first)) {
3867                         case BufferParams::package_off: {
3868                                 QRadioButton * rb =
3869                                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 3)->layout()->itemAt(0)->widget();
3870                                 rb->setChecked(true);
3871                                 break;
3872                         }
3873                         case BufferParams::package_on: {
3874                                 QRadioButton * rb =
3875                                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 2)->layout()->itemAt(0)->widget();
3876                                 rb->setChecked(true);
3877                                 break;
3878                         }
3879                         case BufferParams::package_auto: {
3880                                 QRadioButton * rb =
3881                                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 1)->layout()->itemAt(0)->widget();
3882                                 rb->setChecked(true);
3883                                 break;
3884                         }
3885                 }
3886         }
3887
3888         switch (bp_.spacing().getSpace()) {
3889                 case Spacing::Other: nitem = 3; break;
3890                 case Spacing::Double: nitem = 2; break;
3891                 case Spacing::Onehalf: nitem = 1; break;
3892                 case Spacing::Default: case Spacing::Single: nitem = 0; break;
3893         }
3894
3895         // text layout
3896         string const & layoutID = bp_.baseClassID();
3897         setLayoutComboByIDString(layoutID);
3898
3899         updatePagestyle(documentClass().opt_pagestyle(),
3900                                  bp_.pagestyle);
3901
3902         textLayoutModule->lspacingCO->setCurrentIndex(nitem);
3903         if (bp_.spacing().getSpace() == Spacing::Other) {
3904                 doubleToWidget(textLayoutModule->lspacingLE,
3905                         bp_.spacing().getValueAsString());
3906         }
3907         setLSpacing(nitem);
3908         int ts = textLayoutModule->tableStyleCO->findData(toqstr(bp_.tablestyle));
3909         if (ts != -1)
3910                 textLayoutModule->tableStyleCO->setCurrentIndex(ts);
3911
3912         if (bp_.paragraph_separation == BufferParams::ParagraphIndentSeparation) {
3913                 textLayoutModule->indentRB->setChecked(true);
3914                 string parindent = bp_.getParIndent().asString();
3915                 int indent = 0;
3916                 if (!parindent.empty()) {
3917                         lengthToWidgets(textLayoutModule->indentLE,
3918                                         textLayoutModule->indentLengthCO,
3919                                         parindent, default_unit);
3920                         indent = 1;
3921                 }
3922                 textLayoutModule->indentCO->setCurrentIndex(indent);
3923                 setIndent(indent);
3924         } else {
3925                 textLayoutModule->skipRB->setChecked(true);
3926                 int skip = 0;
3927                 switch (bp_.getDefSkip().kind()) {
3928                 case VSpace::SMALLSKIP:
3929                         skip = 0;
3930                         break;
3931                 case VSpace::MEDSKIP:
3932                         skip = 1;
3933                         break;
3934                 case VSpace::BIGSKIP:
3935                         skip = 2;
3936                         break;
3937                 case VSpace::LENGTH:
3938                         {
3939                         skip = 3;
3940                         string const length = bp_.getDefSkip().asLyXCommand();
3941                         lengthToWidgets(textLayoutModule->skipLE,
3942                                 textLayoutModule->skipLengthCO,
3943                                 length, default_unit);
3944                         break;
3945                         }
3946                 default:
3947                         skip = 0;
3948                         break;
3949                 }
3950                 textLayoutModule->skipCO->setCurrentIndex(skip);
3951                 setSkip(skip);
3952         }
3953
3954         textLayoutModule->twoColumnCB->setChecked(
3955                 bp_.columns == 2);
3956         textLayoutModule->justCB->setChecked(bp_.justification);
3957
3958         if (!bp_.options.empty()) {
3959                 latexModule->optionsLE->setText(
3960                         toqstr(bp_.options));
3961         } else {
3962                 latexModule->optionsLE->setText(QString());
3963         }
3964
3965         // latex
3966         latexModule->defaultOptionsCB->setChecked(
3967                         bp_.use_default_options);
3968         updateSelectedModules();
3969         selectionManager->updateProvidedModules(
3970                         bp_.baseClass()->providedModules());
3971         selectionManager->updateExcludedModules(
3972                         bp_.baseClass()->excludedModules());
3973
3974         if (!documentClass().options().empty()) {
3975                 latexModule->defaultOptionsLE->setText(
3976                         toqstr(documentClass().options()));
3977         } else {
3978                 latexModule->defaultOptionsLE->setText(
3979                         toqstr(_("[No options predefined]")));
3980         }
3981
3982         latexModule->defaultOptionsLE->setEnabled(
3983                 bp_.use_default_options
3984                 && !documentClass().options().empty());
3985
3986         latexModule->defaultOptionsCB->setEnabled(
3987                 !documentClass().options().empty());
3988
3989         if (!bp_.master.empty()) {
3990                 latexModule->childDocGB->setChecked(true);
3991                 latexModule->childDocLE->setText(
3992                         toqstr(bp_.master));
3993         } else {
3994                 latexModule->childDocLE->setText(QString());
3995                 latexModule->childDocGB->setChecked(false);
3996         }
3997
3998         // Master/Child
3999         if (!bufferview() || !buffer().hasChildren()) {
4000                 masterChildModule->childrenTW->clear();
4001                 includeonlys_.clear();
4002                 docPS->showPanel("Child Documents", false);
4003                 if (docPS->isCurrentPanel("Child Documents"))
4004                         docPS->setCurrentPanel("Document Class");
4005         } else {
4006                 docPS->showPanel("Child Documents", true);
4007                 masterChildModule->setEnabled(true);
4008                 includeonlys_ = bp_.getIncludedChildren();
4009                 updateIncludeonlys();
4010         }
4011         masterChildModule->maintainAuxCB->setChecked(
4012                 bp_.maintain_unincluded_children);
4013
4014         // Float Settings
4015         floatModule->setPlacement(bp_.float_placement);
4016         floatModule->setAlignment(bp_.float_alignment);
4017
4018         // ListingsSettings
4019         // break listings_params to multiple lines
4020         string lstparams =
4021                 InsetListingsParams(bp_.listings_params).separatedParams();
4022         listingsModule->listingsED->setPlainText(toqstr(lstparams));
4023         int nn = findToken(lst_packages, bp_.use_minted ? "Minted" : "Listings");
4024         if (nn >= 0)
4025                 listingsModule->packageCO->setCurrentIndex(nn);
4026
4027         // Fonts
4028         // some languages only work with Polyglossia (which requires non-TeX fonts)
4029         Language const * lang = lyx::languages.getLanguage(
4030                 fromqstr(langModule->languageCO->itemData(
4031                         langModule->languageCO->currentIndex()).toString()));
4032         bool const need_fontspec =
4033                 lang->babel().empty() && !lang->polyglossia().empty();
4034         bool const os_fonts_available =
4035                 bp_.baseClass()->outputType() == lyx::LATEX
4036                 && LaTeXFeatures::isAvailable("fontspec");
4037         fontModule->osFontsCB->setEnabled(os_fonts_available && !need_fontspec);
4038         fontModule->osFontsCB->setChecked(
4039                 (os_fonts_available && bp_.useNonTeXFonts) || need_fontspec);
4040         updateFontsize(documentClass().opt_fontsize(),
4041                         bp_.fontsize);
4042
4043         QString font = toqstr(bp_.fontsRoman());
4044         int rpos = fontModule->fontsRomanCO->findData(font);
4045         if (rpos == -1) {
4046                 rpos = fontModule->fontsRomanCO->count();
4047                 fontModule->fontsRomanCO->addItem(font + qt_(" (not installed)"), font);
4048         }
4049         fontModule->fontsRomanCO->setCurrentIndex(rpos);
4050         fontModule->font_roman = toqstr(bp_.fonts_roman[!bp_.useNonTeXFonts]);
4051
4052         font = toqstr(bp_.fontsSans());
4053         int spos = fontModule->fontsSansCO->findData(font);
4054         if (spos == -1) {
4055                 spos = fontModule->fontsSansCO->count();
4056                 fontModule->fontsSansCO->addItem(font + qt_(" (not installed)"), font);
4057         }
4058         fontModule->fontsSansCO->setCurrentIndex(spos);
4059         fontModule->font_sans = toqstr(bp_.fonts_sans[!bp_.useNonTeXFonts]);
4060
4061         font = toqstr(bp_.fontsTypewriter());
4062         int tpos = fontModule->fontsTypewriterCO->findData(font);
4063         if (tpos == -1) {
4064                 tpos = fontModule->fontsTypewriterCO->count();
4065                 fontModule->fontsTypewriterCO->addItem(font + qt_(" (not installed)"), font);
4066         }
4067         fontModule->fontsTypewriterCO->setCurrentIndex(tpos);
4068         fontModule->font_typewriter = toqstr(bp_.fonts_typewriter[!bp_.useNonTeXFonts]);
4069
4070         font = toqstr(bp_.fontsMath());
4071         int mpos = fontModule->fontsMathCO->findData(font);
4072         if (mpos == -1) {
4073                 mpos = fontModule->fontsMathCO->count();
4074                 fontModule->fontsMathCO->addItem(font + qt_(" (not installed)"), font);
4075         }
4076         fontModule->fontsMathCO->setCurrentIndex(mpos);
4077         fontModule->font_math = toqstr(bp_.fonts_math[!bp_.useNonTeXFonts]);
4078
4079         if (bp_.useNonTeXFonts && os_fonts_available) {
4080                 fontModule->fontencLA->setEnabled(false);
4081                 fontModule->fontencCO->setEnabled(false);
4082                 fontModule->fontencLE->setEnabled(false);
4083         } else {
4084                 fontModule->fontencLA->setEnabled(true);
4085                 fontModule->fontencCO->setEnabled(true);
4086                 fontModule->fontencLE->setEnabled(true);
4087                 romanChanged(rpos);
4088                 sansChanged(spos);
4089                 ttChanged(tpos);
4090         }
4091
4092         if (!bp_.fonts_cjk.empty())
4093                 fontModule->cjkFontLE->setText(
4094                         toqstr(bp_.fonts_cjk));
4095         else
4096                 fontModule->cjkFontLE->setText(QString());
4097
4098         fontModule->microtypeCB->setChecked(bp_.use_microtype);
4099         fontModule->dashesCB->setChecked(!bp_.use_dash_ligatures);
4100
4101         fontModule->fontScCB->setChecked(bp_.fonts_expert_sc);
4102         fontModule->fontOsfCB->setChecked(bp_.fonts_old_figures);
4103         fontModule->scaleSansSB->setValue(bp_.fontsSansScale());
4104         fontModule->font_sf_scale = bp_.fonts_sans_scale[!bp_.useNonTeXFonts];
4105         fontModule->scaleTypewriterSB->setValue(bp_.fontsTypewriterScale());
4106         fontModule->font_tt_scale = bp_.fonts_typewriter_scale[!bp_.useNonTeXFonts];
4107
4108         nn = findToken(GuiDocument::fontfamilies, bp_.fonts_default_family);
4109         if (nn >= 0)
4110                 fontModule->fontsDefaultCO->setCurrentIndex(nn);
4111
4112         if (bp_.fontenc == "auto" || bp_.fontenc == "default") {
4113                 fontModule->fontencCO->setCurrentIndex(
4114                         fontModule->fontencCO->findData(toqstr(bp_.fontenc)));
4115                 fontModule->fontencLE->setEnabled(false);
4116         } else {
4117                 fontModule->fontencCO->setCurrentIndex(
4118                                         fontModule->fontencCO->findData("custom"));
4119                 fontModule->fontencLE->setText(toqstr(bp_.fontenc));
4120         }
4121
4122         // Formats
4123         // This must be set _after_ fonts since updateDefaultFormat()
4124         // checks osFontsCB settings.
4125         // update combobox with formats
4126         updateDefaultFormat();
4127         int index = outputModule->defaultFormatCO->findData(toqstr(
4128                 bp_.default_output_format));
4129         // set to default if format is not found
4130         if (index == -1)
4131                 index = 0;
4132         outputModule->defaultFormatCO->setCurrentIndex(index);
4133
4134         outputModule->shellescapeCB->setChecked(bp_.shell_escape);
4135         outputModule->outputsyncCB->setChecked(bp_.output_sync);
4136         outputModule->synccustomCB->setEditText(toqstr(bp_.output_sync_macro));
4137
4138         outputModule->mathimgSB->setValue(bp_.html_math_img_scale);
4139         outputModule->mathoutCB->setCurrentIndex(bp_.html_math_output);
4140         outputModule->strictCB->setChecked(bp_.html_be_strict);
4141         outputModule->cssCB->setChecked(bp_.html_css_as_file);
4142
4143         outputModule->saveTransientPropertiesCB
4144                 ->setChecked(bp_.save_transient_properties);
4145
4146         // paper
4147         bool const extern_geometry =
4148                 documentClass().provides("geometry");
4149         int const psize = bp_.papersize;
4150         pageLayoutModule->papersizeCO->setCurrentIndex(psize);
4151         setCustomPapersize(!extern_geometry && psize == 1);
4152         pageLayoutModule->papersizeCO->setEnabled(!extern_geometry);
4153
4154         bool const landscape =
4155                 bp_.orientation == ORIENTATION_LANDSCAPE;
4156         pageLayoutModule->landscapeRB->setChecked(landscape);
4157         pageLayoutModule->portraitRB->setChecked(!landscape);
4158         pageLayoutModule->landscapeRB->setEnabled(!extern_geometry);
4159         pageLayoutModule->portraitRB->setEnabled(!extern_geometry);
4160
4161         pageLayoutModule->facingPagesCB->setChecked(
4162                 bp_.sides == TwoSides);
4163
4164         lengthToWidgets(pageLayoutModule->paperwidthLE,
4165                 pageLayoutModule->paperwidthUnitCO, bp_.paperwidth, default_unit);
4166         lengthToWidgets(pageLayoutModule->paperheightLE,
4167                 pageLayoutModule->paperheightUnitCO, bp_.paperheight, default_unit);
4168
4169         // margins
4170         Ui::MarginsUi * m = marginsModule;
4171
4172         setMargins();
4173
4174         lengthToWidgets(m->topLE, m->topUnit,
4175                 bp_.topmargin, default_unit);
4176
4177         lengthToWidgets(m->bottomLE, m->bottomUnit,
4178                 bp_.bottommargin, default_unit);
4179
4180         lengthToWidgets(m->innerLE, m->innerUnit,
4181                 bp_.leftmargin, default_unit);
4182
4183         lengthToWidgets(m->outerLE, m->outerUnit,
4184                 bp_.rightmargin, default_unit);
4185
4186         lengthToWidgets(m->headheightLE, m->headheightUnit,
4187                 bp_.headheight, default_unit);
4188
4189         lengthToWidgets(m->headsepLE, m->headsepUnit,
4190                 bp_.headsep, default_unit);
4191
4192         lengthToWidgets(m->footskipLE, m->footskipUnit,
4193                 bp_.footskip, default_unit);
4194
4195         lengthToWidgets(m->columnsepLE, m->columnsepUnit,
4196                 bp_.columnsep, default_unit);
4197
4198         // branches
4199         updateUnknownBranches();
4200         branchesModule->update(bp_);
4201
4202         // PDF support
4203         PDFOptions const & pdf = bp_.pdfoptions();
4204         pdfSupportModule->use_hyperrefGB->setChecked(pdf.use_hyperref);
4205         if (bp_.documentClass().provides("hyperref"))
4206                 pdfSupportModule->use_hyperrefGB->setTitle(qt_("C&ustomize Hyperref Options"));
4207         else
4208                 pdfSupportModule->use_hyperrefGB->setTitle(qt_("&Use Hyperref Support"));
4209         pdfSupportModule->titleLE->setText(toqstr(pdf.title));
4210         pdfSupportModule->authorLE->setText(toqstr(pdf.author));
4211         pdfSupportModule->subjectLE->setText(toqstr(pdf.subject));
4212         pdfSupportModule->keywordsLE->setText(toqstr(pdf.keywords));
4213
4214         pdfSupportModule->bookmarksGB->setChecked(pdf.bookmarks);
4215         pdfSupportModule->bookmarksnumberedCB->setChecked(pdf.bookmarksnumbered);
4216         pdfSupportModule->bookmarksopenGB->setChecked(pdf.bookmarksopen);
4217
4218         pdfSupportModule->bookmarksopenlevelSB->setValue(pdf.bookmarksopenlevel);
4219
4220         pdfSupportModule->breaklinksCB->setChecked(pdf.breaklinks);
4221         pdfSupportModule->pdfborderCB->setChecked(pdf.pdfborder);
4222         pdfSupportModule->pdfusetitleCB->setChecked(pdf.pdfusetitle);
4223         pdfSupportModule->colorlinksCB->setChecked(pdf.colorlinks);
4224
4225         nn = findToken(backref_opts, pdf.backref);
4226         if (nn >= 0)
4227                 pdfSupportModule->backrefCO->setCurrentIndex(nn);
4228
4229         pdfSupportModule->fullscreenCB->setChecked
4230                 (pdf.pagemode == pdf.pagemode_fullscreen);
4231
4232         pdfSupportModule->optionsLE->setText(
4233                 toqstr(pdf.quoted_options));
4234
4235         // Make sure that the bc is in the INITIAL state
4236         if (bc().policy().buttonStatus(ButtonPolicy::RESTORE))
4237                 bc().restore();
4238
4239         // clear changed branches cache
4240         changedBranches_.clear();
4241
4242         // reset trackers
4243         nonModuleChanged_ = false;
4244         shellescapeChanged_ = false;
4245 }
4246
4247
4248 void GuiDocument::saveDocDefault()
4249 {
4250         // we have to apply the params first
4251         applyView();
4252         saveAsDefault();
4253 }
4254
4255
4256 void GuiDocument::updateAvailableModules()
4257 {
4258         modules_av_model_.clear();
4259         list<modInfoStruct> modInfoList = getModuleInfo();
4260         // Sort names according to the locale
4261         modInfoList.sort([](modInfoStruct const & a, modInfoStruct const & b) {
4262                         return 0 < b.name.localeAwareCompare(a.name);
4263                 });
4264         QIcon user_icon(getPixmap("images/", "lyxfiles-user", "svgz,png"));
4265         QIcon system_icon(getPixmap("images/", "lyxfiles-system", "svgz,png"));
4266         int i = 0;
4267         QFont catfont;
4268         catfont.setBold(true);
4269         QBrush unavbrush;
4270         unavbrush.setColor(Qt::gray);
4271         for (modInfoStruct const & m : modInfoList) {
4272                 QStandardItem * item = new QStandardItem();
4273                 QStandardItem * catItem = new QStandardItem();
4274                 QString const catname = m.category;
4275                 QList<QStandardItem *> fcats = modules_av_model_.findItems(catname, Qt::MatchExactly);
4276                 if (!fcats.empty())
4277                         catItem = fcats.first();
4278                 else {
4279                         catItem->setText(catname);
4280                         catItem->setFont(catfont);
4281                         modules_av_model_.insertRow(i, catItem);
4282                         ++i;
4283                 }
4284                 item->setEditable(false);
4285                 catItem->setEditable(false);
4286                 item->setData(m.name, Qt::DisplayRole);
4287                 if (m.missingreqs)
4288                         item->setForeground(unavbrush);
4289                 item->setData(toqstr(m.id), Qt::UserRole);
4290                 item->setData(m.description, Qt::ToolTipRole);
4291                 if (m.local)
4292                         item->setIcon(user_icon);
4293                 else
4294                         item->setIcon(system_icon);
4295                 catItem->appendRow(item);
4296         }
4297         modules_av_model_.sort(0);
4298 }
4299
4300
4301 void GuiDocument::updateSelectedModules()
4302 {
4303         modules_sel_model_.clear();
4304         list<modInfoStruct> const selModList = getSelectedModules();
4305         int i = 0;
4306         for (modInfoStruct const & m : selModList) {
4307                 modules_sel_model_.insertRow(i, m.name, m.id, m.description);
4308                 ++i;
4309         }
4310 }
4311
4312
4313 void GuiDocument::updateIncludeonlys()
4314 {
4315         masterChildModule->childrenTW->clear();
4316         QString const no = qt_("No");
4317         QString const yes = qt_("Yes");
4318
4319         if (includeonlys_.empty()) {
4320                 masterChildModule->includeallRB->setChecked(true);
4321                 masterChildModule->childrenTW->setEnabled(false);
4322                 masterChildModule->maintainAuxCB->setEnabled(false);
4323         } else {
4324                 masterChildModule->includeonlyRB->setChecked(true);
4325                 masterChildModule->childrenTW->setEnabled(true);
4326                 masterChildModule->maintainAuxCB->setEnabled(true);
4327         }
4328         ListOfBuffers children = buffer().getChildren();
4329         ListOfBuffers::const_iterator it  = children.begin();
4330         ListOfBuffers::const_iterator end = children.end();
4331         bool has_unincluded = false;
4332         bool all_unincluded = true;
4333         for (; it != end; ++it) {
4334                 QTreeWidgetItem * item = new QTreeWidgetItem(masterChildModule->childrenTW);
4335                 // FIXME Unicode
4336                 string const name =
4337                         to_utf8(makeRelPath(from_utf8((*it)->fileName().absFileName()),
4338                                                         from_utf8(buffer().filePath())));
4339                 item->setText(0, toqstr(name));
4340                 item->setText(1, isChildIncluded(name) ? yes : no);
4341                 if (!isChildIncluded(name))
4342                         has_unincluded = true;
4343                 else
4344                         all_unincluded = false;
4345         }
4346         // Both if all childs are included and if none is included
4347         // is equal to "include all" (i.e., omit \includeonly).
4348         // Thus, reset the GUI.
4349         if (!has_unincluded || all_unincluded) {
4350                 masterChildModule->includeallRB->setChecked(true);
4351                 masterChildModule->childrenTW->setEnabled(false);
4352                 includeonlys_.clear();
4353         }
4354         // If all are included, we need to update again.
4355         if (!has_unincluded)
4356                 updateIncludeonlys();
4357 }
4358
4359
4360 bool GuiDocument::isBiblatex() const
4361 {
4362         QString const engine =
4363                 biblioModule->citeEngineCO->itemData(
4364                                 biblioModule->citeEngineCO->currentIndex()).toString();
4365
4366         // this can happen if the cite engine is unknown, which can happen
4367         // if one is using a file that came from someone else, etc. in that
4368         // case, we crash if we proceed.
4369         if (engine.isEmpty())
4370             return false;
4371
4372         return theCiteEnginesList[fromqstr(engine)]->getCiteFramework() == "biblatex";
4373 }
4374
4375
4376 void GuiDocument::updateDefaultBiblio(string const & style,
4377                                       string const & which)
4378 {
4379         QString const bibstyle = toqstr(style);
4380         biblioModule->defaultBiblioCO->clear();
4381
4382         int item_nr = -1;
4383
4384         if (isBiblatex()) {
4385                 if (which != "cbx") {
4386                         // First the bbx styles
4387                         biblioModule->biblatexBbxCO->clear();
4388                         QStringList str = texFileList("bbxFiles.lst");
4389                         // test whether we have a valid list, otherwise run rescan
4390                         if (str.isEmpty()) {
4391                                 rescanTexStyles("bbx");
4392                                 str = texFileList("bbxFiles.lst");
4393                         }
4394                         for (int i = 0; i != str.size(); ++i)
4395                                 str[i] = onlyFileName(str[i]);
4396                         // sort on filename only (no path)
4397                         str.sort();
4398
4399                         for (int i = 0; i != str.count(); ++i) {
4400                                 QString item = changeExtension(str[i], "");
4401                                 if (item == bibstyle)
4402                                         item_nr = i;
4403                                 biblioModule->biblatexBbxCO->addItem(item);
4404                         }
4405
4406                         if (item_nr == -1 && !bibstyle.isEmpty()) {
4407                                 biblioModule->biblatexBbxCO->addItem(bibstyle);
4408                                 item_nr = biblioModule->biblatexBbxCO->count() - 1;
4409                         }
4410
4411                         if (item_nr != -1)
4412                                 biblioModule->biblatexBbxCO->setCurrentIndex(item_nr);
4413                         else
4414                                 biblioModule->biblatexBbxCO->clearEditText();
4415                 }
4416
4417                 if (which != "bbx") {
4418                         // now the cbx styles
4419                         biblioModule->biblatexCbxCO->clear();
4420                         QStringList str = texFileList("cbxFiles.lst");
4421                         // test whether we have a valid list, otherwise run rescan
4422                         if (str.isEmpty()) {
4423                                 rescanTexStyles("cbx");
4424                                 str = texFileList("cbxFiles.lst");
4425                         }
4426                         for (int i = 0; i != str.size(); ++i)
4427                                 str[i] = onlyFileName(str[i]);
4428                         // sort on filename only (no path)
4429                         str.sort();
4430
4431                         for (int i = 0; i != str.count(); ++i) {
4432                                 QString item = changeExtension(str[i], "");
4433                                 if (item == bibstyle)
4434                                         item_nr = i;
4435                                 biblioModule->biblatexCbxCO->addItem(item);
4436                         }
4437
4438                         if (item_nr == -1 && !bibstyle.isEmpty()) {
4439                                 biblioModule->biblatexCbxCO->addItem(bibstyle);
4440                                 item_nr = biblioModule->biblatexCbxCO->count() - 1;
4441                         }
4442
4443                         if (item_nr != -1)
4444                                 biblioModule->biblatexCbxCO->setCurrentIndex(item_nr);
4445                         else
4446                                 biblioModule->biblatexCbxCO->clearEditText();
4447                 }
4448         } else {// BibTeX
4449                 biblioModule->biblatexBbxCO->clear();
4450                 biblioModule->biblatexCbxCO->clear();
4451                 QStringList str = texFileList("bstFiles.lst");
4452                 // test whether we have a valid list, otherwise run rescan
4453                 if (str.isEmpty()) {
4454                         rescanTexStyles("bst");
4455                         str = texFileList("bstFiles.lst");
4456                 }
4457                 for (int i = 0; i != str.size(); ++i)
4458                         str[i] = onlyFileName(str[i]);
4459                 // sort on filename only (no path)
4460                 str.sort();
4461
4462                 for (int i = 0; i != str.count(); ++i) {
4463                         QString item = changeExtension(str[i], "");
4464                         if (item == bibstyle)
4465                                 item_nr = i;
4466                         biblioModule->defaultBiblioCO->addItem(item);
4467                 }
4468
4469                 if (item_nr == -1 && !bibstyle.isEmpty()) {
4470                         biblioModule->defaultBiblioCO->addItem(bibstyle);
4471                         item_nr = biblioModule->defaultBiblioCO->count() - 1;
4472                 }
4473
4474                 if (item_nr != -1)
4475                         biblioModule->defaultBiblioCO->setCurrentIndex(item_nr);
4476                 else
4477                         biblioModule->defaultBiblioCO->clearEditText();
4478         }
4479
4480         updateResetDefaultBiblio();
4481 }
4482
4483
4484 void GuiDocument::updateResetDefaultBiblio()
4485 {
4486         QString const engine =
4487                 biblioModule->citeEngineCO->itemData(
4488                                 biblioModule->citeEngineCO->currentIndex()).toString();
4489         CiteEngineType const cet =
4490                 CiteEngineType(biblioModule->citeStyleCO->itemData(
4491                                                           biblioModule->citeStyleCO->currentIndex()).toInt());
4492
4493         string const defbib = theCiteEnginesList[fromqstr(engine)]->getDefaultBiblio(cet);
4494         if (isBiblatex()) {
4495                 QString const bbx = biblioModule->biblatexBbxCO->currentText();
4496                 QString const cbx = biblioModule->biblatexCbxCO->currentText();
4497                 biblioModule->resetCbxPB->setEnabled(defbib != fromqstr(cbx));
4498                 biblioModule->resetBbxPB->setEnabled(defbib != fromqstr(bbx));
4499                 biblioModule->matchBbxPB->setEnabled(bbx != cbx && !cbx.isEmpty()
4500                         && biblioModule->biblatexBbxCO->findText(cbx) != -1);
4501         } else
4502                 biblioModule->resetDefaultBiblioPB->setEnabled(
4503                         defbib != fromqstr(biblioModule->defaultBiblioCO->currentText()));
4504 }
4505
4506
4507 void GuiDocument::matchBiblatexStyles()
4508 {
4509         updateDefaultBiblio(fromqstr(biblioModule->biblatexCbxCO->currentText()), "bbx");
4510         biblioChanged();
4511 }
4512
4513
4514 void GuiDocument::updateContents()
4515 {
4516         // Nothing to do here as the document settings is not cursor dependant.
4517         return;
4518 }
4519
4520
4521 void GuiDocument::useClassDefaults()
4522 {
4523         if (buttonBox->button(QDialogButtonBox::Apply)->isEnabled()) {
4524                 int const ret = Alert::prompt(_("Unapplied changes"),
4525                                 _("Some changes in the dialog were not yet applied.\n"
4526                                   "If you do not apply now, they will be lost after this action."),
4527                                 1, 1, _("&Apply"), _("&Dismiss"));
4528                 if (ret == 0)
4529                         applyView();
4530         }
4531
4532         int idx = latexModule->classCO->currentIndex();
4533         string const classname = fromqstr(latexModule->classCO->getData(idx));
4534         if (!bp_.setBaseClass(classname, buffer().layoutPos())) {
4535                 Alert::error(_("Error"), _("Unable to set document class."));
4536                 return;
4537         }
4538         bp_.useClassDefaults();
4539         paramsToDialog();
4540         changed();
4541 }
4542
4543
4544 void GuiDocument::setLayoutComboByIDString(string const & idString)
4545 {
4546         if (!latexModule->classCO->set(toqstr(idString)))
4547                 Alert::warning(_("Can't set layout!"),
4548                         bformat(_("Unable to set layout for ID: %1$s"), from_utf8(idString)));
4549 }
4550
4551
4552 bool GuiDocument::isValid()
4553 {
4554         return
4555                 validateListingsParameters().isEmpty() &&
4556                 localLayout->isValid() &&
4557                 !localLayout->editing() &&
4558                 !preambleModule->editing() &&
4559                 (
4560                         // if we're asking for skips between paragraphs
4561                         !textLayoutModule->skipRB->isChecked() ||
4562                         // then either we haven't chosen custom
4563                         textLayoutModule->skipCO->currentIndex() != 3 ||
4564                         // or else a length has been given
4565                         !textLayoutModule->skipLE->text().isEmpty()
4566                 ) &&
4567                 (
4568                         // if we're asking for indentation
4569                         !textLayoutModule->indentRB->isChecked() ||
4570                         // then either we haven't chosen custom
4571                         textLayoutModule->indentCO->currentIndex() != 1 ||
4572                         // or else a length has been given
4573                         !textLayoutModule->indentLE->text().isEmpty()
4574                 ) &&
4575                 (
4576                         // if we're asking for math indentation
4577                         !mathsModule->MathIndentCB->isChecked() ||
4578                         // then either we haven't chosen custom
4579                         mathsModule->MathIndentCO->currentIndex() != 1 ||
4580                         // or else a length has been given
4581                         !mathsModule->MathIndentLE->text().isEmpty()
4582                 );
4583 }
4584
4585
4586 char const * const GuiDocument::fontfamilies[5] = {
4587         "default", "rmdefault", "sfdefault", "ttdefault", ""
4588 };
4589
4590
4591 char const * GuiDocument::fontfamilies_gui[5] = {
4592         N_("Default"), N_("Roman"), N_("Sans Serif"), N_("Typewriter"), ""
4593 };
4594
4595
4596 bool GuiDocument::initialiseParams(string const &)
4597 {
4598         BufferView const * view = bufferview();
4599         if (!view) {
4600                 bp_ = BufferParams();
4601                 paramsToDialog();
4602                 return true;
4603         }
4604         bp_ = view->buffer().params();
4605         loadModuleInfo();
4606         updateAvailableModules();
4607         //FIXME It'd be nice to make sure here that the selected
4608         //modules are consistent: That required modules are actually
4609         //selected, and that we don't have conflicts. If so, we could
4610         //at least pop up a warning.
4611         paramsToDialog();
4612         return true;
4613 }
4614
4615
4616 void GuiDocument::clearParams()
4617 {
4618         bp_ = BufferParams();
4619 }
4620
4621
4622 BufferId GuiDocument::id() const
4623 {
4624         BufferView const * const view = bufferview();
4625         return view? &view->buffer() : 0;
4626 }
4627
4628
4629 list<GuiDocument::modInfoStruct> const & GuiDocument::getModuleInfo()
4630 {
4631         return moduleNames_;
4632 }
4633
4634
4635 list<GuiDocument::modInfoStruct> const
4636 GuiDocument::makeModuleInfo(LayoutModuleList const & mods)
4637 {
4638         list<modInfoStruct> mInfo;
4639         for (string const & name : mods) {
4640                 modInfoStruct m;
4641                 LyXModule const * const mod = theModuleList[name];
4642                 if (mod)
4643                         m = modInfo(*mod);
4644                 else {
4645                         m.id = name;
4646                         m.name = toqstr(name + " (") + qt_("Not Found") + toqstr(")");
4647                         m.local = false;
4648                         m.missingreqs = true;
4649                 }
4650                 mInfo.push_back(m);
4651         }
4652         return mInfo;
4653 }
4654
4655
4656 list<GuiDocument::modInfoStruct> const GuiDocument::getSelectedModules()
4657 {
4658         return makeModuleInfo(params().getModules());
4659 }
4660
4661
4662 list<GuiDocument::modInfoStruct> const GuiDocument::getProvidedModules()
4663 {
4664         return makeModuleInfo(params().baseClass()->providedModules());
4665 }
4666
4667
4668 DocumentClass const & GuiDocument::documentClass() const
4669 {
4670         return bp_.documentClass();
4671 }
4672
4673
4674 static void dispatch_bufferparams(Dialog const & dialog,
4675         BufferParams const & bp, FuncCode lfun, Buffer const * buf)
4676 {
4677         ostringstream ss;
4678         ss << "\\begin_header\n";
4679         bp.writeFile(ss, buf);
4680         ss << "\\end_header\n";
4681         dialog.dispatch(FuncRequest(lfun, ss.str()));
4682 }
4683
4684
4685 void GuiDocument::dispatchParams()
4686 {
4687         // We need a non-const buffer object.
4688         Buffer & buf = const_cast<BufferView *>(bufferview())->buffer();
4689         // There may be several undo records; group them (bug #8998)
4690         // This handles undo groups automagically
4691         UndoGroupHelper ugh(&buf);
4692
4693         // This must come first so that a language change is correctly noticed
4694         setLanguage();
4695
4696         // We need to load the master before we formally update the params,
4697         // since otherwise we run updateBuffer, etc, before the child's master
4698         // has been set.
4699         if (!params().master.empty()) {
4700                 FileName const master_file = support::makeAbsPath(params().master,
4701                            support::onlyPath(buffer().absFileName()));
4702                 if (isLyXFileName(master_file.absFileName())) {
4703                         Buffer * master = checkAndLoadLyXFile(master_file);
4704                         if (master) {
4705                                 if (master->isChild(const_cast<Buffer *>(&buffer())))
4706                                         const_cast<Buffer &>(buffer()).setParent(master);
4707                                 else
4708                                         Alert::warning(_("Assigned master does not include this file"),
4709                                                 bformat(_("You must include this file in the document\n"
4710                                                           "'%1$s' in order to use the master document\n"
4711                                                           "feature."), from_utf8(params().master)));
4712                         } else
4713                                 Alert::warning(_("Could not load master"),
4714                                                 bformat(_("The master document '%1$s'\n"
4715                                                            "could not be loaded."),
4716                                                            from_utf8(params().master)));
4717                 }
4718         }
4719
4720         // Apply the BufferParams. Note that this will set the base class
4721         // and then update the buffer's layout.
4722         dispatch_bufferparams(*this, params(), LFUN_BUFFER_PARAMS_APPLY, &buffer());
4723
4724         // Generate the colours requested by each new branch.
4725         BranchList & branchlist = params().branchlist();
4726         if (!branchlist.empty()) {
4727                 BranchList::const_iterator it = branchlist.begin();
4728                 BranchList::const_iterator const end = branchlist.end();
4729                 for (; it != end; ++it) {
4730                         docstring const & current_branch = it->branch();
4731                         Branch const * branch = branchlist.find(current_branch);
4732                         string const x11hexname = X11hexname(branch->color());
4733                         // display the new color
4734                         docstring const str = current_branch + ' ' + from_ascii(x11hexname);
4735                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
4736                 }
4737         }
4738         // rename branches in the document
4739         executeBranchRenaming();
4740         // and clear changed branches cache
4741         changedBranches_.clear();
4742
4743         // Generate the colours requested by indices.
4744         IndicesList & indiceslist = params().indiceslist();
4745         if (!indiceslist.empty()) {
4746                 IndicesList::const_iterator it = indiceslist.begin();
4747                 IndicesList::const_iterator const end = indiceslist.end();
4748                 for (; it != end; ++it) {
4749                         docstring const & current_index = it->shortcut();
4750                         Index const * index = indiceslist.findShortcut(current_index);
4751                         string const x11hexname = X11hexname(index->color());
4752                         // display the new color
4753                         docstring const str = current_index + ' ' + from_ascii(x11hexname);
4754                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
4755                 }
4756         }
4757         // FIXME LFUN
4758         // If we used an LFUN, we would not need these two lines:
4759         BufferView * bv = const_cast<BufferView *>(bufferview());
4760         bv->processUpdateFlags(Update::Force | Update::FitCursor);
4761 }
4762
4763
4764 void GuiDocument::setLanguage() const
4765 {
4766         Language const * const newL = bp_.language;
4767         if (buffer().params().language == newL)
4768                 return;
4769
4770         string const & lang_name = newL->lang();
4771         dispatch(FuncRequest(LFUN_BUFFER_LANGUAGE, lang_name));
4772 }
4773
4774
4775 void GuiDocument::saveAsDefault() const
4776 {
4777         dispatch_bufferparams(*this, params(), LFUN_BUFFER_SAVE_AS_DEFAULT, &buffer());
4778 }
4779
4780
4781 bool GuiDocument::providesOSF(QString const & font) const
4782 {
4783         if (fontModule->osFontsCB->isChecked())
4784                 // FIXME: we should check if the fonts really
4785                 // have OSF support. But how?
4786                 return true;
4787         return theLaTeXFonts().getLaTeXFont(
4788                                 qstring_to_ucs4(font)).providesOSF(ot1(),
4789                                                                    completeFontset(),
4790                                                                    noMathFont());
4791 }
4792
4793
4794 bool GuiDocument::providesSC(QString const & font) const
4795 {
4796         if (fontModule->osFontsCB->isChecked())
4797                 return false;
4798         return theLaTeXFonts().getLaTeXFont(
4799                                 qstring_to_ucs4(font)).providesSC(ot1(),
4800                                                                   completeFontset(),
4801                                                                   noMathFont());
4802 }
4803
4804
4805 bool GuiDocument::providesScale(QString const & font) const
4806 {
4807         if (fontModule->osFontsCB->isChecked())
4808                 return true;
4809         return theLaTeXFonts().getLaTeXFont(
4810                                 qstring_to_ucs4(font)).providesScale(ot1(),
4811                                                                      completeFontset(),
4812                                                                      noMathFont());
4813 }
4814
4815
4816 bool GuiDocument::providesNoMath(QString const & font) const
4817 {
4818         if (fontModule->osFontsCB->isChecked())
4819                 return false;
4820         return theLaTeXFonts().getLaTeXFont(
4821                                 qstring_to_ucs4(font)).providesNoMath(ot1(),
4822                                                                       completeFontset());
4823 }
4824
4825
4826 bool GuiDocument::hasMonolithicExpertSet(QString const & font) const
4827 {
4828         if (fontModule->osFontsCB->isChecked())
4829                 return false;
4830         return theLaTeXFonts().getLaTeXFont(
4831                                 qstring_to_ucs4(font)).hasMonolithicExpertSet(ot1(),
4832                                                                               completeFontset(),
4833                                                                               noMathFont());
4834 }
4835
4836
4837 //static
4838 GuiDocument::modInfoStruct GuiDocument::modInfo(LyXModule const & mod)
4839 {
4840         // FIXME Unicode: docstrings would be better for these parameters but this
4841         // change requires a lot of others
4842         modInfoStruct m;
4843         m.id = mod.getID();
4844         QString const guiname = toqstr(translateIfPossible(from_utf8(mod.getName())));
4845         m.missingreqs = !isModuleAvailable(mod.getID());
4846         if (m.missingreqs) {
4847                 m.name = QString(qt_("%1 (missing req.)")).arg(guiname);
4848         } else
4849                 m.name = guiname;
4850         m.category = mod.category().empty() ? qt_("Miscellaneous")
4851                                             : toqstr(translateIfPossible(from_utf8(mod.category())));
4852         QString desc = toqstr(translateIfPossible(from_utf8(mod.getDescription())));
4853         // Find the first sentence of the description
4854         QTextBoundaryFinder bf(QTextBoundaryFinder::Sentence, desc);
4855         int pos = bf.toNextBoundary();
4856         if (pos > 0)
4857                 desc.truncate(pos);
4858         m.local = mod.isLocal();
4859         QString const mtype = m.local ? qt_("personal module") : qt_("distributed module");
4860         QString modulename = QString(qt_("<b>Module name:</b> <i>%1</i> (%2)")).arg(toqstr(m.id)).arg(mtype);
4861         // Tooltip is the desc followed by the module name and the type
4862         m.description = QString("%1%2")
4863                 .arg(desc.isEmpty() ? QString() : QString("<p>%1</p>").arg(desc),
4864                      modulename);
4865         if (m.missingreqs)
4866                 m.description += QString("<p>%1</p>").arg(qt_("<b>Note:</b> Some requirements for this module are missing!"));
4867         return m;
4868 }
4869
4870
4871 void GuiDocument::loadModuleInfo()
4872 {
4873         moduleNames_.clear();
4874         for (LyXModule const & mod : theModuleList)
4875                 moduleNames_.push_back(modInfo(mod));
4876 }
4877
4878
4879 void GuiDocument::updateUnknownBranches()
4880 {
4881         if (!bufferview())
4882                 return;
4883         list<docstring> used_branches;
4884         buffer().getUsedBranches(used_branches);
4885         list<docstring>::const_iterator it = used_branches.begin();
4886         QStringList unknown_branches;
4887         for (; it != used_branches.end() ; ++it) {
4888                 if (!buffer().params().branchlist().find(*it))
4889                         unknown_branches.append(toqstr(*it));
4890         }
4891         branchesModule->setUnknownBranches(unknown_branches);
4892 }
4893
4894
4895 void GuiDocument::branchesRename(docstring const & oldname, docstring const & newname)
4896 {
4897         map<docstring, docstring>::iterator it = changedBranches_.begin();
4898         for (; it != changedBranches_.end() ; ++it) {
4899                 if (it->second == oldname) {
4900                         // branch has already been renamed
4901                         it->second = newname;
4902                         return;
4903                 }
4904         }
4905         // store new name
4906         changedBranches_[oldname] = newname;
4907 }
4908
4909
4910 void GuiDocument::executeBranchRenaming() const
4911 {
4912         map<docstring, docstring>::const_iterator it = changedBranches_.begin();
4913         for (; it != changedBranches_.end() ; ++it) {
4914                 docstring const arg = '"' + it->first + '"' + " " + '"' + it->second + '"';
4915                 dispatch(FuncRequest(LFUN_BRANCHES_RENAME, arg));
4916         }
4917 }
4918
4919
4920 void GuiDocument::allPackagesAuto()
4921 {
4922         allPackages(1);
4923 }
4924
4925
4926 void GuiDocument::allPackagesAlways()
4927 {
4928         allPackages(2);
4929 }
4930
4931
4932 void GuiDocument::allPackagesNot()
4933 {
4934         allPackages(3);
4935 }
4936
4937
4938 void GuiDocument::allPackages(int col)
4939 {
4940         for (int row = 0; row < mathsModule->packagesTW->rowCount(); ++row) {
4941                 QRadioButton * rb =
4942                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, col)->layout()->itemAt(0)->widget();
4943                 rb->setChecked(true);
4944         }
4945 }
4946
4947
4948 void GuiDocument::linenoToggled()
4949 {
4950         numberingModule->linenoLE->setEnabled(numberingModule->linenoCB->isChecked());
4951 }
4952
4953
4954
4955 Dialog * createGuiDocument(GuiView & lv) { return new GuiDocument(lv); }
4956
4957
4958 } // namespace frontend
4959 } // namespace lyx
4960
4961 #include "moc_GuiDocument.cpp"