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