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