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