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