]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiDocument.cpp
Use proper QPalette::NoRole enum value instead of our own
[lyx.git] / src / frontends / qt4 / GuiDocument.cpp
1 /**
2  * \file GuiDocument.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Edwin Leuven
7  * \author Richard Heck (modules)
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "GuiDocument.h"
15
16 #include "CategorizedCombo.h"
17 #include "GuiApplication.h"
18 #include "GuiBranches.h"
19 #include "GuiIndices.h"
20 #include "GuiSelectionManager.h"
21 #include "LaTeXHighlighter.h"
22 #include "LengthCombo.h"
23 #include "PanelStack.h"
24 #include "Validator.h"
25
26 #include "LayoutFile.h"
27 #include "BranchList.h"
28 #include "buffer_funcs.h"
29 #include "Buffer.h"
30 #include "BufferParams.h"
31 #include "BufferView.h"
32 #include "Color.h"
33 #include "ColorCache.h"
34 #include "Cursor.h"
35 #include "Encoding.h"
36 #include "FloatPlacement.h"
37 #include "Format.h"
38 #include "FuncRequest.h"
39 #include "HSpace.h"
40 #include "IndicesList.h"
41 #include "Language.h"
42 #include "LaTeXFeatures.h"
43 #include "LaTeXFonts.h"
44 #include "Layout.h"
45 #include "LayoutEnums.h"
46 #include "LayoutModuleList.h"
47 #include "LyXRC.h"
48 #include "ModuleList.h"
49 #include "OutputParams.h"
50 #include "PDFOptions.h"
51 #include "qt_helpers.h"
52 #include "Spacing.h"
53 #include "TextClass.h"
54 #include "Undo.h"
55 #include "VSpace.h"
56
57 #include "insets/InsetListingsParams.h"
58
59 #include "support/debug.h"
60 #include "support/FileName.h"
61 #include "support/filetools.h"
62 #include "support/gettext.h"
63 #include "support/lassert.h"
64 #include "support/lstrings.h"
65
66 #include "frontends/alert.h"
67
68 #include <QAbstractItemModel>
69 #include <QHeaderView>
70 #include <QColor>
71 #include <QColorDialog>
72 #include <QCloseEvent>
73 #include <QFontDatabase>
74 #include <QScrollBar>
75 #include <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         if (listingsModule->bypassCB->isChecked())
1500                 return QString();
1501         string params = fromqstr(listingsModule->listingsED->toPlainText());
1502         return toqstr(InsetListingsParams(params).validate());
1503 }
1504
1505
1506 void GuiDocument::setListingsMessage()
1507 {
1508         // FIXME THREAD
1509         static bool isOK = true;
1510         QString msg = validateListingsParameters();
1511         if (msg.isEmpty()) {
1512                 if (isOK)
1513                         return;
1514                 isOK = true;
1515                 // listingsTB->setTextColor("black");
1516                 listingsModule->listingsTB->setPlainText(
1517                         qt_("Input listings parameters below. "
1518                             "Enter ? for a list of parameters."));
1519         } else {
1520                 isOK = false;
1521                 // listingsTB->setTextColor("red");
1522                 listingsModule->listingsTB->setPlainText(msg);
1523         }
1524 }
1525
1526
1527 void GuiDocument::setLSpacing(int item)
1528 {
1529         textLayoutModule->lspacingLE->setEnabled(item == 3);
1530 }
1531
1532
1533 void GuiDocument::setIndent(int item)
1534 {
1535         bool const enable = (item == 1);
1536         textLayoutModule->indentLE->setEnabled(enable);
1537         textLayoutModule->indentLengthCO->setEnabled(enable);
1538         textLayoutModule->skipLE->setEnabled(false);
1539         textLayoutModule->skipLengthCO->setEnabled(false);
1540         isValid();
1541 }
1542
1543
1544 void GuiDocument::enableIndent(bool indent)
1545 {
1546         textLayoutModule->skipLE->setEnabled(!indent);
1547         textLayoutModule->skipLengthCO->setEnabled(!indent);
1548         if (indent)
1549                 setIndent(textLayoutModule->indentCO->currentIndex());
1550 }
1551
1552
1553 void GuiDocument::setSkip(int item)
1554 {
1555         bool const enable = (item == 3);
1556         textLayoutModule->skipLE->setEnabled(enable);
1557         textLayoutModule->skipLengthCO->setEnabled(enable);
1558         isValid();
1559 }
1560
1561
1562 void GuiDocument::enableSkip(bool skip)
1563 {
1564         textLayoutModule->indentLE->setEnabled(!skip);
1565         textLayoutModule->indentLengthCO->setEnabled(!skip);
1566         if (skip)
1567                 setSkip(textLayoutModule->skipCO->currentIndex());
1568 }
1569
1570
1571 void GuiDocument::setMargins()
1572 {
1573         bool const extern_geometry =
1574                 documentClass().provides("geometry");
1575         marginsModule->marginCB->setEnabled(!extern_geometry);
1576         if (extern_geometry) {
1577                 marginsModule->marginCB->setChecked(false);
1578                 setCustomMargins(true);
1579         } else {
1580                 marginsModule->marginCB->setChecked(!bp_.use_geometry);
1581                 setCustomMargins(!bp_.use_geometry);
1582         }
1583 }
1584
1585
1586 void GuiDocument::papersizeChanged(int paper_size)
1587 {
1588         setCustomPapersize(paper_size == 1);
1589 }
1590
1591
1592 void GuiDocument::setCustomPapersize(bool custom)
1593 {
1594         pageLayoutModule->paperwidthL->setEnabled(custom);
1595         pageLayoutModule->paperwidthLE->setEnabled(custom);
1596         pageLayoutModule->paperwidthUnitCO->setEnabled(custom);
1597         pageLayoutModule->paperheightL->setEnabled(custom);
1598         pageLayoutModule->paperheightLE->setEnabled(custom);
1599         pageLayoutModule->paperheightLE->setFocus();
1600         pageLayoutModule->paperheightUnitCO->setEnabled(custom);
1601 }
1602
1603
1604 void GuiDocument::setColSep()
1605 {
1606         setCustomMargins(marginsModule->marginCB->checkState() == Qt::Checked);
1607 }
1608
1609
1610 void GuiDocument::setCustomMargins(bool custom)
1611 {
1612         marginsModule->topL->setEnabled(!custom);
1613         marginsModule->topLE->setEnabled(!custom);
1614         marginsModule->topUnit->setEnabled(!custom);
1615
1616         marginsModule->bottomL->setEnabled(!custom);
1617         marginsModule->bottomLE->setEnabled(!custom);
1618         marginsModule->bottomUnit->setEnabled(!custom);
1619
1620         marginsModule->innerL->setEnabled(!custom);
1621         marginsModule->innerLE->setEnabled(!custom);
1622         marginsModule->innerUnit->setEnabled(!custom);
1623
1624         marginsModule->outerL->setEnabled(!custom);
1625         marginsModule->outerLE->setEnabled(!custom);
1626         marginsModule->outerUnit->setEnabled(!custom);
1627
1628         marginsModule->headheightL->setEnabled(!custom);
1629         marginsModule->headheightLE->setEnabled(!custom);
1630         marginsModule->headheightUnit->setEnabled(!custom);
1631
1632         marginsModule->headsepL->setEnabled(!custom);
1633         marginsModule->headsepLE->setEnabled(!custom);
1634         marginsModule->headsepUnit->setEnabled(!custom);
1635
1636         marginsModule->footskipL->setEnabled(!custom);
1637         marginsModule->footskipLE->setEnabled(!custom);
1638         marginsModule->footskipUnit->setEnabled(!custom);
1639
1640         bool const enableColSep = !custom &&
1641                         textLayoutModule->twoColumnCB->checkState() == Qt::Checked;
1642         marginsModule->columnsepL->setEnabled(enableColSep);
1643         marginsModule->columnsepLE->setEnabled(enableColSep);
1644         marginsModule->columnsepUnit->setEnabled(enableColSep);
1645 }
1646
1647
1648 void GuiDocument::changeBackgroundColor()
1649 {
1650         QColor const & newColor = QColorDialog::getColor(
1651                 rgb2qcolor(set_backgroundcolor), asQWidget());
1652         if (!newColor.isValid())
1653                 return;
1654         // set the button color and text
1655         colorModule->backgroundPB->setStyleSheet(
1656                 colorButtonStyleSheet(newColor));
1657         colorModule->backgroundPB->setText(qt_("&Change..."));
1658         // save color
1659         set_backgroundcolor = rgbFromHexName(fromqstr(newColor.name()));
1660         is_backgroundcolor = true;
1661         change_adaptor();
1662 }
1663
1664
1665 void GuiDocument::deleteBackgroundColor()
1666 {
1667         // set the button color back to default by setting an empty StyleSheet
1668         colorModule->backgroundPB->setStyleSheet(QLatin1String(""));
1669         // change button text
1670         colorModule->backgroundPB->setText(qt_("&Default..."));
1671         // save default color (white)
1672         set_backgroundcolor = rgbFromHexName("#ffffff");
1673         is_backgroundcolor = false;
1674         change_adaptor();
1675 }
1676
1677
1678 void GuiDocument::changeFontColor()
1679 {
1680         QColor const & newColor = QColorDialog::getColor(
1681                 rgb2qcolor(set_fontcolor), asQWidget());
1682         if (!newColor.isValid())
1683                 return;
1684         // set the button color and text
1685         colorModule->fontColorPB->setStyleSheet(
1686                 colorButtonStyleSheet(newColor));
1687         colorModule->fontColorPB->setText(qt_("&Change..."));
1688         // save color
1689         set_fontcolor = rgbFromHexName(fromqstr(newColor.name()));
1690         is_fontcolor = true;
1691         change_adaptor();
1692 }
1693
1694
1695 void GuiDocument::deleteFontColor()
1696 {
1697         // set the button color back to default by setting an empty StyleSheet
1698         colorModule->fontColorPB->setStyleSheet(QLatin1String(""));
1699         // change button text
1700         colorModule->fontColorPB->setText(qt_("&Default..."));
1701         // save default color (black)
1702         set_fontcolor = rgbFromHexName("#000000");
1703         is_fontcolor = false;
1704         change_adaptor();
1705 }
1706
1707
1708 void GuiDocument::changeNoteFontColor()
1709 {
1710         QColor const & newColor = QColorDialog::getColor(
1711                 rgb2qcolor(set_notefontcolor), asQWidget());
1712         if (!newColor.isValid())
1713                 return;
1714         // set the button color
1715         colorModule->noteFontColorPB->setStyleSheet(
1716                 colorButtonStyleSheet(newColor));
1717         // save color
1718         set_notefontcolor = rgbFromHexName(fromqstr(newColor.name()));
1719         change_adaptor();
1720 }
1721
1722
1723 void GuiDocument::deleteNoteFontColor()
1724 {
1725         // set the button color back to pref
1726         theApp()->getRgbColor(Color_greyedouttext, set_notefontcolor);
1727         colorModule->noteFontColorPB->setStyleSheet(
1728                 colorButtonStyleSheet(rgb2qcolor(set_notefontcolor)));
1729         change_adaptor();
1730 }
1731
1732
1733 void GuiDocument::changeBoxBackgroundColor()
1734 {
1735         QColor const & newColor = QColorDialog::getColor(
1736                 rgb2qcolor(set_boxbgcolor), asQWidget());
1737         if (!newColor.isValid())
1738                 return;
1739         // set the button color
1740         colorModule->boxBackgroundPB->setStyleSheet(
1741                 colorButtonStyleSheet(newColor));
1742         // save color
1743         set_boxbgcolor = rgbFromHexName(fromqstr(newColor.name()));
1744         change_adaptor();
1745 }
1746
1747
1748 void GuiDocument::deleteBoxBackgroundColor()
1749 {
1750         // set the button color back to pref
1751         theApp()->getRgbColor(Color_shadedbg, set_boxbgcolor);
1752         colorModule->boxBackgroundPB->setStyleSheet(
1753                 colorButtonStyleSheet(rgb2qcolor(set_boxbgcolor)));
1754         change_adaptor();
1755 }
1756
1757
1758 void GuiDocument::languageChanged(int i)
1759 {
1760         // some languages only work with polyglossia
1761         Language const * lang = lyx::languages.getLanguage(
1762                 fromqstr(langModule->languageCO->itemData(i).toString()));
1763         if (lang->babel().empty() && !lang->polyglossia().empty()) {
1764                         // If we force to switch fontspec on, store
1765                         // current state (#8717)
1766                         if (fontModule->osFontsCB->isEnabled())
1767                                 forced_fontspec_activation =
1768                                         !fontModule->osFontsCB->isChecked();
1769                         fontModule->osFontsCB->setChecked(true);
1770                         fontModule->osFontsCB->setEnabled(false);
1771         }
1772         else {
1773                 fontModule->osFontsCB->setEnabled(true);
1774                 // If we have forced to switch fontspec on,
1775                 // restore previous state (#8717)
1776                 if (forced_fontspec_activation)
1777                         fontModule->osFontsCB->setChecked(false);
1778                 forced_fontspec_activation = false;
1779         }
1780
1781         // set appropriate quotation mark style
1782         if (!lang->quoteStyle().empty()) {
1783                 langModule->quoteStyleCO->setCurrentIndex(
1784                         bp_.getQuoteStyle(lang->quoteStyle()));
1785         }
1786 }
1787
1788
1789 void GuiDocument::osFontsChanged(bool nontexfonts)
1790 {
1791         bool const tex_fonts = !nontexfonts;
1792         // store current fonts
1793         QString const font_roman = fontModule->fontsRomanCO->itemData(
1794                         fontModule->fontsRomanCO->currentIndex()).toString();
1795         QString const font_sans = fontModule->fontsSansCO->itemData(
1796                         fontModule->fontsSansCO->currentIndex()).toString();
1797         QString const font_typewriter = fontModule->fontsTypewriterCO->itemData(
1798                         fontModule->fontsTypewriterCO->currentIndex()).toString();
1799         QString const font_math = fontModule->fontsMathCO->itemData(
1800                         fontModule->fontsMathCO->currentIndex()).toString();
1801         int const font_sf_scale = fontModule->scaleSansSB->value();
1802         int const font_tt_scale = fontModule->scaleTypewriterSB->value();
1803
1804         updateFontlist();
1805         // store default format
1806         QString const dformat = outputModule->defaultFormatCO->itemData(
1807                 outputModule->defaultFormatCO->currentIndex()).toString();
1808         updateDefaultFormat();
1809         // try to restore default format
1810         int index = outputModule->defaultFormatCO->findData(dformat);
1811         // set to default if format is not found
1812         if (index == -1)
1813                 index = 0;
1814         outputModule->defaultFormatCO->setCurrentIndex(index);
1815
1816         // try to restore fonts which were selected two toggles ago
1817         index = fontModule->fontsRomanCO->findData(fontModule->font_roman);
1818         if (index != -1)
1819                 fontModule->fontsRomanCO->setCurrentIndex(index);
1820         index = fontModule->fontsSansCO->findData(fontModule->font_sans);
1821         if (index != -1)
1822                 fontModule->fontsSansCO->setCurrentIndex(index);
1823         index = fontModule->fontsTypewriterCO->findData(fontModule->font_typewriter);
1824         if (index != -1)
1825                 fontModule->fontsTypewriterCO->setCurrentIndex(index);
1826         index = fontModule->fontsMathCO->findData(fontModule->font_math);
1827         if (index != -1)
1828                 fontModule->fontsMathCO->setCurrentIndex(index);
1829         // save fonts for next next toggle
1830         fontModule->font_roman = font_roman;
1831         fontModule->font_sans = font_sans;
1832         fontModule->font_typewriter = font_typewriter;
1833         fontModule->font_math = font_math;
1834         fontModule->font_sf_scale = font_sf_scale;
1835         fontModule->font_tt_scale = font_tt_scale;
1836
1837         langModule->encodingCO->setEnabled(tex_fonts &&
1838                 !langModule->defaultencodingRB->isChecked());
1839         langModule->defaultencodingRB->setEnabled(tex_fonts);
1840         langModule->otherencodingRB->setEnabled(tex_fonts);
1841
1842         fontModule->fontsDefaultCO->setEnabled(tex_fonts);
1843         fontModule->fontsDefaultLA->setEnabled(tex_fonts);
1844         fontModule->cjkFontLE->setEnabled(tex_fonts);
1845         fontModule->cjkFontLA->setEnabled(tex_fonts);
1846
1847         updateFontOptions();
1848
1849         fontModule->fontencLA->setEnabled(tex_fonts);
1850         fontModule->fontencCO->setEnabled(tex_fonts);
1851         if (!tex_fonts)
1852                 fontModule->fontencLE->setEnabled(false);
1853         else
1854                 fontencChanged(fontModule->fontencCO->currentIndex());
1855 }
1856
1857
1858 void GuiDocument::mathFontChanged(int)
1859 {
1860         updateFontOptions();
1861 }
1862
1863
1864 void GuiDocument::fontOsfToggled(bool state)
1865 {
1866         if (fontModule->osFontsCB->isChecked())
1867                 return;
1868         QString font = fontModule->fontsRomanCO->itemData(
1869                         fontModule->fontsRomanCO->currentIndex()).toString();
1870         if (hasMonolithicExpertSet(font))
1871                 fontModule->fontScCB->setChecked(state);
1872 }
1873
1874
1875 void GuiDocument::fontScToggled(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->fontOsfCB->setChecked(state);
1883 }
1884
1885
1886 void GuiDocument::updateFontOptions()
1887 {
1888         bool const tex_fonts = !fontModule->osFontsCB->isChecked();
1889         QString font;
1890         if (tex_fonts)
1891                 font = fontModule->fontsSansCO->itemData(
1892                                 fontModule->fontsSansCO->currentIndex()).toString();
1893         bool scaleable = providesScale(font);
1894         fontModule->scaleSansSB->setEnabled(scaleable);
1895         fontModule->scaleSansLA->setEnabled(scaleable);
1896         if (tex_fonts)
1897                 font = fontModule->fontsTypewriterCO->itemData(
1898                                 fontModule->fontsTypewriterCO->currentIndex()).toString();
1899         scaleable = providesScale(font);
1900         fontModule->scaleTypewriterSB->setEnabled(scaleable);
1901         fontModule->scaleTypewriterLA->setEnabled(scaleable);
1902         if (tex_fonts)
1903                 font = fontModule->fontsRomanCO->itemData(
1904                                 fontModule->fontsRomanCO->currentIndex()).toString();
1905         fontModule->fontScCB->setEnabled(providesSC(font));
1906         fontModule->fontOsfCB->setEnabled(providesOSF(font));
1907         updateMathFonts(font);
1908 }
1909
1910
1911 void GuiDocument::updateFontsize(string const & items, string const & sel)
1912 {
1913         fontModule->fontsizeCO->clear();
1914         fontModule->fontsizeCO->addItem(qt_("Default"));
1915
1916         for (int n = 0; !token(items,'|',n).empty(); ++n)
1917                 fontModule->fontsizeCO->
1918                         addItem(toqstr(token(items,'|',n)));
1919
1920         for (int n = 0; n < fontModule->fontsizeCO->count(); ++n) {
1921                 if (fromqstr(fontModule->fontsizeCO->itemText(n)) == sel) {
1922                         fontModule->fontsizeCO->setCurrentIndex(n);
1923                         break;
1924                 }
1925         }
1926 }
1927
1928
1929 bool GuiDocument::ot1() const
1930 {
1931         QString const fontenc =
1932                 fontModule->fontencCO->itemData(fontModule->fontencCO->currentIndex()).toString();
1933         return (fontenc == "default"
1934                 || (fontenc == "global" && (lyxrc.fontenc == "default" || lyxrc.fontenc == "OT1"))
1935                 || (fontenc == "custom" && fontModule->fontencLE->text() == "OT1"));
1936 }
1937
1938
1939 bool GuiDocument::completeFontset() const
1940 {
1941         return (fontModule->fontsSansCO->itemData(
1942                         fontModule->fontsSansCO->currentIndex()).toString() == "default"
1943                 && fontModule->fontsSansCO->itemData(
1944                         fontModule->fontsTypewriterCO->currentIndex()).toString() == "default");
1945 }
1946
1947
1948 bool GuiDocument::noMathFont() const
1949 {
1950         return (fontModule->fontsMathCO->itemData(
1951                 fontModule->fontsMathCO->currentIndex()).toString() == "default");
1952 }
1953
1954
1955 void GuiDocument::updateTexFonts()
1956 {
1957         LaTeXFonts::TexFontMap texfontmap = theLaTeXFonts().getLaTeXFonts();
1958
1959         LaTeXFonts::TexFontMap::const_iterator it = texfontmap.begin();
1960         LaTeXFonts::TexFontMap::const_iterator end = texfontmap.end();
1961         for (; it != end; ++it) {
1962                 LaTeXFont lf = it->second;
1963                 if (lf.name().empty()) {
1964                         LYXERR0("Error: Unnamed font: " << it->first);
1965                         continue;
1966                 }
1967                 docstring const family = lf.family();
1968                 docstring guiname = translateIfPossible(lf.guiname());
1969                 if (!lf.available(ot1(), noMathFont()))
1970                         guiname += _(" (not installed)");
1971                 if (family == "rm")
1972                         rmfonts_.insert(toqstr(guiname), toqstr(it->first));
1973                 else if (family == "sf")
1974                         sffonts_.insert(toqstr(guiname), toqstr(it->first));
1975                 else if (family == "tt")
1976                         ttfonts_.insert(toqstr(guiname), toqstr(it->first));
1977                 else if (family == "math")
1978                         mathfonts_.insert(toqstr(guiname), toqstr(it->first));
1979         }
1980 }
1981
1982
1983 void GuiDocument::updateFontlist()
1984 {
1985         fontModule->fontsRomanCO->clear();
1986         fontModule->fontsSansCO->clear();
1987         fontModule->fontsTypewriterCO->clear();
1988         fontModule->fontsMathCO->clear();
1989
1990         // With fontspec (XeTeX, LuaTeX), we have access to all system fonts, but not the LaTeX fonts
1991         if (fontModule->osFontsCB->isChecked()) {
1992                 fontModule->fontsRomanCO->addItem(qt_("Default"), QString("default"));
1993                 fontModule->fontsSansCO->addItem(qt_("Default"), QString("default"));
1994                 fontModule->fontsTypewriterCO->addItem(qt_("Default"), QString("default"));
1995                 QString unimath = qt_("Non-TeX Fonts Default");
1996                 if (!LaTeXFeatures::isAvailable("unicode-math"))
1997                         unimath += qt_(" (not available)");
1998                 fontModule->fontsMathCO->addItem(qt_("Class Default (TeX Fonts)"), QString("auto"));
1999                 fontModule->fontsMathCO->addItem(unimath, QString("default"));
2000
2001                 QFontDatabase fontdb;
2002                 QStringList families(fontdb.families());
2003                 for (QStringList::Iterator it = families.begin(); it != families.end(); ++it) {
2004                         fontModule->fontsRomanCO->addItem(*it, *it);
2005                         fontModule->fontsSansCO->addItem(*it, *it);
2006                         fontModule->fontsTypewriterCO->addItem(*it, *it);
2007                 }
2008                 return;
2009         }
2010
2011         if (rmfonts_.empty())
2012                 updateTexFonts();
2013
2014         fontModule->fontsRomanCO->addItem(qt_("Default"), QString("default"));
2015         QMap<QString, QString>::const_iterator rmi = rmfonts_.constBegin();
2016         while (rmi != rmfonts_.constEnd()) {
2017                 fontModule->fontsRomanCO->addItem(rmi.key(), rmi.value());
2018                 ++rmi;
2019         }
2020
2021         fontModule->fontsSansCO->addItem(qt_("Default"), QString("default"));
2022         QMap<QString, QString>::const_iterator sfi = sffonts_.constBegin();
2023         while (sfi != sffonts_.constEnd()) {
2024                 fontModule->fontsSansCO->addItem(sfi.key(), sfi.value());
2025                 ++sfi;
2026         }
2027
2028         fontModule->fontsTypewriterCO->addItem(qt_("Default"), QString("default"));
2029         QMap<QString, QString>::const_iterator tti = ttfonts_.constBegin();
2030         while (tti != ttfonts_.constEnd()) {
2031                 fontModule->fontsTypewriterCO->addItem(tti.key(), tti.value());
2032                 ++tti;
2033         }
2034
2035         fontModule->fontsMathCO->addItem(qt_("Automatic"), QString("auto"));
2036         fontModule->fontsMathCO->addItem(qt_("Class Default"), QString("default"));
2037         QMap<QString, QString>::const_iterator mmi = mathfonts_.constBegin();
2038         while (mmi != mathfonts_.constEnd()) {
2039                 fontModule->fontsMathCO->addItem(mmi.key(), mmi.value());
2040                 ++mmi;
2041         }
2042 }
2043
2044
2045 void GuiDocument::fontencChanged(int item)
2046 {
2047         fontModule->fontencLE->setEnabled(
2048                 fontModule->fontencCO->itemData(item).toString() == "custom");
2049         // The availability of TeX fonts depends on the font encoding
2050         updateTexFonts();
2051         updateFontOptions();
2052 }
2053
2054
2055 void GuiDocument::updateMathFonts(QString const & rm)
2056 {
2057         if (fontModule->osFontsCB->isChecked())
2058                 return;
2059         QString const math =
2060                 fontModule->fontsMathCO->itemData(fontModule->fontsMathCO->currentIndex()).toString();
2061         int const i = fontModule->fontsMathCO->findData("default");
2062         if (providesNoMath(rm) && i == -1)
2063                 fontModule->fontsMathCO->insertItem(1, qt_("Class Default"), QString("default"));
2064         else if (!providesNoMath(rm) && i != -1) {
2065                 int const c = fontModule->fontsMathCO->currentIndex();
2066                 fontModule->fontsMathCO->removeItem(i);
2067                 if (c == i)
2068                         fontModule->fontsMathCO->setCurrentIndex(0);
2069         }
2070 }
2071
2072
2073 void GuiDocument::romanChanged(int item)
2074 {
2075         if (fontModule->osFontsCB->isChecked())
2076                 return;
2077         QString const font =
2078                 fontModule->fontsRomanCO->itemData(item).toString();
2079         fontModule->fontScCB->setEnabled(providesSC(font));
2080         fontModule->fontOsfCB->setEnabled(providesOSF(font));
2081         updateMathFonts(font);
2082 }
2083
2084
2085 void GuiDocument::sansChanged(int item)
2086 {
2087         if (fontModule->osFontsCB->isChecked())
2088                 return;
2089         QString const font =
2090                 fontModule->fontsSansCO->itemData(item).toString();
2091         bool scaleable = providesScale(font);
2092         fontModule->scaleSansSB->setEnabled(scaleable);
2093         fontModule->scaleSansLA->setEnabled(scaleable);
2094 }
2095
2096
2097 void GuiDocument::ttChanged(int item)
2098 {
2099         if (fontModule->osFontsCB->isChecked())
2100                 return;
2101         QString const font =
2102                 fontModule->fontsTypewriterCO->itemData(item).toString();
2103         bool scaleable = providesScale(font);
2104         fontModule->scaleTypewriterSB->setEnabled(scaleable);
2105         fontModule->scaleTypewriterLA->setEnabled(scaleable);
2106 }
2107
2108
2109 void GuiDocument::updatePagestyle(string const & items, string const & sel)
2110 {
2111         pagestyles.clear();
2112         pageLayoutModule->pagestyleCO->clear();
2113         pageLayoutModule->pagestyleCO->addItem(qt_("Default"));
2114
2115         for (int n = 0; !token(items, '|', n).empty(); ++n) {
2116                 string style = token(items, '|', n);
2117                 QString style_gui = qt_(style);
2118                 pagestyles.push_back(pair<string, QString>(style, style_gui));
2119                 pageLayoutModule->pagestyleCO->addItem(style_gui);
2120         }
2121
2122         if (sel == "default") {
2123                 pageLayoutModule->pagestyleCO->setCurrentIndex(0);
2124                 return;
2125         }
2126
2127         int nn = 0;
2128
2129         for (size_t i = 0; i < pagestyles.size(); ++i)
2130                 if (pagestyles[i].first == sel)
2131                         nn = pageLayoutModule->pagestyleCO->findText(pagestyles[i].second);
2132
2133         if (nn > 0)
2134                 pageLayoutModule->pagestyleCO->setCurrentIndex(nn);
2135 }
2136
2137
2138 void GuiDocument::browseLayout()
2139 {
2140         QString const label1 = qt_("Layouts|#o#O");
2141         QString const dir1 = toqstr(lyxrc.document_path);
2142         QStringList const filter(qt_("LyX Layout (*.layout)"));
2143         QString file = browseRelToParent(QString(), bufferFilePath(),
2144                 qt_("Local layout file"), filter, false,
2145                 label1, dir1);
2146
2147         if (!file.endsWith(".layout"))
2148                 return;
2149
2150         FileName layoutFile = support::makeAbsPath(fromqstr(file),
2151                 fromqstr(bufferFilePath()));
2152
2153         int const ret = Alert::prompt(_("Local layout file"),
2154                 _("The layout file you have selected is a local layout\n"
2155                   "file, not one in the system or user directory.\n"
2156                   "Your document will not work with this layout if you\n"
2157                   "move the layout file to a different directory."),
2158                   1, 1, _("&Set Layout"), _("&Cancel"));
2159         if (ret == 1)
2160                 return;
2161
2162         // load the layout file
2163         LayoutFileList & bcl = LayoutFileList::get();
2164         string classname = layoutFile.onlyFileName();
2165         // this will update an existing layout if that layout has been loaded before.
2166         LayoutFileIndex name = support::onlyFileName(bcl.addLocalLayout(
2167                 classname.substr(0, classname.size() - 7),
2168                 layoutFile.onlyPath().absFileName()));
2169
2170         if (name.empty()) {
2171                 Alert::error(_("Error"),
2172                         _("Unable to read local layout file."));
2173                 return;
2174         }
2175
2176         const_cast<Buffer &>(buffer()).setLayoutPos(layoutFile.onlyPath().absFileName());
2177
2178         // do not trigger classChanged if there is no change.
2179         if (latexModule->classCO->currentText() == toqstr(name))
2180                 return;
2181
2182         // add to combo box
2183         bool const avail = latexModule->classCO->set(toqstr(name));
2184         if (!avail) {
2185                 LayoutFile const & tc = bcl[name];
2186                 docstring const guiname = translateIfPossible(from_utf8(tc.description()));
2187                 // tooltip sensu "KOMA-Script Article [Class 'scrartcl']"
2188                 QString tooltip = toqstr(bformat(_("%1$s [Class '%2$s']"), guiname, from_utf8(tc.latexname())));
2189                 tooltip += '\n' + qt_("This is a local layout file.");
2190                 latexModule->classCO->addItemSort(toqstr(tc.name()), toqstr(guiname),
2191                                                   toqstr(translateIfPossible(from_utf8(tc.category()))),
2192                                                   tooltip,
2193                                                   true, true, true, true);
2194                 latexModule->classCO->set(toqstr(name));
2195         }
2196
2197         classChanged();
2198 }
2199
2200
2201 void GuiDocument::browseMaster()
2202 {
2203         QString const title = qt_("Select master document");
2204         QString const dir1 = toqstr(lyxrc.document_path);
2205         QString const old = latexModule->childDocLE->text();
2206         QString const docpath = toqstr(support::onlyPath(buffer().absFileName()));
2207         QStringList const filter(qt_("LyX Files (*.lyx)"));
2208         QString file = browseRelToSub(old, docpath, title, filter, false,
2209                 qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
2210
2211         if (!file.isEmpty())
2212                 latexModule->childDocLE->setText(file);
2213 }
2214
2215
2216 void GuiDocument::classChanged_adaptor()
2217 {
2218         const_cast<Buffer &>(buffer()).setLayoutPos(string());
2219         classChanged();
2220 }
2221
2222
2223 void GuiDocument::classChanged()
2224 {
2225         int idx = latexModule->classCO->currentIndex();
2226         if (idx < 0)
2227                 return;
2228         string const classname = fromqstr(latexModule->classCO->getData(idx));
2229
2230         if (applyPB->isEnabled()) {
2231                 int const ret = Alert::prompt(_("Unapplied changes"),
2232                                 _("Some changes in the dialog were not yet applied.\n"
2233                                 "If you do not apply now, they will be lost after this action."),
2234                                 1, 1, _("&Apply"), _("&Dismiss"));
2235                 if (ret == 0)
2236                         applyView();
2237         }
2238
2239         // We load the TextClass as soon as it is selected. This is
2240         // necessary so that other options in the dialog can be updated
2241         // according to the new class. Note, however, that, if you use
2242         // the scroll wheel when sitting on the combo box, we'll load a
2243         // lot of TextClass objects very quickly....
2244         if (!bp_.setBaseClass(classname)) {
2245                 Alert::error(_("Error"), _("Unable to set document class."));
2246                 return;
2247         }
2248         if (lyxrc.auto_reset_options)
2249                 bp_.useClassDefaults();
2250
2251         // With the introduction of modules came a distinction between the base
2252         // class and the document class. The former corresponds to the main layout
2253         // file; the latter is that plus the modules (or the document-specific layout,
2254         // or  whatever else there could be). Our parameters come from the document
2255         // class. So when we set the base class, we also need to recreate the document
2256         // class. Otherwise, we still have the old one.
2257         bp_.makeDocumentClass();
2258         paramsToDialog();
2259 }
2260
2261
2262 void GuiDocument::languagePackageChanged(int i)
2263 {
2264          langModule->languagePackageLE->setEnabled(
2265                 langModule->languagePackageCO->itemData(i).toString() == "custom");
2266 }
2267
2268
2269 void GuiDocument::biblioChanged()
2270 {
2271         biblioChanged_ = true;
2272         change_adaptor();
2273 }
2274
2275
2276 void GuiDocument::bibtexChanged(int n)
2277 {
2278         biblioModule->bibtexOptionsLE->setEnabled(
2279                 biblioModule->bibtexCO->itemData(n).toString() != "default");
2280         biblioChanged();
2281 }
2282
2283
2284 void GuiDocument::setAuthorYear(bool authoryear)
2285 {
2286         if (authoryear)
2287                 biblioModule->citeStyleCO->setCurrentIndex(0);
2288         biblioChanged();
2289 }
2290
2291
2292 void GuiDocument::setNumerical(bool numerical)
2293 {
2294         if (numerical)
2295                 biblioModule->citeStyleCO->setCurrentIndex(1);
2296         biblioChanged();
2297 }
2298
2299
2300 void GuiDocument::updateEngineType(string const & items, CiteEngineType const & sel)
2301 {
2302         engine_types_.clear();
2303
2304         int nn = 0;
2305
2306         for (int n = 0; !token(items, '|', n).empty(); ++n) {
2307                 nn += 1;
2308                 string style = token(items, '|', n);
2309                 engine_types_.push_back(style);
2310         }
2311
2312         switch (sel) {
2313                 case ENGINE_TYPE_AUTHORYEAR:
2314                         biblioModule->citeStyleCO->setCurrentIndex(0);
2315                         break;
2316                 case ENGINE_TYPE_NUMERICAL:
2317                 case ENGINE_TYPE_DEFAULT:
2318                         biblioModule->citeStyleCO->setCurrentIndex(1);
2319                         break;
2320         }
2321
2322         biblioModule->citationStyleL->setEnabled(nn > 1);
2323         biblioModule->citeStyleCO->setEnabled(nn > 1);
2324
2325         if (nn != 1)
2326                 return;
2327
2328         // If the textclass allows only one of authoryear or numerical,
2329         // we have no choice but to force that engine type.
2330         if (engine_types_[0] == "authoryear")
2331                 biblioModule->citeStyleCO->setCurrentIndex(0);
2332         else
2333                 biblioModule->citeStyleCO->setCurrentIndex(1);
2334 }
2335
2336
2337 namespace {
2338         // FIXME unicode
2339         // both of these should take a vector<docstring>
2340
2341         // This is an insanely complicated attempt to make this sort of thing
2342         // work with RTL languages.
2343         docstring formatStrVec(vector<string> const & v, docstring const & s)
2344         {
2345                 //this mess formats the list as "v[0], v[1], ..., [s] v[n]"
2346                 if (v.empty())
2347                         return docstring();
2348                 if (v.size() == 1)
2349                         return translateIfPossible(from_utf8(v[0]));
2350                 if (v.size() == 2) {
2351                         docstring retval = _("%1$s and %2$s");
2352                         retval = subst(retval, _("and"), s);
2353                         return bformat(retval, translateIfPossible(from_utf8(v[0])),
2354                                        translateIfPossible(from_utf8(v[1])));
2355                 }
2356                 // The idea here is to format all but the last two items...
2357                 int const vSize = v.size();
2358                 docstring t2 = _("%1$s, %2$s");
2359                 docstring retval = translateIfPossible(from_utf8(v[0]));
2360                 for (int i = 1; i < vSize - 2; ++i)
2361                         retval = bformat(t2, retval, translateIfPossible(from_utf8(v[i])));
2362                 //...and then to  plug them, and the last two, into this schema
2363                 docstring t = _("%1$s, %2$s, and %3$s");
2364                 t = subst(t, _("and"), s);
2365                 return bformat(t, retval, translateIfPossible(from_utf8(v[vSize - 2])),
2366                                translateIfPossible(from_utf8(v[vSize - 1])));
2367         }
2368
2369         vector<string> idsToNames(vector<string> const & idList)
2370         {
2371                 vector<string> retval;
2372                 vector<string>::const_iterator it  = idList.begin();
2373                 vector<string>::const_iterator end = idList.end();
2374                 for (; it != end; ++it) {
2375                         LyXModule const * const mod = theModuleList[*it];
2376                         if (!mod)
2377                                 retval.push_back(to_utf8(bformat(_("%1$s (unavailable)"),
2378                                                 translateIfPossible(from_utf8(*it)))));
2379                         else
2380                                 retval.push_back(mod->getName());
2381                 }
2382                 return retval;
2383         }
2384 } // end anonymous namespace
2385
2386
2387 void GuiDocument::modulesToParams(BufferParams & bp)
2388 {
2389         // update list of loaded modules
2390         bp.clearLayoutModules();
2391         int const srows = modules_sel_model_.rowCount();
2392         for (int i = 0; i < srows; ++i)
2393                 bp.addLayoutModule(modules_sel_model_.getIDString(i));
2394
2395         // update the list of removed modules
2396         bp.clearRemovedModules();
2397         LayoutModuleList const & reqmods = bp.baseClass()->defaultModules();
2398         list<string>::const_iterator rit = reqmods.begin();
2399         list<string>::const_iterator ren = reqmods.end();
2400
2401         // check each of the default modules
2402         for (; rit != ren; ++rit) {
2403                 list<string>::const_iterator mit = bp.getModules().begin();
2404                 list<string>::const_iterator men = bp.getModules().end();
2405                 bool found = false;
2406                 for (; mit != men; ++mit) {
2407                         if (*rit == *mit) {
2408                                 found = true;
2409                                 break;
2410                         }
2411                 }
2412                 if (!found) {
2413                         // the module isn't present so must have been removed by the user
2414                         bp.addRemovedModule(*rit);
2415                 }
2416         }
2417 }
2418
2419 void GuiDocument::modulesChanged()
2420 {
2421         modulesToParams(bp_);
2422
2423         if (applyPB->isEnabled() && nonModuleChanged_) {
2424                 int const ret = Alert::prompt(_("Unapplied changes"),
2425                                 _("Some changes in the dialog were not yet applied.\n"
2426                                 "If you do not apply now, they will be lost after this action."),
2427                                 1, 1, _("&Apply"), _("&Dismiss"));
2428                 if (ret == 0)
2429                         applyView();
2430         }
2431
2432         bp_.makeDocumentClass();
2433         paramsToDialog();
2434         changed();
2435 }
2436
2437
2438 void GuiDocument::updateModuleInfo()
2439 {
2440         selectionManager->update();
2441
2442         //Module description
2443         bool const focus_on_selected = selectionManager->selectedFocused();
2444         QAbstractItemView * lv;
2445         if (focus_on_selected)
2446                 lv = modulesModule->selectedLV;
2447         else
2448                 lv = modulesModule->availableLV;
2449         if (lv->selectionModel()->selectedIndexes().isEmpty()) {
2450                 modulesModule->infoML->document()->clear();
2451                 return;
2452         }
2453         QModelIndex const & idx = lv->selectionModel()->currentIndex();
2454         GuiIdListModel const & id_model =
2455                         focus_on_selected  ? modules_sel_model_ : modules_av_model_;
2456         string const modName = id_model.getIDString(idx.row());
2457         docstring desc = getModuleDescription(modName);
2458
2459         LayoutModuleList const & provmods = bp_.baseClass()->providedModules();
2460         if (std::find(provmods.begin(), provmods.end(), modName) != provmods.end()) {
2461                 if (!desc.empty())
2462                         desc += "\n";
2463                 desc += _("Module provided by document class.");
2464         }
2465
2466         docstring cat = getModuleCategory(modName);
2467         if (!cat.empty()) {
2468                 if (!desc.empty())
2469                         desc += "\n";
2470                 desc += bformat(_("Category: %1$s."), cat);
2471         }
2472
2473         vector<string> pkglist = getPackageList(modName);
2474         docstring pkgdesc = formatStrVec(pkglist, _("and"));
2475         if (!pkgdesc.empty()) {
2476                 if (!desc.empty())
2477                         desc += "\n";
2478                 desc += bformat(_("Package(s) required: %1$s."), pkgdesc);
2479         }
2480
2481         pkglist = getRequiredList(modName);
2482         if (!pkglist.empty()) {
2483                 vector<string> const reqdescs = idsToNames(pkglist);
2484                 pkgdesc = formatStrVec(reqdescs, _("or"));
2485                 if (!desc.empty())
2486                         desc += "\n";
2487                 desc += bformat(_("Modules required: %1$s."), pkgdesc);
2488         }
2489
2490         pkglist = getExcludedList(modName);
2491         if (!pkglist.empty()) {
2492                 vector<string> const reqdescs = idsToNames(pkglist);
2493                 pkgdesc = formatStrVec(reqdescs, _( "and"));
2494                 if (!desc.empty())
2495                         desc += "\n";
2496                 desc += bformat(_("Modules excluded: %1$s."), pkgdesc);
2497         }
2498
2499         if (!isModuleAvailable(modName)) {
2500                 if (!desc.empty())
2501                         desc += "\n";
2502                 desc += _("WARNING: Some required packages are unavailable!");
2503         }
2504
2505         modulesModule->infoML->document()->setPlainText(toqstr(desc));
2506 }
2507
2508
2509 void GuiDocument::updateNumbering()
2510 {
2511         DocumentClass const & tclass = documentClass();
2512
2513         numberingModule->tocTW->setUpdatesEnabled(false);
2514         numberingModule->tocTW->clear();
2515
2516         int const depth = numberingModule->depthSL->value();
2517         int const toc = numberingModule->tocSL->value();
2518         QString const no = qt_("No");
2519         QString const yes = qt_("Yes");
2520         QTreeWidgetItem * item = 0;
2521
2522         DocumentClass::const_iterator lit = tclass.begin();
2523         DocumentClass::const_iterator len = tclass.end();
2524         for (; lit != len; ++lit) {
2525                 int const toclevel = lit->toclevel;
2526                 if (toclevel != Layout::NOT_IN_TOC && !lit->counter.empty()) {
2527                         item = new QTreeWidgetItem(numberingModule->tocTW);
2528                         item->setText(0, toqstr(translateIfPossible(lit->name())));
2529                         item->setText(1, (toclevel <= depth) ? yes : no);
2530                         item->setText(2, (toclevel <= toc) ? yes : no);
2531                 }
2532         }
2533
2534         numberingModule->tocTW->setUpdatesEnabled(true);
2535         numberingModule->tocTW->update();
2536 }
2537
2538
2539 void GuiDocument::updateDefaultFormat()
2540 {
2541         if (!bufferview())
2542                 return;
2543         // make a copy in order to consider unapplied changes
2544         BufferParams param_copy = buffer().params();
2545         param_copy.useNonTeXFonts = fontModule->osFontsCB->isChecked();
2546         int const idx = latexModule->classCO->currentIndex();
2547         if (idx >= 0) {
2548                 string const classname = fromqstr(latexModule->classCO->getData(idx));
2549                 param_copy.setBaseClass(classname);
2550                 param_copy.makeDocumentClass(true);
2551         }
2552         outputModule->defaultFormatCO->blockSignals(true);
2553         outputModule->defaultFormatCO->clear();
2554         outputModule->defaultFormatCO->addItem(qt_("Default"),
2555                                 QVariant(QString("default")));
2556         typedef vector<Format const *> Formats;
2557         Formats formats = param_copy.exportableFormats(true);
2558         sort(formats.begin(), formats.end(), Format::formatSorter);
2559         Formats::const_iterator cit = formats.begin();
2560         Formats::const_iterator end = formats.end();
2561         for (; cit != end; ++cit)
2562                 outputModule->defaultFormatCO->addItem(qt_((*cit)->prettyname()),
2563                                 QVariant(toqstr((*cit)->name())));
2564         outputModule->defaultFormatCO->blockSignals(false);
2565 }
2566
2567
2568 bool GuiDocument::isChildIncluded(string const & child)
2569 {
2570         if (includeonlys_.empty())
2571                 return false;
2572         return (std::find(includeonlys_.begin(),
2573                           includeonlys_.end(), child) != includeonlys_.end());
2574 }
2575
2576
2577 void GuiDocument::applyView()
2578 {
2579         // preamble
2580         preambleModule->apply(bp_);
2581         localLayout->apply(bp_);
2582
2583         // date
2584         bp_.suppress_date = latexModule->suppressDateCB->isChecked();
2585         bp_.use_refstyle  = latexModule->refstyleCB->isChecked();
2586
2587         // biblio
2588         if (biblioModule->citeNatbibRB->isChecked())
2589                 bp_.setCiteEngine("natbib");
2590         else if (biblioModule->citeJurabibRB->isChecked())
2591                 bp_.setCiteEngine("jurabib");
2592         if (biblioModule->citeDefaultRB->isChecked()) {
2593                 bp_.setCiteEngine("basic");
2594                 bp_.setCiteEngineType(ENGINE_TYPE_DEFAULT);
2595         }
2596         else
2597         if (biblioModule->citeStyleCO->currentIndex())
2598                 bp_.setCiteEngineType(ENGINE_TYPE_NUMERICAL);
2599         else
2600                 bp_.setCiteEngineType(ENGINE_TYPE_AUTHORYEAR);
2601
2602         bp_.use_bibtopic =
2603                 biblioModule->bibtopicCB->isChecked();
2604
2605         bp_.biblio_style = fromqstr(biblioModule->bibtexStyleLE->text());
2606
2607         string const bibtex_command =
2608                 fromqstr(biblioModule->bibtexCO->itemData(
2609                         biblioModule->bibtexCO->currentIndex()).toString());
2610         string const bibtex_options =
2611                 fromqstr(biblioModule->bibtexOptionsLE->text());
2612         if (bibtex_command == "default" || bibtex_options.empty())
2613                 bp_.bibtex_command = bibtex_command;
2614         else
2615                 bp_.bibtex_command = bibtex_command + " " + bibtex_options;
2616
2617         if (biblioChanged_) {
2618                 buffer().invalidateBibinfoCache();
2619                 buffer().removeBiblioTempFiles();
2620         }
2621
2622         // Indices
2623         indicesModule->apply(bp_);
2624
2625         // language & quotes
2626         if (langModule->defaultencodingRB->isChecked()) {
2627                 bp_.inputenc = "auto";
2628         } else {
2629                 int i = langModule->encodingCO->currentIndex();
2630                 if (i == 0)
2631                         bp_.inputenc = "default";
2632                 else {
2633                         QString const enc_gui =
2634                                 langModule->encodingCO->currentText();
2635                         Encodings::const_iterator it = encodings.begin();
2636                         Encodings::const_iterator const end = encodings.end();
2637                         bool found = false;
2638                         for (; it != end; ++it) {
2639                                 if (qt_(it->guiName()) == enc_gui &&
2640                                     !it->unsafe()) {
2641                                         bp_.inputenc = it->name();
2642                                         found = true;
2643                                         break;
2644                                 }
2645                         }
2646                         if (!found) {
2647                                 // should not happen
2648                                 lyxerr << "GuiDocument::apply: Unknown encoding! Resetting to default" << endl;
2649                                 bp_.inputenc = "default";
2650                         }
2651                 }
2652         }
2653
2654         bp_.quotes_language = (InsetQuotes::QuoteLanguage) langModule->quoteStyleCO->itemData(
2655                 langModule->quoteStyleCO->currentIndex()).toInt();
2656
2657         QString const langname = langModule->languageCO->itemData(
2658                 langModule->languageCO->currentIndex()).toString();
2659         Language const * newlang = lyx::languages.getLanguage(fromqstr(langname));
2660         Cursor & cur = const_cast<BufferView *>(bufferview())->cursor();
2661         // If current cursor language was the document language, then update it too.
2662         if (cur.current_font.language() == bp_.language) {
2663                 cur.current_font.setLanguage(newlang);
2664                 cur.real_current_font.setLanguage(newlang);
2665         }
2666         bp_.language = newlang;
2667
2668         QString const pack = langModule->languagePackageCO->itemData(
2669                 langModule->languagePackageCO->currentIndex()).toString();
2670         if (pack == "custom")
2671                 bp_.lang_package =
2672                         fromqstr(langModule->languagePackageLE->text());
2673         else
2674                 bp_.lang_package = fromqstr(pack);
2675
2676         //color
2677         bp_.backgroundcolor = set_backgroundcolor;
2678         bp_.isbackgroundcolor = is_backgroundcolor;
2679         bp_.fontcolor = set_fontcolor;
2680         bp_.isfontcolor = is_fontcolor;
2681         bp_.notefontcolor = set_notefontcolor;
2682         bp_.boxbgcolor = set_boxbgcolor;
2683
2684         // numbering
2685         if (bp_.documentClass().hasTocLevels()) {
2686                 bp_.tocdepth = numberingModule->tocSL->value();
2687                 bp_.secnumdepth = numberingModule->depthSL->value();
2688         }
2689
2690         // bullets
2691         bp_.user_defined_bullet(0) = bulletsModule->bullet(0);
2692         bp_.user_defined_bullet(1) = bulletsModule->bullet(1);
2693         bp_.user_defined_bullet(2) = bulletsModule->bullet(2);
2694         bp_.user_defined_bullet(3) = bulletsModule->bullet(3);
2695
2696         // packages
2697         bp_.graphics_driver =
2698                 tex_graphics[latexModule->psdriverCO->currentIndex()];
2699
2700         // text layout
2701         int idx = latexModule->classCO->currentIndex();
2702         if (idx >= 0) {
2703                 string const classname = fromqstr(latexModule->classCO->getData(idx));
2704                 bp_.setBaseClass(classname);
2705         }
2706
2707         // Modules
2708         modulesToParams(bp_);
2709
2710         // Math
2711         map<string, string> const & packages = BufferParams::auto_packages();
2712         for (map<string, string>::const_iterator it = packages.begin();
2713              it != packages.end(); ++it) {
2714                 QTableWidgetItem * item = mathsModule->packagesTW->findItems(toqstr(it->first), Qt::MatchExactly)[0];
2715                 if (!item)
2716                         continue;
2717                 int row = mathsModule->packagesTW->row(item);
2718                 QRadioButton * rb = (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 1);
2719                 if (rb->isChecked()) {
2720                         bp_.use_package(it->first, BufferParams::package_auto);
2721                         continue;
2722                 }
2723                 rb = (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 2);
2724                 if (rb->isChecked()) {
2725                         bp_.use_package(it->first, BufferParams::package_on);
2726                         continue;
2727                 }
2728                 rb = (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 3);
2729                 if (rb->isChecked())
2730                         bp_.use_package(it->first, BufferParams::package_off);
2731         }
2732
2733         // Page Layout
2734         if (pageLayoutModule->pagestyleCO->currentIndex() == 0)
2735                 bp_.pagestyle = "default";
2736         else {
2737                 QString style_gui = pageLayoutModule->pagestyleCO->currentText();
2738                 for (size_t i = 0; i != pagestyles.size(); ++i)
2739                         if (pagestyles[i].second == style_gui)
2740                                 bp_.pagestyle = pagestyles[i].first;
2741         }
2742
2743         // Text Layout
2744         switch (textLayoutModule->lspacingCO->currentIndex()) {
2745         case 0:
2746                 bp_.spacing().set(Spacing::Single);
2747                 break;
2748         case 1:
2749                 bp_.spacing().set(Spacing::Onehalf);
2750                 break;
2751         case 2:
2752                 bp_.spacing().set(Spacing::Double);
2753                 break;
2754         case 3: {
2755                 string s = widgetToDoubleStr(textLayoutModule->lspacingLE);
2756                 if (s.empty())
2757                         bp_.spacing().set(Spacing::Single);
2758                 else
2759                         bp_.spacing().set(Spacing::Other, s);
2760                 break;
2761                 }
2762         }
2763
2764         if (textLayoutModule->twoColumnCB->isChecked())
2765                 bp_.columns = 2;
2766         else
2767                 bp_.columns = 1;
2768
2769         bp_.justification = textLayoutModule->justCB->isChecked();
2770
2771         if (textLayoutModule->indentRB->isChecked()) {
2772                 // if paragraphs are separated by an indentation
2773                 bp_.paragraph_separation = BufferParams::ParagraphIndentSeparation;
2774                 switch (textLayoutModule->indentCO->currentIndex()) {
2775                 case 0:
2776                         bp_.setIndentation(HSpace(HSpace::DEFAULT));
2777                         break;
2778                 case 1: {
2779                         HSpace indent = HSpace(
2780                                 widgetsToLength(textLayoutModule->indentLE,
2781                                 textLayoutModule->indentLengthCO)
2782                                 );
2783                         bp_.setIndentation(indent);
2784                         break;
2785                         }
2786                 default:
2787                         // this should never happen
2788                         bp_.setIndentation(HSpace(HSpace::DEFAULT));
2789                         break;
2790                 }
2791         } else {
2792                 // if paragraphs are separated by a skip
2793                 bp_.paragraph_separation = BufferParams::ParagraphSkipSeparation;
2794                 switch (textLayoutModule->skipCO->currentIndex()) {
2795                 case 0:
2796                         bp_.setDefSkip(VSpace(VSpace::SMALLSKIP));
2797                         break;
2798                 case 1:
2799                         bp_.setDefSkip(VSpace(VSpace::MEDSKIP));
2800                         break;
2801                 case 2:
2802                         bp_.setDefSkip(VSpace(VSpace::BIGSKIP));
2803                         break;
2804                 case 3:
2805                         {
2806                         VSpace vs = VSpace(
2807                                 widgetsToLength(textLayoutModule->skipLE,
2808                                 textLayoutModule->skipLengthCO)
2809                                 );
2810                         bp_.setDefSkip(vs);
2811                         break;
2812                         }
2813                 default:
2814                         // this should never happen
2815                         bp_.setDefSkip(VSpace(VSpace::MEDSKIP));
2816                         break;
2817                 }
2818         }
2819
2820         bp_.options =
2821                 fromqstr(latexModule->optionsLE->text());
2822
2823         bp_.use_default_options =
2824                 latexModule->defaultOptionsCB->isChecked();
2825
2826         if (latexModule->childDocGB->isChecked())
2827                 bp_.master =
2828                         fromqstr(latexModule->childDocLE->text());
2829         else
2830                 bp_.master = string();
2831
2832         // Master/Child
2833         bp_.clearIncludedChildren();
2834         if (masterChildModule->includeonlyRB->isChecked()) {
2835                 list<string>::const_iterator it = includeonlys_.begin();
2836                 for (; it != includeonlys_.end() ; ++it) {
2837                         bp_.addIncludedChildren(*it);
2838                 }
2839         }
2840         bp_.maintain_unincluded_children =
2841                 masterChildModule->maintainAuxCB->isChecked();
2842
2843         // Float Placement
2844         bp_.float_placement = floatModule->get();
2845
2846         // Listings
2847         // text should have passed validation
2848         bp_.listings_params =
2849                 InsetListingsParams(fromqstr(listingsModule->listingsED->toPlainText())).params();
2850
2851         // Format
2852         bp_.default_output_format = fromqstr(outputModule->defaultFormatCO->itemData(
2853                 outputModule->defaultFormatCO->currentIndex()).toString());
2854
2855         bool const nontexfonts = fontModule->osFontsCB->isChecked();
2856         bp_.useNonTeXFonts = nontexfonts;
2857
2858         bp_.output_sync = outputModule->outputsyncCB->isChecked();
2859
2860         bp_.output_sync_macro = fromqstr(outputModule->synccustomCB->currentText());
2861
2862         int mathfmt = outputModule->mathoutCB->currentIndex();
2863         if (mathfmt == -1)
2864                 mathfmt = 0;
2865         BufferParams::MathOutput const mo =
2866                 static_cast<BufferParams::MathOutput>(mathfmt);
2867         bp_.html_math_output = mo;
2868         bp_.html_be_strict = outputModule->strictCB->isChecked();
2869         bp_.html_css_as_file = outputModule->cssCB->isChecked();
2870         bp_.html_math_img_scale = outputModule->mathimgSB->value();
2871         bp_.display_pixel_ratio = theGuiApp()->pixelRatio();
2872
2873         bp_.save_transient_properties =
2874                 outputModule->saveTransientPropertiesCB->isChecked();
2875
2876         // fonts
2877         bp_.fonts_roman[nontexfonts] =
2878                 fromqstr(fontModule->fontsRomanCO->
2879                         itemData(fontModule->fontsRomanCO->currentIndex()).toString());
2880         bp_.fonts_roman[!nontexfonts] = fromqstr(fontModule->font_roman);
2881
2882         bp_.fonts_sans[nontexfonts] =
2883                 fromqstr(fontModule->fontsSansCO->
2884                         itemData(fontModule->fontsSansCO->currentIndex()).toString());
2885         bp_.fonts_sans[!nontexfonts] = fromqstr(fontModule->font_sans);
2886
2887         bp_.fonts_typewriter[nontexfonts] =
2888                 fromqstr(fontModule->fontsTypewriterCO->
2889                         itemData(fontModule->fontsTypewriterCO->currentIndex()).toString());
2890         bp_.fonts_typewriter[!nontexfonts] = fromqstr(fontModule->font_typewriter);
2891
2892         bp_.fonts_math[nontexfonts] =
2893                 fromqstr(fontModule->fontsMathCO->
2894                         itemData(fontModule->fontsMathCO->currentIndex()).toString());
2895         bp_.fonts_math[!nontexfonts] = fromqstr(fontModule->font_math);
2896
2897         QString const fontenc =
2898                 fontModule->fontencCO->itemData(fontModule->fontencCO->currentIndex()).toString();
2899         if (fontenc == "custom")
2900                 bp_.fontenc = fromqstr(fontModule->fontencLE->text());
2901         else
2902                 bp_.fontenc = fromqstr(fontenc);
2903
2904         bp_.fonts_cjk =
2905                 fromqstr(fontModule->cjkFontLE->text());
2906
2907         bp_.use_microtype = fontModule->microtypeCB->isChecked();
2908
2909         bp_.fonts_sans_scale[nontexfonts] = fontModule->scaleSansSB->value();
2910         bp_.fonts_sans_scale[!nontexfonts] = fontModule->font_sf_scale;
2911
2912         bp_.fonts_typewriter_scale[nontexfonts] = fontModule->scaleTypewriterSB->value();
2913         bp_.fonts_typewriter_scale[!nontexfonts] = fontModule->font_tt_scale;
2914
2915         bp_.fonts_expert_sc = fontModule->fontScCB->isChecked();
2916
2917         bp_.fonts_old_figures = fontModule->fontOsfCB->isChecked();
2918
2919         if (nontexfonts)
2920                 bp_.fonts_default_family = "default";
2921         else
2922                 bp_.fonts_default_family = GuiDocument::fontfamilies[
2923                         fontModule->fontsDefaultCO->currentIndex()];
2924
2925         if (fontModule->fontsizeCO->currentIndex() == 0)
2926                 bp_.fontsize = "default";
2927         else
2928                 bp_.fontsize =
2929                         fromqstr(fontModule->fontsizeCO->currentText());
2930
2931         // paper
2932         bp_.papersize = PAPER_SIZE(
2933                 pageLayoutModule->papersizeCO->currentIndex());
2934
2935         bp_.paperwidth = widgetsToLength(pageLayoutModule->paperwidthLE,
2936                 pageLayoutModule->paperwidthUnitCO);
2937
2938         bp_.paperheight = widgetsToLength(pageLayoutModule->paperheightLE,
2939                 pageLayoutModule->paperheightUnitCO);
2940
2941         if (pageLayoutModule->facingPagesCB->isChecked())
2942                 bp_.sides = TwoSides;
2943         else
2944                 bp_.sides = OneSide;
2945
2946         if (pageLayoutModule->landscapeRB->isChecked())
2947                 bp_.orientation = ORIENTATION_LANDSCAPE;
2948         else
2949                 bp_.orientation = ORIENTATION_PORTRAIT;
2950
2951         // margins
2952         bp_.use_geometry = !marginsModule->marginCB->isChecked();
2953
2954         Ui::MarginsUi const * m = marginsModule;
2955
2956         bp_.leftmargin = widgetsToLength(m->innerLE, m->innerUnit);
2957         bp_.topmargin = widgetsToLength(m->topLE, m->topUnit);
2958         bp_.rightmargin = widgetsToLength(m->outerLE, m->outerUnit);
2959         bp_.bottommargin = widgetsToLength(m->bottomLE, m->bottomUnit);
2960         bp_.headheight = widgetsToLength(m->headheightLE, m->headheightUnit);
2961         bp_.headsep = widgetsToLength(m->headsepLE, m->headsepUnit);
2962         bp_.footskip = widgetsToLength(m->footskipLE, m->footskipUnit);
2963         bp_.columnsep = widgetsToLength(m->columnsepLE, m->columnsepUnit);
2964
2965         // branches
2966         branchesModule->apply(bp_);
2967
2968         // PDF support
2969         PDFOptions & pdf = bp_.pdfoptions();
2970         pdf.use_hyperref = pdfSupportModule->use_hyperrefGB->isChecked();
2971         pdf.title = fromqstr(pdfSupportModule->titleLE->text());
2972         pdf.author = fromqstr(pdfSupportModule->authorLE->text());
2973         pdf.subject = fromqstr(pdfSupportModule->subjectLE->text());
2974         pdf.keywords = fromqstr(pdfSupportModule->keywordsLE->text());
2975
2976         pdf.bookmarks = pdfSupportModule->bookmarksGB->isChecked();
2977         pdf.bookmarksnumbered = pdfSupportModule->bookmarksnumberedCB->isChecked();
2978         pdf.bookmarksopen = pdfSupportModule->bookmarksopenGB->isChecked();
2979         pdf.bookmarksopenlevel = pdfSupportModule->bookmarksopenlevelSB->value();
2980
2981         pdf.breaklinks = pdfSupportModule->breaklinksCB->isChecked();
2982         pdf.pdfborder = pdfSupportModule->pdfborderCB->isChecked();
2983         pdf.pdfusetitle = pdfSupportModule->pdfusetitleCB->isChecked();
2984         pdf.colorlinks = pdfSupportModule->colorlinksCB->isChecked();
2985         pdf.backref =
2986                 backref_opts[pdfSupportModule->backrefCO->currentIndex()];
2987         if (pdfSupportModule->fullscreenCB->isChecked())
2988                 pdf.pagemode = pdf.pagemode_fullscreen;
2989         else
2990                 pdf.pagemode.clear();
2991         pdf.quoted_options = pdf.quoted_options_check(
2992                                 fromqstr(pdfSupportModule->optionsLE->text()));
2993
2994         // reset tracker
2995         nonModuleChanged_ = false;
2996 }
2997
2998
2999 void GuiDocument::paramsToDialog()
3000 {
3001         // set the default unit
3002         Length::UNIT const default_unit = Length::defaultUnit();
3003
3004         // preamble
3005         preambleModule->update(bp_, id());
3006         localLayout->update(bp_, id());
3007
3008         // date
3009         latexModule->suppressDateCB->setChecked(bp_.suppress_date);
3010         latexModule->refstyleCB->setChecked(bp_.use_refstyle);
3011
3012         // biblio
3013         string const cite_engine = bp_.citeEngine().list().front();
3014
3015         biblioModule->citeDefaultRB->setChecked(
3016                 cite_engine == "basic");
3017
3018         biblioModule->citeJurabibRB->setChecked(
3019                 cite_engine == "jurabib");
3020
3021         biblioModule->citeNatbibRB->setChecked(
3022                 cite_engine == "natbib");
3023
3024         biblioModule->citeStyleCO->setCurrentIndex(
3025                 bp_.citeEngineType() & ENGINE_TYPE_NUMERICAL);
3026
3027         updateEngineType(documentClass().opt_enginetype(),
3028                 bp_.citeEngineType());
3029
3030         biblioModule->bibtopicCB->setChecked(
3031                 bp_.use_bibtopic);
3032
3033         biblioModule->bibtexStyleLE->setText(toqstr(bp_.biblio_style));
3034
3035         string command;
3036         string options =
3037                 split(bp_.bibtex_command, command, ' ');
3038
3039         int const bpos = biblioModule->bibtexCO->findData(toqstr(command));
3040         if (bpos != -1) {
3041                 biblioModule->bibtexCO->setCurrentIndex(bpos);
3042                 biblioModule->bibtexOptionsLE->setText(toqstr(options).trimmed());
3043         } else {
3044                 // We reset to default if we do not know the specified compiler
3045                 // This is for security reasons
3046                 biblioModule->bibtexCO->setCurrentIndex(
3047                         biblioModule->bibtexCO->findData(toqstr("default")));
3048                 biblioModule->bibtexOptionsLE->clear();
3049         }
3050         biblioModule->bibtexOptionsLE->setEnabled(
3051                 biblioModule->bibtexCO->currentIndex() != 0);
3052
3053         biblioChanged_ = false;
3054
3055         // indices
3056         // We may be called when there is no Buffer, e.g., when 
3057         // the last view has just been closed.
3058         bool const isReadOnly = isBufferAvailable() ? buffer().isReadonly() : false;
3059         indicesModule->update(bp_, isReadOnly);
3060
3061         // language & quotes
3062         int const pos = langModule->languageCO->findData(toqstr(
3063                 bp_.language->lang()));
3064         langModule->languageCO->setCurrentIndex(pos);
3065
3066         langModule->quoteStyleCO->setCurrentIndex(
3067                 bp_.quotes_language);
3068
3069         bool default_enc = true;
3070         if (bp_.inputenc != "auto") {
3071                 default_enc = false;
3072                 if (bp_.inputenc == "default") {
3073                         langModule->encodingCO->setCurrentIndex(0);
3074                 } else {
3075                         string enc_gui;
3076                         Encodings::const_iterator it = encodings.begin();
3077                         Encodings::const_iterator const end = encodings.end();
3078                         for (; it != end; ++it) {
3079                                 if (it->name() == bp_.inputenc &&
3080                                     !it->unsafe()) {
3081                                         enc_gui = it->guiName();
3082                                         break;
3083                                 }
3084                         }
3085                         int const i = langModule->encodingCO->findText(
3086                                         qt_(enc_gui));
3087                         if (i >= 0)
3088                                 langModule->encodingCO->setCurrentIndex(i);
3089                         else
3090                                 // unknown encoding. Set to default.
3091                                 default_enc = true;
3092                 }
3093         }
3094         langModule->defaultencodingRB->setChecked(default_enc);
3095         langModule->otherencodingRB->setChecked(!default_enc);
3096
3097         int const p = langModule->languagePackageCO->findData(toqstr(bp_.lang_package));
3098         if (p == -1) {
3099                 langModule->languagePackageCO->setCurrentIndex(
3100                           langModule->languagePackageCO->findData("custom"));
3101                 langModule->languagePackageLE->setText(toqstr(bp_.lang_package));
3102         } else {
3103                 langModule->languagePackageCO->setCurrentIndex(p);
3104                 langModule->languagePackageLE->clear();
3105         }
3106
3107         //color
3108         if (bp_.isfontcolor) {
3109                 colorModule->fontColorPB->setStyleSheet(
3110                         colorButtonStyleSheet(rgb2qcolor(bp_.fontcolor)));
3111         }
3112         set_fontcolor = bp_.fontcolor;
3113         is_fontcolor = bp_.isfontcolor;
3114
3115         colorModule->noteFontColorPB->setStyleSheet(
3116                 colorButtonStyleSheet(rgb2qcolor(bp_.notefontcolor)));
3117         set_notefontcolor = bp_.notefontcolor;
3118
3119         if (bp_.isbackgroundcolor) {
3120                 colorModule->backgroundPB->setStyleSheet(
3121                         colorButtonStyleSheet(rgb2qcolor(bp_.backgroundcolor)));
3122         }
3123         set_backgroundcolor = bp_.backgroundcolor;
3124         is_backgroundcolor = bp_.isbackgroundcolor;
3125
3126         colorModule->boxBackgroundPB->setStyleSheet(
3127                 colorButtonStyleSheet(rgb2qcolor(bp_.boxbgcolor)));
3128         set_boxbgcolor = bp_.boxbgcolor;
3129
3130         // numbering
3131         int const min_toclevel = documentClass().min_toclevel();
3132         int const max_toclevel = documentClass().max_toclevel();
3133         if (documentClass().hasTocLevels()) {
3134                 numberingModule->setEnabled(true);
3135                 numberingModule->depthSL->setMinimum(min_toclevel - 1);
3136                 numberingModule->depthSL->setMaximum(max_toclevel);
3137                 numberingModule->depthSL->setValue(bp_.secnumdepth);
3138                 numberingModule->tocSL->setMaximum(min_toclevel - 1);
3139                 numberingModule->tocSL->setMaximum(max_toclevel);
3140                 numberingModule->tocSL->setValue(bp_.tocdepth);
3141                 updateNumbering();
3142         } else {
3143                 numberingModule->setEnabled(false);
3144                 numberingModule->tocTW->clear();
3145         }
3146
3147         // bullets
3148         bulletsModule->setBullet(0, bp_.user_defined_bullet(0));
3149         bulletsModule->setBullet(1, bp_.user_defined_bullet(1));
3150         bulletsModule->setBullet(2, bp_.user_defined_bullet(2));
3151         bulletsModule->setBullet(3, bp_.user_defined_bullet(3));
3152         bulletsModule->init();
3153
3154         // packages
3155         int nitem = findToken(tex_graphics, bp_.graphics_driver);
3156         if (nitem >= 0)
3157                 latexModule->psdriverCO->setCurrentIndex(nitem);
3158         updateModuleInfo();
3159
3160         map<string, string> const & packages = BufferParams::auto_packages();
3161         for (map<string, string>::const_iterator it = packages.begin();
3162              it != packages.end(); ++it) {
3163                 QTableWidgetItem * item = mathsModule->packagesTW->findItems(toqstr(it->first), Qt::MatchExactly)[0];
3164                 if (!item)
3165                         continue;
3166                 int row = mathsModule->packagesTW->row(item);
3167                 switch (bp_.use_package(it->first)) {
3168                         case BufferParams::package_off: {
3169                                 QRadioButton * rb = (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 3);
3170                                 rb->setChecked(true);
3171                                 break;
3172                         }
3173                         case BufferParams::package_on: {
3174                                 QRadioButton * rb = (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 2);
3175                                 rb->setChecked(true);
3176                                 break;
3177                         }
3178                         case BufferParams::package_auto: {
3179                                 QRadioButton * rb = (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 1);
3180                                 rb->setChecked(true);
3181                                 break;
3182                         }
3183                 }
3184         }
3185
3186         switch (bp_.spacing().getSpace()) {
3187                 case Spacing::Other: nitem = 3; break;
3188                 case Spacing::Double: nitem = 2; break;
3189                 case Spacing::Onehalf: nitem = 1; break;
3190                 case Spacing::Default: case Spacing::Single: nitem = 0; break;
3191         }
3192
3193         // text layout
3194         string const & layoutID = bp_.baseClassID();
3195         setLayoutComboByIDString(layoutID);
3196
3197         updatePagestyle(documentClass().opt_pagestyle(),
3198                                  bp_.pagestyle);
3199
3200         textLayoutModule->lspacingCO->setCurrentIndex(nitem);
3201         if (bp_.spacing().getSpace() == Spacing::Other) {
3202                 doubleToWidget(textLayoutModule->lspacingLE,
3203                         bp_.spacing().getValueAsString());
3204         }
3205         setLSpacing(nitem);
3206
3207         if (bp_.paragraph_separation == BufferParams::ParagraphIndentSeparation) {
3208                 textLayoutModule->indentRB->setChecked(true);
3209                 string indentation = bp_.getIndentation().asLyXCommand();
3210                 int indent = 0;
3211                 if (indentation != "default") {
3212                         lengthToWidgets(textLayoutModule->indentLE,
3213                         textLayoutModule->indentLengthCO,
3214                         indentation, default_unit);
3215                         indent = 1;
3216                 }
3217                 textLayoutModule->indentCO->setCurrentIndex(indent);
3218                 setIndent(indent);
3219         } else {
3220                 textLayoutModule->skipRB->setChecked(true);
3221                 int skip = 0;
3222                 switch (bp_.getDefSkip().kind()) {
3223                 case VSpace::SMALLSKIP:
3224                         skip = 0;
3225                         break;
3226                 case VSpace::MEDSKIP:
3227                         skip = 1;
3228                         break;
3229                 case VSpace::BIGSKIP:
3230                         skip = 2;
3231                         break;
3232                 case VSpace::LENGTH:
3233                         {
3234                         skip = 3;
3235                         string const length = bp_.getDefSkip().asLyXCommand();
3236                         lengthToWidgets(textLayoutModule->skipLE,
3237                                 textLayoutModule->skipLengthCO,
3238                                 length, default_unit);
3239                         break;
3240                         }
3241                 default:
3242                         skip = 0;
3243                         break;
3244                 }
3245                 textLayoutModule->skipCO->setCurrentIndex(skip);
3246                 setSkip(skip);
3247         }
3248
3249         textLayoutModule->twoColumnCB->setChecked(
3250                 bp_.columns == 2);
3251         textLayoutModule->justCB->setChecked(bp_.justification);
3252
3253         if (!bp_.options.empty()) {
3254                 latexModule->optionsLE->setText(
3255                         toqstr(bp_.options));
3256         } else {
3257                 latexModule->optionsLE->setText(QString());
3258         }
3259
3260         // latex
3261         latexModule->defaultOptionsCB->setChecked(
3262                         bp_.use_default_options);
3263         updateSelectedModules();
3264         selectionManager->updateProvidedModules(
3265                         bp_.baseClass()->providedModules());
3266         selectionManager->updateExcludedModules(
3267                         bp_.baseClass()->excludedModules());
3268
3269         if (!documentClass().options().empty()) {
3270                 latexModule->defaultOptionsLE->setText(
3271                         toqstr(documentClass().options()));
3272         } else {
3273                 latexModule->defaultOptionsLE->setText(
3274                         toqstr(_("[No options predefined]")));
3275         }
3276
3277         latexModule->defaultOptionsLE->setEnabled(
3278                 bp_.use_default_options
3279                 && !documentClass().options().empty());
3280
3281         latexModule->defaultOptionsCB->setEnabled(
3282                 !documentClass().options().empty());
3283
3284         if (!bp_.master.empty()) {
3285                 latexModule->childDocGB->setChecked(true);
3286                 latexModule->childDocLE->setText(
3287                         toqstr(bp_.master));
3288         } else {
3289                 latexModule->childDocLE->setText(QString());
3290                 latexModule->childDocGB->setChecked(false);
3291         }
3292
3293         // Master/Child
3294         if (!bufferview() || !buffer().hasChildren()) {
3295                 masterChildModule->childrenTW->clear();
3296                 includeonlys_.clear();
3297                 docPS->showPanel("Child Documents", false);
3298                 if (docPS->isCurrentPanel("Child Documents"))
3299                         docPS->setCurrentPanel("Document Class");
3300         } else {
3301                 docPS->showPanel("Child Documents", true);
3302                 masterChildModule->setEnabled(true);
3303                 includeonlys_ = bp_.getIncludedChildren();
3304                 updateIncludeonlys();
3305         }
3306         masterChildModule->maintainAuxCB->setChecked(
3307                 bp_.maintain_unincluded_children);
3308
3309         // Float Settings
3310         floatModule->set(bp_.float_placement);
3311
3312         // ListingsSettings
3313         // break listings_params to multiple lines
3314         string lstparams =
3315                 InsetListingsParams(bp_.listings_params).separatedParams();
3316         listingsModule->listingsED->setPlainText(toqstr(lstparams));
3317
3318         // Fonts
3319         // some languages only work with polyglossia/XeTeX
3320         Language const * lang = lyx::languages.getLanguage(
3321                 fromqstr(langModule->languageCO->itemData(
3322                         langModule->languageCO->currentIndex()).toString()));
3323         bool const need_fontspec =
3324                 lang->babel().empty() && !lang->polyglossia().empty();
3325         bool const os_fonts_available =
3326                 bp_.baseClass()->outputType() == lyx::LATEX
3327                 && LaTeXFeatures::isAvailable("fontspec");
3328         fontModule->osFontsCB->setEnabled(os_fonts_available && !need_fontspec);
3329         fontModule->osFontsCB->setChecked(
3330                 (os_fonts_available && bp_.useNonTeXFonts) || need_fontspec);
3331         updateFontsize(documentClass().opt_fontsize(),
3332                         bp_.fontsize);
3333
3334         QString font = toqstr(bp_.fontsRoman());
3335         int rpos = fontModule->fontsRomanCO->findData(font);
3336         if (rpos == -1) {
3337                 rpos = fontModule->fontsRomanCO->count();
3338                 fontModule->fontsRomanCO->addItem(font + qt_(" (not installed)"), font);
3339         }
3340         fontModule->fontsRomanCO->setCurrentIndex(rpos);
3341         fontModule->font_roman = toqstr(bp_.fonts_roman[!bp_.useNonTeXFonts]);
3342
3343         font = toqstr(bp_.fontsSans());
3344         int spos = fontModule->fontsSansCO->findData(font);
3345         if (spos == -1) {
3346                 spos = fontModule->fontsSansCO->count();
3347                 fontModule->fontsSansCO->addItem(font + qt_(" (not installed)"), font);
3348         }
3349         fontModule->fontsSansCO->setCurrentIndex(spos);
3350         fontModule->font_sans = toqstr(bp_.fonts_sans[!bp_.useNonTeXFonts]);
3351
3352         font = toqstr(bp_.fontsTypewriter());
3353         int tpos = fontModule->fontsTypewriterCO->findData(font);
3354         if (tpos == -1) {
3355                 tpos = fontModule->fontsTypewriterCO->count();
3356                 fontModule->fontsTypewriterCO->addItem(font + qt_(" (not installed)"), font);
3357         }
3358         fontModule->fontsTypewriterCO->setCurrentIndex(tpos);
3359         fontModule->font_typewriter = toqstr(bp_.fonts_typewriter[!bp_.useNonTeXFonts]);
3360
3361         font = toqstr(bp_.fontsMath());
3362         int mpos = fontModule->fontsMathCO->findData(font);
3363         if (mpos == -1) {
3364                 mpos = fontModule->fontsMathCO->count();
3365                 fontModule->fontsMathCO->addItem(font + qt_(" (not installed)"), font);
3366         }
3367         fontModule->fontsMathCO->setCurrentIndex(mpos);
3368         fontModule->font_math = toqstr(bp_.fonts_math[!bp_.useNonTeXFonts]);
3369
3370         if (bp_.useNonTeXFonts && os_fonts_available) {
3371                 fontModule->fontencLA->setEnabled(false);
3372                 fontModule->fontencCO->setEnabled(false);
3373                 fontModule->fontencLE->setEnabled(false);
3374         } else {
3375                 fontModule->fontencLA->setEnabled(true);
3376                 fontModule->fontencCO->setEnabled(true);
3377                 fontModule->fontencLE->setEnabled(true);
3378                 romanChanged(rpos);
3379                 sansChanged(spos);
3380                 ttChanged(tpos);
3381         }
3382
3383         if (!bp_.fonts_cjk.empty())
3384                 fontModule->cjkFontLE->setText(
3385                         toqstr(bp_.fonts_cjk));
3386         else
3387                 fontModule->cjkFontLE->setText(QString());
3388         
3389         fontModule->microtypeCB->setChecked(bp_.use_microtype);
3390
3391         fontModule->fontScCB->setChecked(bp_.fonts_expert_sc);
3392         fontModule->fontOsfCB->setChecked(bp_.fonts_old_figures);
3393         fontModule->scaleSansSB->setValue(bp_.fontsSansScale());
3394         fontModule->font_sf_scale = bp_.fonts_sans_scale[!bp_.useNonTeXFonts];
3395         fontModule->scaleTypewriterSB->setValue(bp_.fontsTypewriterScale());
3396         fontModule->font_tt_scale = bp_.fonts_typewriter_scale[!bp_.useNonTeXFonts];
3397
3398         int nn = findToken(GuiDocument::fontfamilies, bp_.fonts_default_family);
3399         if (nn >= 0)
3400                 fontModule->fontsDefaultCO->setCurrentIndex(nn);
3401
3402         if (bp_.fontenc == "global" || bp_.fontenc == "default") {
3403                 fontModule->fontencCO->setCurrentIndex(
3404                         fontModule->fontencCO->findData(toqstr(bp_.fontenc)));
3405                 fontModule->fontencLE->setEnabled(false);
3406         } else {
3407                 fontModule->fontencCO->setCurrentIndex(1);
3408                 fontModule->fontencLE->setText(toqstr(bp_.fontenc));
3409         }
3410
3411         // Format
3412         // This must be set _after_ fonts since updateDefaultFormat()
3413         // checks osFontsCB settings.
3414         // update combobox with formats
3415         updateDefaultFormat();
3416         int index = outputModule->defaultFormatCO->findData(toqstr(
3417                 bp_.default_output_format));
3418         // set to default if format is not found
3419         if (index == -1)
3420                 index = 0;
3421         outputModule->defaultFormatCO->setCurrentIndex(index);
3422
3423         outputModule->outputsyncCB->setChecked(bp_.output_sync);
3424         outputModule->synccustomCB->setEditText(toqstr(bp_.output_sync_macro));
3425
3426         outputModule->mathimgSB->setValue(bp_.html_math_img_scale);
3427         outputModule->mathoutCB->setCurrentIndex(bp_.html_math_output);
3428         outputModule->strictCB->setChecked(bp_.html_be_strict);
3429         outputModule->cssCB->setChecked(bp_.html_css_as_file);
3430
3431         outputModule->saveTransientPropertiesCB
3432                 ->setChecked(bp_.save_transient_properties);
3433
3434         // paper
3435         bool const extern_geometry =
3436                 documentClass().provides("geometry");
3437         int const psize = bp_.papersize;
3438         pageLayoutModule->papersizeCO->setCurrentIndex(psize);
3439         setCustomPapersize(!extern_geometry && psize == 1);
3440         pageLayoutModule->papersizeCO->setEnabled(!extern_geometry);
3441
3442         bool const landscape =
3443                 bp_.orientation == ORIENTATION_LANDSCAPE;
3444         pageLayoutModule->landscapeRB->setChecked(landscape);
3445         pageLayoutModule->portraitRB->setChecked(!landscape);
3446         pageLayoutModule->landscapeRB->setEnabled(!extern_geometry);
3447         pageLayoutModule->portraitRB->setEnabled(!extern_geometry);
3448
3449         pageLayoutModule->facingPagesCB->setChecked(
3450                 bp_.sides == TwoSides);
3451
3452         lengthToWidgets(pageLayoutModule->paperwidthLE,
3453                 pageLayoutModule->paperwidthUnitCO, bp_.paperwidth, default_unit);
3454         lengthToWidgets(pageLayoutModule->paperheightLE,
3455                 pageLayoutModule->paperheightUnitCO, bp_.paperheight, default_unit);
3456
3457         // margins
3458         Ui::MarginsUi * m = marginsModule;
3459
3460         setMargins();
3461
3462         lengthToWidgets(m->topLE, m->topUnit,
3463                 bp_.topmargin, default_unit);
3464
3465         lengthToWidgets(m->bottomLE, m->bottomUnit,
3466                 bp_.bottommargin, default_unit);
3467
3468         lengthToWidgets(m->innerLE, m->innerUnit,
3469                 bp_.leftmargin, default_unit);
3470
3471         lengthToWidgets(m->outerLE, m->outerUnit,
3472                 bp_.rightmargin, default_unit);
3473
3474         lengthToWidgets(m->headheightLE, m->headheightUnit,
3475                 bp_.headheight, default_unit);
3476
3477         lengthToWidgets(m->headsepLE, m->headsepUnit,
3478                 bp_.headsep, default_unit);
3479
3480         lengthToWidgets(m->footskipLE, m->footskipUnit,
3481                 bp_.footskip, default_unit);
3482
3483         lengthToWidgets(m->columnsepLE, m->columnsepUnit,
3484                 bp_.columnsep, default_unit);
3485
3486         // branches
3487         updateUnknownBranches();
3488         branchesModule->update(bp_);
3489
3490         // PDF support
3491         PDFOptions const & pdf = bp_.pdfoptions();
3492         pdfSupportModule->use_hyperrefGB->setChecked(pdf.use_hyperref);
3493         if (bp_.documentClass().provides("hyperref"))
3494                 pdfSupportModule->use_hyperrefGB->setTitle(qt_("C&ustomize Hyperref Options"));
3495         else
3496                 pdfSupportModule->use_hyperrefGB->setTitle(qt_("&Use Hyperref Support"));
3497         pdfSupportModule->titleLE->setText(toqstr(pdf.title));
3498         pdfSupportModule->authorLE->setText(toqstr(pdf.author));
3499         pdfSupportModule->subjectLE->setText(toqstr(pdf.subject));
3500         pdfSupportModule->keywordsLE->setText(toqstr(pdf.keywords));
3501
3502         pdfSupportModule->bookmarksGB->setChecked(pdf.bookmarks);
3503         pdfSupportModule->bookmarksnumberedCB->setChecked(pdf.bookmarksnumbered);
3504         pdfSupportModule->bookmarksopenGB->setChecked(pdf.bookmarksopen);
3505
3506         pdfSupportModule->bookmarksopenlevelSB->setValue(pdf.bookmarksopenlevel);
3507
3508         pdfSupportModule->breaklinksCB->setChecked(pdf.breaklinks);
3509         pdfSupportModule->pdfborderCB->setChecked(pdf.pdfborder);
3510         pdfSupportModule->pdfusetitleCB->setChecked(pdf.pdfusetitle);
3511         pdfSupportModule->colorlinksCB->setChecked(pdf.colorlinks);
3512
3513         nn = findToken(backref_opts, pdf.backref);
3514         if (nn >= 0)
3515                 pdfSupportModule->backrefCO->setCurrentIndex(nn);
3516
3517         pdfSupportModule->fullscreenCB->setChecked
3518                 (pdf.pagemode == pdf.pagemode_fullscreen);
3519
3520         pdfSupportModule->optionsLE->setText(
3521                 toqstr(pdf.quoted_options));
3522
3523         // Make sure that the bc is in the INITIAL state
3524         if (bc().policy().buttonStatus(ButtonPolicy::RESTORE))
3525                 bc().restore();
3526
3527         // clear changed branches cache
3528         changedBranches_.clear();
3529
3530         // reset tracker
3531         nonModuleChanged_ = false;
3532 }
3533
3534
3535 void GuiDocument::saveDocDefault()
3536 {
3537         // we have to apply the params first
3538         applyView();
3539         saveAsDefault();
3540 }
3541
3542
3543 void GuiDocument::updateAvailableModules()
3544 {
3545         modules_av_model_.clear();
3546         list<modInfoStruct> modInfoList = getModuleInfo();
3547         // Sort names according to the locale
3548         modInfoList.sort([](modInfoStruct const & a, modInfoStruct const & b) {
3549                         return 0 < b.name.localeAwareCompare(a.name);
3550                 });
3551         int i = 0;
3552         for (modInfoStruct const & m : modInfoList) {
3553                 modules_av_model_.insertRow(i, m.name, m.id, m.description);
3554                 ++i;
3555         }
3556 }
3557
3558
3559 void GuiDocument::updateSelectedModules()
3560 {
3561         modules_sel_model_.clear();
3562         list<modInfoStruct> const selModList = getSelectedModules();
3563         int i = 0;
3564         for (modInfoStruct const & m : selModList) {
3565                 modules_sel_model_.insertRow(i, m.name, m.id, m.description);
3566                 ++i;
3567         }
3568 }
3569
3570
3571 void GuiDocument::updateIncludeonlys()
3572 {
3573         masterChildModule->childrenTW->clear();
3574         QString const no = qt_("No");
3575         QString const yes = qt_("Yes");
3576
3577         if (includeonlys_.empty()) {
3578                 masterChildModule->includeallRB->setChecked(true);
3579                 masterChildModule->childrenTW->setEnabled(false);
3580                 masterChildModule->maintainAuxCB->setEnabled(false);
3581         } else {
3582                 masterChildModule->includeonlyRB->setChecked(true);
3583                 masterChildModule->childrenTW->setEnabled(true);
3584                 masterChildModule->maintainAuxCB->setEnabled(true);
3585         }
3586         ListOfBuffers children = buffer().getChildren();
3587         ListOfBuffers::const_iterator it  = children.begin();
3588         ListOfBuffers::const_iterator end = children.end();
3589         bool has_unincluded = false;
3590         bool all_unincluded = true;
3591         for (; it != end; ++it) {
3592                 QTreeWidgetItem * item = new QTreeWidgetItem(masterChildModule->childrenTW);
3593                 // FIXME Unicode
3594                 string const name =
3595                         to_utf8(makeRelPath(from_utf8((*it)->fileName().absFileName()),
3596                                                         from_utf8(buffer().filePath())));
3597                 item->setText(0, toqstr(name));
3598                 item->setText(1, isChildIncluded(name) ? yes : no);
3599                 if (!isChildIncluded(name))
3600                         has_unincluded = true;
3601                 else
3602                         all_unincluded = false;
3603         }
3604         // Both if all childs are included and if none is included
3605         // is equal to "include all" (i.e., ommit \includeonly).
3606         // Thus, reset the GUI.
3607         if (!has_unincluded || all_unincluded) {
3608                 masterChildModule->includeallRB->setChecked(true);
3609                 masterChildModule->childrenTW->setEnabled(false);
3610                 includeonlys_.clear();
3611         }
3612         // If all are included, we need to update again.
3613         if (!has_unincluded)
3614                 updateIncludeonlys();
3615 }
3616
3617
3618 void GuiDocument::updateContents()
3619 {
3620         // Nothing to do here as the document settings is not cursor dependant.
3621         return;
3622 }
3623
3624
3625 void GuiDocument::useClassDefaults()
3626 {
3627         if (applyPB->isEnabled()) {
3628                 int const ret = Alert::prompt(_("Unapplied changes"),
3629                                 _("Some changes in the dialog were not yet applied.\n"
3630                                   "If you do not apply now, they will be lost after this action."),
3631                                 1, 1, _("&Apply"), _("&Dismiss"));
3632                 if (ret == 0)
3633                         applyView();
3634         }
3635
3636         int idx = latexModule->classCO->currentIndex();
3637         string const classname = fromqstr(latexModule->classCO->getData(idx));
3638         if (!bp_.setBaseClass(classname)) {
3639                 Alert::error(_("Error"), _("Unable to set document class."));
3640                 return;
3641         }
3642         bp_.useClassDefaults();
3643         paramsToDialog();
3644 }
3645
3646
3647 void GuiDocument::setLayoutComboByIDString(string const & idString)
3648 {
3649         if (!latexModule->classCO->set(toqstr(idString)))
3650                 Alert::warning(_("Can't set layout!"),
3651                         bformat(_("Unable to set layout for ID: %1$s"), from_utf8(idString)));
3652 }
3653
3654
3655 bool GuiDocument::isValid()
3656 {
3657         return
3658                 validateListingsParameters().isEmpty() &&
3659                 localLayout->isValid() &&
3660                 (
3661                         // if we're asking for skips between paragraphs
3662                         !textLayoutModule->skipRB->isChecked() ||
3663                         // then either we haven't chosen custom
3664                         textLayoutModule->skipCO->currentIndex() != 3 ||
3665                         // or else a length has been given
3666                         !textLayoutModule->skipLE->text().isEmpty()
3667                 ) &&
3668                 (
3669                         // if we're asking for indentation
3670                         !textLayoutModule->indentRB->isChecked() ||
3671                         // then either we haven't chosen custom
3672                         textLayoutModule->indentCO->currentIndex() != 1 ||
3673                         // or else a length has been given
3674                         !textLayoutModule->indentLE->text().isEmpty()
3675                 );
3676 }
3677
3678
3679 char const * const GuiDocument::fontfamilies[5] = {
3680         "default", "rmdefault", "sfdefault", "ttdefault", ""
3681 };
3682
3683
3684 char const * GuiDocument::fontfamilies_gui[5] = {
3685         N_("Default"), N_("Roman"), N_("Sans Serif"), N_("Typewriter"), ""
3686 };
3687
3688
3689 bool GuiDocument::initialiseParams(string const &)
3690 {
3691         BufferView const * view = bufferview();
3692         if (!view) {
3693                 bp_ = BufferParams();
3694                 paramsToDialog();
3695                 return true;
3696         }
3697         bp_ = view->buffer().params();
3698         loadModuleInfo();
3699         updateAvailableModules();
3700         //FIXME It'd be nice to make sure here that the selected
3701         //modules are consistent: That required modules are actually
3702         //selected, and that we don't have conflicts. If so, we could
3703         //at least pop up a warning.
3704         paramsToDialog();
3705         return true;
3706 }
3707
3708
3709 void GuiDocument::clearParams()
3710 {
3711         bp_ = BufferParams();
3712 }
3713
3714
3715 BufferId GuiDocument::id() const
3716 {
3717         BufferView const * const view = bufferview();
3718         return view? &view->buffer() : 0;
3719 }
3720
3721
3722 list<GuiDocument::modInfoStruct> const & GuiDocument::getModuleInfo()
3723 {
3724         return moduleNames_;
3725 }
3726
3727
3728 list<GuiDocument::modInfoStruct> const
3729 GuiDocument::makeModuleInfo(LayoutModuleList const & mods)
3730 {
3731         list<modInfoStruct> mInfo;
3732         for (string const & name : mods) {
3733                 modInfoStruct m;
3734                 LyXModule const * const mod = theModuleList[name];
3735                 if (mod)
3736                         m = modInfo(*mod);
3737                 else {
3738                         m.id = name;
3739                         m.name = toqstr(name + " (") + qt_("Not Found") + toqstr(")");
3740                 }
3741                 mInfo.push_back(m);
3742         }
3743         return mInfo;
3744 }
3745
3746
3747 list<GuiDocument::modInfoStruct> const GuiDocument::getSelectedModules()
3748 {
3749         return makeModuleInfo(params().getModules());
3750 }
3751
3752
3753 list<GuiDocument::modInfoStruct> const GuiDocument::getProvidedModules()
3754 {
3755         return makeModuleInfo(params().baseClass()->providedModules());
3756 }
3757
3758
3759 DocumentClass const & GuiDocument::documentClass() const
3760 {
3761         return bp_.documentClass();
3762 }
3763
3764
3765 static void dispatch_bufferparams(Dialog const & dialog,
3766         BufferParams const & bp, FuncCode lfun, Buffer const * buf)
3767 {
3768         ostringstream ss;
3769         ss << "\\begin_header\n";
3770         bp.writeFile(ss, buf);
3771         ss << "\\end_header\n";
3772         dialog.dispatch(FuncRequest(lfun, ss.str()));
3773 }
3774
3775
3776 void GuiDocument::dispatchParams()
3777 {
3778         // We need a non-const buffer object.
3779         Buffer & buf = const_cast<BufferView *>(bufferview())->buffer();
3780         // There may be several undo records; group them (bug #8998)
3781         buf.undo().beginUndoGroup();
3782
3783         // This must come first so that a language change is correctly noticed
3784         setLanguage();
3785
3786         // Apply the BufferParams. Note that this will set the base class
3787         // and then update the buffer's layout.
3788         dispatch_bufferparams(*this, params(), LFUN_BUFFER_PARAMS_APPLY, &buffer());
3789
3790         if (!params().master.empty()) {
3791                 FileName const master_file = support::makeAbsPath(params().master,
3792                            support::onlyPath(buffer().absFileName()));
3793                 if (isLyXFileName(master_file.absFileName())) {
3794                         Buffer * master = checkAndLoadLyXFile(master_file);
3795                         if (master) {
3796                                 if (master->isChild(const_cast<Buffer *>(&buffer())))
3797                                         const_cast<Buffer &>(buffer()).setParent(master);
3798                                 else
3799                                         Alert::warning(_("Assigned master does not include this file"),
3800                                                 bformat(_("You must include this file in the document\n"
3801                                                           "'%1$s' in order to use the master document\n"
3802                                                           "feature."), from_utf8(params().master)));
3803                         } else
3804                                 Alert::warning(_("Could not load master"),
3805                                                 bformat(_("The master document '%1$s'\n"
3806                                                            "could not be loaded."),
3807                                                            from_utf8(params().master)));
3808                 }
3809         }
3810
3811         // Generate the colours requested by each new branch.
3812         BranchList & branchlist = params().branchlist();
3813         if (!branchlist.empty()) {
3814                 BranchList::const_iterator it = branchlist.begin();
3815                 BranchList::const_iterator const end = branchlist.end();
3816                 for (; it != end; ++it) {
3817                         docstring const & current_branch = it->branch();
3818                         Branch const * branch = branchlist.find(current_branch);
3819                         string const x11hexname = X11hexname(branch->color());
3820                         // display the new color
3821                         docstring const str = current_branch + ' ' + from_ascii(x11hexname);
3822                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
3823                 }
3824
3825                 // Open insets of selected branches, close deselected ones
3826                 dispatch(FuncRequest(LFUN_INSET_FORALL,
3827                         "Branch inset-toggle assign"));
3828         }
3829         // rename branches in the document
3830         executeBranchRenaming();
3831         // and clear changed branches cache
3832         changedBranches_.clear();
3833
3834         // Generate the colours requested by indices.
3835         IndicesList & indiceslist = params().indiceslist();
3836         if (!indiceslist.empty()) {
3837                 IndicesList::const_iterator it = indiceslist.begin();
3838                 IndicesList::const_iterator const end = indiceslist.end();
3839                 for (; it != end; ++it) {
3840                         docstring const & current_index = it->shortcut();
3841                         Index const * index = indiceslist.findShortcut(current_index);
3842                         string const x11hexname = X11hexname(index->color());
3843                         // display the new color
3844                         docstring const str = current_index + ' ' + from_ascii(x11hexname);
3845                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
3846                 }
3847         }
3848         // FIXME LFUN
3849         // If we used an LFUN, we would not need these two lines:
3850         BufferView * bv = const_cast<BufferView *>(bufferview());
3851         bv->processUpdateFlags(Update::Force | Update::FitCursor);
3852
3853         // Don't forget to close the group. Note that it is important
3854         // to check that there is no early return in the method.
3855         buf.undo().endUndoGroup();
3856 }
3857
3858
3859 void GuiDocument::setLanguage() const
3860 {
3861         Language const * const newL = bp_.language;
3862         if (buffer().params().language == newL)
3863                 return;
3864
3865         string const & lang_name = newL->lang();
3866         dispatch(FuncRequest(LFUN_BUFFER_LANGUAGE, lang_name));
3867 }
3868
3869
3870 void GuiDocument::saveAsDefault() const
3871 {
3872         dispatch_bufferparams(*this, params(), LFUN_BUFFER_SAVE_AS_DEFAULT, &buffer());
3873 }
3874
3875
3876 bool GuiDocument::providesOSF(QString const & font) const
3877 {
3878         if (fontModule->osFontsCB->isChecked())
3879                 // FIXME: we should check if the fonts really
3880                 // have OSF support. But how?
3881                 return true;
3882         return theLaTeXFonts().getLaTeXFont(
3883                                 qstring_to_ucs4(font)).providesOSF(ot1(),
3884                                                                    completeFontset(),
3885                                                                    noMathFont());
3886 }
3887
3888
3889 bool GuiDocument::providesSC(QString const & font) const
3890 {
3891         if (fontModule->osFontsCB->isChecked())
3892                 return false;
3893         return theLaTeXFonts().getLaTeXFont(
3894                                 qstring_to_ucs4(font)).providesSC(ot1(),
3895                                                                   completeFontset(),
3896                                                                   noMathFont());
3897 }
3898
3899
3900 bool GuiDocument::providesScale(QString const & font) const
3901 {
3902         if (fontModule->osFontsCB->isChecked())
3903                 return true;
3904         return theLaTeXFonts().getLaTeXFont(
3905                                 qstring_to_ucs4(font)).providesScale(ot1(),
3906                                                                      completeFontset(),
3907                                                                      noMathFont());
3908 }
3909
3910
3911 bool GuiDocument::providesNoMath(QString const & font) const
3912 {
3913         if (fontModule->osFontsCB->isChecked())
3914                 return false;
3915         return theLaTeXFonts().getLaTeXFont(
3916                                 qstring_to_ucs4(font)).providesNoMath(ot1(),
3917                                                                       completeFontset());
3918 }
3919
3920
3921 bool GuiDocument::hasMonolithicExpertSet(QString const & font) const
3922 {
3923         if (fontModule->osFontsCB->isChecked())
3924                 return false;
3925         return theLaTeXFonts().getLaTeXFont(
3926                                 qstring_to_ucs4(font)).hasMonolithicExpertSet(ot1(),
3927                                                                               completeFontset(),
3928                                                                               noMathFont());
3929 }
3930
3931
3932 //static
3933 GuiDocument::modInfoStruct GuiDocument::modInfo(LyXModule const & mod)
3934 {
3935         // FIXME Unicode: docstrings would be better for these parameters but this
3936         // change requires a lot of others
3937         modInfoStruct m;
3938         m.id = mod.getID();
3939         m.name = toqstr(translateIfPossible(from_utf8(mod.getName())));
3940         QString desc = toqstr(translateIfPossible(from_utf8(mod.getDescription())));
3941         // Find the first sentence of the description
3942         QTextBoundaryFinder bf(QTextBoundaryFinder::Sentence, desc);
3943         int pos = bf.toNextBoundary();
3944         if (pos > 0)
3945                 desc.truncate(pos);
3946         QString modulename = QString(qt_("(Module name: %1)")).arg(toqstr(m.id));
3947         // Tooltip is the desc followed by the module name
3948         m.description = QString("%1<i>%2</i>")
3949                 .arg(desc.isEmpty() ? QString() : QString("<p>%1</p>").arg(desc),
3950                      modulename);
3951         return m;
3952 }
3953
3954
3955 void GuiDocument::loadModuleInfo()
3956 {
3957         moduleNames_.clear();
3958         for (LyXModule const & mod : theModuleList)
3959                 if (mod.category().substr(0, 8) != "Citation")
3960                         moduleNames_.push_back(modInfo(mod));
3961 }
3962
3963
3964 void GuiDocument::updateUnknownBranches()
3965 {
3966         if (!bufferview())
3967                 return;
3968         list<docstring> used_branches;
3969         buffer().getUsedBranches(used_branches);
3970         list<docstring>::const_iterator it = used_branches.begin();
3971         QStringList unknown_branches;
3972         for (; it != used_branches.end() ; ++it) {
3973                 if (!buffer().params().branchlist().find(*it))
3974                         unknown_branches.append(toqstr(*it));
3975         }
3976         branchesModule->setUnknownBranches(unknown_branches);
3977 }
3978
3979
3980 void GuiDocument::branchesRename(docstring const & oldname, docstring const & newname)
3981 {
3982         map<docstring, docstring>::iterator it = changedBranches_.begin();
3983         for (; it != changedBranches_.end() ; ++it) {
3984                 if (it->second == oldname) {
3985                         // branch has already been renamed
3986                         it->second = newname;
3987                         return;
3988                 }
3989         }
3990         // store new name
3991         changedBranches_[oldname] = newname;
3992 }
3993
3994
3995 void GuiDocument::executeBranchRenaming() const
3996 {
3997         map<docstring, docstring>::const_iterator it = changedBranches_.begin();
3998         for (; it != changedBranches_.end() ; ++it) {
3999                 docstring const arg = '"' + it->first + '"' + " " + '"' + it->second + '"';
4000                 dispatch(FuncRequest(LFUN_BRANCHES_RENAME, arg));
4001         }
4002 }
4003
4004
4005 void GuiDocument::allPackagesAuto()
4006 {
4007         allPackages(1);
4008 }
4009
4010
4011 void GuiDocument::allPackagesAlways()
4012 {
4013         allPackages(2);
4014 }
4015
4016
4017 void GuiDocument::allPackagesNot()
4018 {
4019         allPackages(3);
4020 }
4021
4022
4023 void GuiDocument::allPackages(int col)
4024 {
4025         for (int row = 0; row < mathsModule->packagesTW->rowCount(); ++row) {
4026                 QRadioButton * rb = (QRadioButton*)mathsModule->packagesTW->cellWidget(row, col);
4027                 rb->setChecked(true);
4028         }
4029 }
4030
4031
4032 Dialog * createGuiDocument(GuiView & lv) { return new GuiDocument(lv); }
4033
4034
4035 } // namespace frontend
4036 } // namespace lyx
4037
4038 #include "moc_GuiDocument.cpp"