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