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