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