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