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