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