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