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