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