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