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