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