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