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