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