]> git.lyx.org Git - features.git/blob - src/frontends/qt4/GuiDocument.cpp
Add tablestyle buffer param
[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."), cat);
2906         }
2907
2908         vector<string> pkglist = getPackageList(modName);
2909         docstring pkgdesc = formatStrVec(pkglist, _("and"));
2910         if (!pkgdesc.empty()) {
2911                 if (!desc.empty())
2912                         desc += "\n";
2913                 desc += bformat(_("Package(s) required: %1$s."), pkgdesc);
2914         }
2915
2916         pkglist = getRequiredList(modName);
2917         if (!pkglist.empty()) {
2918                 vector<string> const reqdescs = idsToNames(pkglist);
2919                 pkgdesc = formatStrVec(reqdescs, _("or"));
2920                 if (!desc.empty())
2921                         desc += "\n";
2922                 desc += bformat(_("Modules required: %1$s."), pkgdesc);
2923         }
2924
2925         pkglist = getExcludedList(modName);
2926         if (!pkglist.empty()) {
2927                 vector<string> const reqdescs = idsToNames(pkglist);
2928                 pkgdesc = formatStrVec(reqdescs, _( "and"));
2929                 if (!desc.empty())
2930                         desc += "\n";
2931                 desc += bformat(_("Modules excluded: %1$s."), pkgdesc);
2932         }
2933
2934         if (!desc.empty())
2935                 desc += "\n";
2936         desc += bformat(_("Filename: %1$s.module."), from_utf8(modName));
2937
2938         if (!isModuleAvailable(modName)) {
2939                 if (!desc.empty())
2940                         desc += "\n";
2941                 desc += _("WARNING: Some required packages are unavailable!");
2942         }
2943
2944         modulesModule->infoML->document()->setPlainText(toqstr(desc));
2945 }
2946
2947
2948 void GuiDocument::updateNumbering()
2949 {
2950         DocumentClass const & tclass = documentClass();
2951
2952         numberingModule->tocTW->setUpdatesEnabled(false);
2953         numberingModule->tocTW->clear();
2954
2955         int const depth = numberingModule->depthSL->value();
2956         int const toc = numberingModule->tocSL->value();
2957         QString const no = qt_("No");
2958         QString const yes = qt_("Yes");
2959         QTreeWidgetItem * item = 0;
2960
2961         DocumentClass::const_iterator lit = tclass.begin();
2962         DocumentClass::const_iterator len = tclass.end();
2963         for (; lit != len; ++lit) {
2964                 int const toclevel = lit->toclevel;
2965                 if (toclevel != Layout::NOT_IN_TOC && !lit->counter.empty()) {
2966                         item = new QTreeWidgetItem(numberingModule->tocTW);
2967                         item->setText(0, toqstr(translateIfPossible(lit->name())));
2968                         item->setText(1, (toclevel <= depth) ? yes : no);
2969                         item->setText(2, (toclevel <= toc) ? yes : no);
2970                 }
2971         }
2972
2973         numberingModule->tocTW->setUpdatesEnabled(true);
2974         numberingModule->tocTW->update();
2975 }
2976
2977
2978 void GuiDocument::getTableStyles()
2979 {
2980         // We look for lyx files in the subdirectory dir of
2981         //   1) user_lyxdir
2982         //   2) build_lyxdir (if not empty)
2983         //   3) system_lyxdir
2984         // in this order. Files with a given sub-hierarchy will
2985         // only be listed once.
2986         // We also consider i18n subdirectories and store them separately.
2987         QStringList dirs;
2988
2989         // The three locations to look at.
2990         string const user = addPath(package().user_support().absFileName(), "tabletemplates");
2991         string const build = addPath(package().build_support().absFileName(), "tabletemplates");
2992         string const system = addPath(package().system_support().absFileName(), "tabletemplates");
2993
2994         dirs << toqstr(user)
2995              << toqstr(build)
2996              << toqstr(system);
2997
2998         for (int i = 0; i < dirs.size(); ++i) {
2999                 QString const dir = dirs.at(i);
3000                 QDirIterator it(dir, QDir::Files, QDirIterator::Subdirectories);
3001                 while (it.hasNext()) {
3002                         QString fn = QFileInfo(it.next()).fileName();
3003                         if (!fn.endsWith(".lyx") || fn.contains("_1x"))
3004                                 continue;
3005                         QString data = fn.left(fn.lastIndexOf(".lyx"));
3006                         QString guiname = data;
3007                         guiname = toqstr(translateIfPossible(qstring_to_ucs4(guiname.replace('_', ' '))));
3008                         QString relpath = toqstr(makeRelPath(qstring_to_ucs4(fn),
3009                                                              qstring_to_ucs4(dir)));
3010                         if (textLayoutModule->tableStyleCO->findData(data) == -1)
3011                                 textLayoutModule->tableStyleCO->addItem(guiname, data);
3012                 }
3013         }
3014 }
3015
3016
3017 void GuiDocument::updateDefaultFormat()
3018 {
3019         if (!bufferview())
3020                 return;
3021         // make a copy in order to consider unapplied changes
3022         BufferParams param_copy = buffer().params();
3023         param_copy.useNonTeXFonts = fontModule->osFontsCB->isChecked();
3024         int const idx = latexModule->classCO->currentIndex();
3025         if (idx >= 0) {
3026                 string const classname = fromqstr(latexModule->classCO->getData(idx));
3027                 param_copy.setBaseClass(classname, buffer().layoutPos());
3028                 param_copy.makeDocumentClass(true);
3029         }
3030         outputModule->defaultFormatCO->blockSignals(true);
3031         outputModule->defaultFormatCO->clear();
3032         outputModule->defaultFormatCO->addItem(qt_("Default"),
3033                                 QVariant(QString("default")));
3034         FormatList const & formats =
3035                                 param_copy.exportableFormats(true);
3036         for (Format const * f : formats)
3037                 outputModule->defaultFormatCO->addItem
3038                         (toqstr(translateIfPossible(f->prettyname())),
3039                          QVariant(toqstr(f->name())));
3040         outputModule->defaultFormatCO->blockSignals(false);
3041 }
3042
3043
3044 bool GuiDocument::isChildIncluded(string const & child)
3045 {
3046         if (includeonlys_.empty())
3047                 return false;
3048         return (std::find(includeonlys_.begin(),
3049                           includeonlys_.end(), child) != includeonlys_.end());
3050 }
3051
3052
3053 void GuiDocument::applyView()
3054 {
3055         // preamble
3056         preambleModule->apply(bp_);
3057         localLayout->apply(bp_);
3058
3059         // date
3060         bp_.suppress_date = latexModule->suppressDateCB->isChecked();
3061         bp_.use_refstyle  = latexModule->refstyleCB->isChecked();
3062
3063         // biblio
3064         string const engine =
3065                 fromqstr(biblioModule->citeEngineCO->itemData(
3066                                 biblioModule->citeEngineCO->currentIndex()).toString());
3067         bp_.setCiteEngine(engine);
3068
3069         CiteEngineType const style = CiteEngineType(biblioModule->citeStyleCO->itemData(
3070                 biblioModule->citeStyleCO->currentIndex()).toInt());
3071         if (theCiteEnginesList[engine]->hasEngineType(style))
3072                 bp_.setCiteEngineType(style);
3073         else
3074                 bp_.setCiteEngineType(ENGINE_TYPE_DEFAULT);
3075
3076         bp_.splitbib(biblioModule->bibtopicCB->isChecked());
3077
3078         bp_.multibib = fromqstr(biblioModule->bibunitsCO->itemData(
3079                                 biblioModule->bibunitsCO->currentIndex()).toString());
3080
3081         bp_.setDefaultBiblioStyle(fromqstr(biblioModule->defaultBiblioCO->currentText()));
3082
3083         bp_.biblatex_bibstyle = fromqstr(biblioModule->biblatexBbxCO->currentText());
3084         bp_.biblatex_citestyle = fromqstr(biblioModule->biblatexCbxCO->currentText());
3085         bp_.biblio_opts = fromqstr(biblioModule->citePackageOptionsLE->text());
3086
3087         string const bibtex_command =
3088                 fromqstr(biblioModule->bibtexCO->itemData(
3089                         biblioModule->bibtexCO->currentIndex()).toString());
3090         string const bibtex_options =
3091                 fromqstr(biblioModule->bibtexOptionsLE->text());
3092         if (bibtex_command == "default" || bibtex_options.empty())
3093                 bp_.bibtex_command = bibtex_command;
3094         else
3095                 bp_.bibtex_command = bibtex_command + " " + bibtex_options;
3096
3097         if (biblioChanged_) {
3098                 buffer().invalidateBibinfoCache();
3099                 buffer().removeBiblioTempFiles();
3100         }
3101
3102         // Indices
3103         indicesModule->apply(bp_);
3104
3105         // language & quotes
3106         if (langModule->defaultencodingRB->isChecked()) {
3107                 bp_.inputenc = "auto";
3108         } else {
3109                 int i = langModule->encodingCO->currentIndex();
3110                 if (i == 0)
3111                         bp_.inputenc = "default";
3112                 else {
3113                         QString const enc_gui =
3114                                 langModule->encodingCO->currentText();
3115                         Encodings::const_iterator it = encodings.begin();
3116                         Encodings::const_iterator const end = encodings.end();
3117                         bool found = false;
3118                         for (; it != end; ++it) {
3119                                 if (qt_(it->guiName()) == enc_gui &&
3120                                     !it->unsafe()) {
3121                                         bp_.inputenc = it->name();
3122                                         found = true;
3123                                         break;
3124                                 }
3125                         }
3126                         if (!found) {
3127                                 // should not happen
3128                                 lyxerr << "GuiDocument::apply: Unknown encoding! Resetting to default" << endl;
3129                                 bp_.inputenc = "default";
3130                         }
3131                 }
3132         }
3133
3134         bp_.quotes_style = (InsetQuotesParams::QuoteStyle) langModule->quoteStyleCO->itemData(
3135                 langModule->quoteStyleCO->currentIndex()).toInt();
3136         bp_.dynamic_quotes = langModule->dynamicQuotesCB->isChecked();
3137
3138         QString const langname = langModule->languageCO->itemData(
3139                 langModule->languageCO->currentIndex()).toString();
3140         Language const * newlang = lyx::languages.getLanguage(fromqstr(langname));
3141         Cursor & cur = const_cast<BufferView *>(bufferview())->cursor();
3142         // If current cursor language was the document language, then update it too.
3143         if (cur.current_font.language() == bp_.language) {
3144                 cur.current_font.setLanguage(newlang);
3145                 cur.real_current_font.setLanguage(newlang);
3146         }
3147         bp_.language = newlang;
3148
3149         QString const pack = langModule->languagePackageCO->itemData(
3150                 langModule->languagePackageCO->currentIndex()).toString();
3151         if (pack == "custom")
3152                 bp_.lang_package =
3153                         fromqstr(langModule->languagePackageLE->text());
3154         else
3155                 bp_.lang_package = fromqstr(pack);
3156
3157         //color
3158         bp_.backgroundcolor = set_backgroundcolor;
3159         bp_.isbackgroundcolor = is_backgroundcolor;
3160         bp_.fontcolor = set_fontcolor;
3161         bp_.isfontcolor = is_fontcolor;
3162         bp_.notefontcolor = set_notefontcolor;
3163         bp_.boxbgcolor = set_boxbgcolor;
3164
3165         // numbering
3166         if (bp_.documentClass().hasTocLevels()) {
3167                 bp_.tocdepth = numberingModule->tocSL->value();
3168                 bp_.secnumdepth = numberingModule->depthSL->value();
3169         }
3170
3171         // bullets
3172         bp_.user_defined_bullet(0) = bulletsModule->bullet(0);
3173         bp_.user_defined_bullet(1) = bulletsModule->bullet(1);
3174         bp_.user_defined_bullet(2) = bulletsModule->bullet(2);
3175         bp_.user_defined_bullet(3) = bulletsModule->bullet(3);
3176
3177         // packages
3178         bp_.graphics_driver =
3179                 tex_graphics[latexModule->psdriverCO->currentIndex()];
3180
3181         // text layout
3182         int idx = latexModule->classCO->currentIndex();
3183         if (idx >= 0) {
3184                 string const classname = fromqstr(latexModule->classCO->getData(idx));
3185                 bp_.setBaseClass(classname, buffer().layoutPos());
3186         }
3187
3188         // Modules
3189         modulesToParams(bp_);
3190
3191         // Math
3192         map<string, string> const & packages = BufferParams::auto_packages();
3193         for (map<string, string>::const_iterator it = packages.begin();
3194              it != packages.end(); ++it) {
3195                 QTableWidgetItem * item = mathsModule->packagesTW->findItems(toqstr(it->first), Qt::MatchExactly)[0];
3196                 if (!item)
3197                         continue;
3198                 int row = mathsModule->packagesTW->row(item);
3199
3200                 QRadioButton * rb =
3201                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 1)->layout()->itemAt(0)->widget();
3202                 if (rb->isChecked()) {
3203                         bp_.use_package(it->first, BufferParams::package_auto);
3204                         continue;
3205                 }
3206                 rb = (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 2)->layout()->itemAt(0)->widget();
3207                 if (rb->isChecked()) {
3208                         bp_.use_package(it->first, BufferParams::package_on);
3209                         continue;
3210                 }
3211                 rb = (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 3)->layout()->itemAt(0)->widget();
3212                 if (rb->isChecked())
3213                         bp_.use_package(it->first, BufferParams::package_off);
3214         }
3215         // if math is indented
3216         bp_.is_math_indent = mathsModule->MathIndentCB->isChecked();
3217         if (bp_.is_math_indent) {
3218                 // if formulas are indented
3219                 switch (mathsModule->MathIndentCO->currentIndex()) {
3220                 case 0:
3221                         bp_.setMathIndent(Length());
3222                         break;
3223                 case 1: {
3224                         Length mathindent(widgetsToLength(mathsModule->MathIndentLE,
3225                                                           mathsModule->MathIndentLengthCO));
3226                         bp_.setMathIndent(mathindent);
3227                         break;
3228                 }
3229                 default:
3230                         // this should never happen
3231                         bp_.setMathIndent(Length());
3232                         break;
3233                 }
3234         }
3235         switch (mathsModule->MathNumberingPosCO->currentIndex()) {
3236                 case 0:
3237                         bp_.math_numbering_side = BufferParams::LEFT;
3238                         break;
3239                 case 1:
3240                         bp_.math_numbering_side = BufferParams::DEFAULT;
3241                         break;
3242                 case 2:
3243                         bp_.math_numbering_side = BufferParams::RIGHT;
3244                         break;
3245                 default:
3246                         // this should never happen
3247                         bp_.math_numbering_side = BufferParams::DEFAULT;
3248                         break;
3249         }
3250
3251         // Page Layout
3252         if (pageLayoutModule->pagestyleCO->currentIndex() == 0)
3253                 bp_.pagestyle = "default";
3254         else {
3255                 QString style_gui = pageLayoutModule->pagestyleCO->currentText();
3256                 for (size_t i = 0; i != pagestyles.size(); ++i)
3257                         if (pagestyles[i].second == style_gui)
3258                                 bp_.pagestyle = pagestyles[i].first;
3259         }
3260
3261         // Text Layout
3262         switch (textLayoutModule->lspacingCO->currentIndex()) {
3263         case 0:
3264                 bp_.spacing().set(Spacing::Single);
3265                 break;
3266         case 1:
3267                 bp_.spacing().set(Spacing::Onehalf);
3268                 break;
3269         case 2:
3270                 bp_.spacing().set(Spacing::Double);
3271                 break;
3272         case 3: {
3273                 string s = widgetToDoubleStr(textLayoutModule->lspacingLE);
3274                 if (s.empty())
3275                         bp_.spacing().set(Spacing::Single);
3276                 else
3277                         bp_.spacing().set(Spacing::Other, s);
3278                 break;
3279                 }
3280         }
3281
3282         if (textLayoutModule->twoColumnCB->isChecked())
3283                 bp_.columns = 2;
3284         else
3285                 bp_.columns = 1;
3286
3287         bp_.justification = textLayoutModule->justCB->isChecked();
3288
3289         if (textLayoutModule->indentRB->isChecked()) {
3290                 // if paragraphs are separated by an indentation
3291                 bp_.paragraph_separation = BufferParams::ParagraphIndentSeparation;
3292                 switch (textLayoutModule->indentCO->currentIndex()) {
3293                 case 0:
3294                         bp_.setParIndent(Length());
3295                         break;
3296                 case 1: {
3297                         Length parindent(widgetsToLength(textLayoutModule->indentLE,
3298                                                          textLayoutModule->indentLengthCO));
3299                         bp_.setParIndent(parindent);
3300                         break;
3301                 }
3302                 default:
3303                         // this should never happen
3304                         bp_.setParIndent(Length());
3305                         break;
3306                 }
3307         } else {
3308                 // if paragraphs are separated by a skip
3309                 bp_.paragraph_separation = BufferParams::ParagraphSkipSeparation;
3310                 switch (textLayoutModule->skipCO->currentIndex()) {
3311                 case 0:
3312                         bp_.setDefSkip(VSpace(VSpace::SMALLSKIP));
3313                         break;
3314                 case 1:
3315                         bp_.setDefSkip(VSpace(VSpace::MEDSKIP));
3316                         break;
3317                 case 2:
3318                         bp_.setDefSkip(VSpace(VSpace::BIGSKIP));
3319                         break;
3320                 case 3:
3321                         {
3322                         VSpace vs = VSpace(
3323                                 widgetsToLength(textLayoutModule->skipLE,
3324                                 textLayoutModule->skipLengthCO)
3325                                 );
3326                         bp_.setDefSkip(vs);
3327                         break;
3328                         }
3329                 default:
3330                         // this should never happen
3331                         bp_.setDefSkip(VSpace(VSpace::MEDSKIP));
3332                         break;
3333                 }
3334         }
3335         bp_.tablestyle = fromqstr(textLayoutModule->tableStyleCO->itemData(
3336                                       textLayoutModule->tableStyleCO->currentIndex()).toString());
3337
3338         bp_.options =
3339                 fromqstr(latexModule->optionsLE->text());
3340
3341         bp_.use_default_options =
3342                 latexModule->defaultOptionsCB->isChecked();
3343
3344         if (latexModule->childDocGB->isChecked())
3345                 bp_.master =
3346                         fromqstr(latexModule->childDocLE->text());
3347         else
3348                 bp_.master = string();
3349
3350         // Master/Child
3351         bp_.clearIncludedChildren();
3352         if (masterChildModule->includeonlyRB->isChecked()) {
3353                 list<string>::const_iterator it = includeonlys_.begin();
3354                 for (; it != includeonlys_.end() ; ++it) {
3355                         bp_.addIncludedChildren(*it);
3356                 }
3357         }
3358         bp_.maintain_unincluded_children =
3359                 masterChildModule->maintainAuxCB->isChecked();
3360
3361         // Float Settings
3362         bp_.float_placement = floatModule->getPlacement();
3363         bp_.float_alignment = floatModule->getAlignment();
3364
3365         // Listings
3366         // text should have passed validation
3367         idx = listingsModule->packageCO->currentIndex();
3368         bp_.use_minted = string(lst_packages[idx]) == "Minted";
3369         bp_.listings_params =
3370                 InsetListingsParams(fromqstr(listingsModule->listingsED->toPlainText())).params();
3371
3372         // Formats
3373         bp_.default_output_format = fromqstr(outputModule->defaultFormatCO->itemData(
3374                 outputModule->defaultFormatCO->currentIndex()).toString());
3375
3376         bool const nontexfonts = fontModule->osFontsCB->isChecked();
3377         bp_.useNonTeXFonts = nontexfonts;
3378
3379         bp_.shell_escape = outputModule->shellescapeCB->isChecked();
3380         if (!bp_.shell_escape)
3381             theSession().shellescapeFiles().remove(buffer().absFileName());
3382         else if (!theSession().shellescapeFiles().find(buffer().absFileName()))
3383             theSession().shellescapeFiles().insert(buffer().absFileName());
3384         Buffer & buf = const_cast<Buffer &>(buffer());
3385         buf.params().shell_escape = bp_.shell_escape;
3386
3387         bp_.output_sync = outputModule->outputsyncCB->isChecked();
3388
3389         bp_.output_sync_macro = fromqstr(outputModule->synccustomCB->currentText());
3390
3391         int mathfmt = outputModule->mathoutCB->currentIndex();
3392         if (mathfmt == -1)
3393                 mathfmt = 0;
3394         BufferParams::MathOutput const mo =
3395                 static_cast<BufferParams::MathOutput>(mathfmt);
3396         bp_.html_math_output = mo;
3397         bp_.html_be_strict = outputModule->strictCB->isChecked();
3398         bp_.html_css_as_file = outputModule->cssCB->isChecked();
3399         bp_.html_math_img_scale = outputModule->mathimgSB->value();
3400         bp_.display_pixel_ratio = theGuiApp()->pixelRatio();
3401
3402         bp_.save_transient_properties =
3403                 outputModule->saveTransientPropertiesCB->isChecked();
3404
3405         // fonts
3406         bp_.fonts_roman[nontexfonts] =
3407                 fromqstr(fontModule->fontsRomanCO->
3408                         itemData(fontModule->fontsRomanCO->currentIndex()).toString());
3409         bp_.fonts_roman[!nontexfonts] = fromqstr(fontModule->font_roman);
3410
3411         bp_.fonts_sans[nontexfonts] =
3412                 fromqstr(fontModule->fontsSansCO->
3413                         itemData(fontModule->fontsSansCO->currentIndex()).toString());
3414         bp_.fonts_sans[!nontexfonts] = fromqstr(fontModule->font_sans);
3415
3416         bp_.fonts_typewriter[nontexfonts] =
3417                 fromqstr(fontModule->fontsTypewriterCO->
3418                         itemData(fontModule->fontsTypewriterCO->currentIndex()).toString());
3419         bp_.fonts_typewriter[!nontexfonts] = fromqstr(fontModule->font_typewriter);
3420
3421         bp_.fonts_math[nontexfonts] =
3422                 fromqstr(fontModule->fontsMathCO->
3423                         itemData(fontModule->fontsMathCO->currentIndex()).toString());
3424         bp_.fonts_math[!nontexfonts] = fromqstr(fontModule->font_math);
3425
3426         QString const fontenc =
3427                 fontModule->fontencCO->itemData(fontModule->fontencCO->currentIndex()).toString();
3428         if (fontenc == "custom")
3429                 bp_.fontenc = fromqstr(fontModule->fontencLE->text());
3430         else
3431                 bp_.fontenc = fromqstr(fontenc);
3432
3433         bp_.fonts_cjk =
3434                 fromqstr(fontModule->cjkFontLE->text());
3435
3436         bp_.use_microtype = fontModule->microtypeCB->isChecked();
3437         bp_.use_dash_ligatures = !fontModule->dashesCB->isChecked();
3438
3439         bp_.fonts_sans_scale[nontexfonts] = fontModule->scaleSansSB->value();
3440         bp_.fonts_sans_scale[!nontexfonts] = fontModule->font_sf_scale;
3441
3442         bp_.fonts_typewriter_scale[nontexfonts] = fontModule->scaleTypewriterSB->value();
3443         bp_.fonts_typewriter_scale[!nontexfonts] = fontModule->font_tt_scale;
3444
3445         bp_.fonts_expert_sc = fontModule->fontScCB->isChecked();
3446
3447         bp_.fonts_old_figures = fontModule->fontOsfCB->isChecked();
3448
3449         if (nontexfonts)
3450                 bp_.fonts_default_family = "default";
3451         else
3452                 bp_.fonts_default_family = GuiDocument::fontfamilies[
3453                         fontModule->fontsDefaultCO->currentIndex()];
3454
3455         if (fontModule->fontsizeCO->currentIndex() == 0)
3456                 bp_.fontsize = "default";
3457         else
3458                 bp_.fontsize =
3459                         fromqstr(fontModule->fontsizeCO->currentText());
3460
3461         // paper
3462         bp_.papersize = PAPER_SIZE(
3463                 pageLayoutModule->papersizeCO->currentIndex());
3464
3465         bp_.paperwidth = widgetsToLength(pageLayoutModule->paperwidthLE,
3466                 pageLayoutModule->paperwidthUnitCO);
3467
3468         bp_.paperheight = widgetsToLength(pageLayoutModule->paperheightLE,
3469                 pageLayoutModule->paperheightUnitCO);
3470
3471         if (pageLayoutModule->facingPagesCB->isChecked())
3472                 bp_.sides = TwoSides;
3473         else
3474                 bp_.sides = OneSide;
3475
3476         if (pageLayoutModule->landscapeRB->isChecked())
3477                 bp_.orientation = ORIENTATION_LANDSCAPE;
3478         else
3479                 bp_.orientation = ORIENTATION_PORTRAIT;
3480
3481         // margins
3482         bp_.use_geometry = !marginsModule->marginCB->isChecked();
3483
3484         Ui::MarginsUi const * m = marginsModule;
3485
3486         bp_.leftmargin = widgetsToLength(m->innerLE, m->innerUnit);
3487         bp_.topmargin = widgetsToLength(m->topLE, m->topUnit);
3488         bp_.rightmargin = widgetsToLength(m->outerLE, m->outerUnit);
3489         bp_.bottommargin = widgetsToLength(m->bottomLE, m->bottomUnit);
3490         bp_.headheight = widgetsToLength(m->headheightLE, m->headheightUnit);
3491         bp_.headsep = widgetsToLength(m->headsepLE, m->headsepUnit);
3492         bp_.footskip = widgetsToLength(m->footskipLE, m->footskipUnit);
3493         bp_.columnsep = widgetsToLength(m->columnsepLE, m->columnsepUnit);
3494
3495         // branches
3496         branchesModule->apply(bp_);
3497
3498         // PDF support
3499         PDFOptions & pdf = bp_.pdfoptions();
3500         pdf.use_hyperref = pdfSupportModule->use_hyperrefGB->isChecked();
3501         pdf.title = fromqstr(pdfSupportModule->titleLE->text());
3502         pdf.author = fromqstr(pdfSupportModule->authorLE->text());
3503         pdf.subject = fromqstr(pdfSupportModule->subjectLE->text());
3504         pdf.keywords = fromqstr(pdfSupportModule->keywordsLE->text());
3505
3506         pdf.bookmarks = pdfSupportModule->bookmarksGB->isChecked();
3507         pdf.bookmarksnumbered = pdfSupportModule->bookmarksnumberedCB->isChecked();
3508         pdf.bookmarksopen = pdfSupportModule->bookmarksopenGB->isChecked();
3509         pdf.bookmarksopenlevel = pdfSupportModule->bookmarksopenlevelSB->value();
3510
3511         pdf.breaklinks = pdfSupportModule->breaklinksCB->isChecked();
3512         pdf.pdfborder = pdfSupportModule->pdfborderCB->isChecked();
3513         pdf.pdfusetitle = pdfSupportModule->pdfusetitleCB->isChecked();
3514         pdf.colorlinks = pdfSupportModule->colorlinksCB->isChecked();
3515         pdf.backref =
3516                 backref_opts[pdfSupportModule->backrefCO->currentIndex()];
3517         if (pdfSupportModule->fullscreenCB->isChecked())
3518                 pdf.pagemode = pdf.pagemode_fullscreen;
3519         else
3520                 pdf.pagemode.clear();
3521         pdf.quoted_options = pdf.quoted_options_check(
3522                                 fromqstr(pdfSupportModule->optionsLE->text()));
3523
3524         // reset trackers
3525         nonModuleChanged_ = false;
3526         shellescapeChanged_ = false;
3527 }
3528
3529
3530 void GuiDocument::paramsToDialog()
3531 {
3532         // set the default unit
3533         Length::UNIT const default_unit = Length::defaultUnit();
3534
3535         // preamble
3536         preambleModule->update(bp_, id());
3537         localLayout->update(bp_, id());
3538
3539         // date
3540         latexModule->suppressDateCB->setChecked(bp_.suppress_date);
3541         latexModule->refstyleCB->setChecked(bp_.use_refstyle);
3542
3543         // biblio
3544         string const cite_engine = bp_.citeEngine();
3545
3546         biblioModule->citeEngineCO->setCurrentIndex(
3547                 biblioModule->citeEngineCO->findData(toqstr(cite_engine)));
3548
3549         updateEngineType(documentClass().opt_enginetype(),
3550                 bp_.citeEngineType());
3551
3552         checkPossibleCiteEngines();
3553
3554         biblioModule->citeStyleCO->setCurrentIndex(
3555                 biblioModule->citeStyleCO->findData(bp_.citeEngineType()));
3556
3557         biblioModule->bibtopicCB->setChecked(bp_.splitbib());
3558
3559         biblioModule->bibunitsCO->clear();
3560         biblioModule->bibunitsCO->addItem(qt_("No"), QString());
3561         if (documentClass().hasLaTeXLayout("part"))
3562                 biblioModule->bibunitsCO->addItem(qt_("per part"), toqstr("part"));
3563         if (documentClass().hasLaTeXLayout("chapter"))
3564                 biblioModule->bibunitsCO->addItem(qt_("per chapter"), toqstr("chapter"));
3565         if (documentClass().hasLaTeXLayout("section"))
3566                 biblioModule->bibunitsCO->addItem(qt_("per section"), toqstr("section"));
3567         if (documentClass().hasLaTeXLayout("subsection"))
3568                 biblioModule->bibunitsCO->addItem(qt_("per subsection"), toqstr("subsection"));
3569         biblioModule->bibunitsCO->addItem(qt_("per child document"), toqstr("child"));
3570
3571         int const mbpos = biblioModule->bibunitsCO->findData(toqstr(bp_.multibib));
3572         if (mbpos != -1)
3573                 biblioModule->bibunitsCO->setCurrentIndex(mbpos);
3574         else
3575                 biblioModule->bibunitsCO->setCurrentIndex(0);
3576
3577         updateEngineDependends();
3578
3579         if (isBiblatex()) {
3580                 updateDefaultBiblio(bp_.biblatex_bibstyle, "bbx");
3581                 updateDefaultBiblio(bp_.biblatex_citestyle, "cbx");
3582         } else
3583                 updateDefaultBiblio(bp_.defaultBiblioStyle());
3584
3585         biblioModule->citePackageOptionsLE->setText(toqstr(bp_.biblio_opts));
3586
3587         string command;
3588         string options =
3589                 split(bp_.bibtex_command, command, ' ');
3590
3591         int const bpos = biblioModule->bibtexCO->findData(toqstr(command));
3592         if (bpos != -1) {
3593                 biblioModule->bibtexCO->setCurrentIndex(bpos);
3594                 biblioModule->bibtexOptionsLE->setText(toqstr(options).trimmed());
3595         } else {
3596                 // We reset to default if we do not know the specified compiler
3597                 // This is for security reasons
3598                 biblioModule->bibtexCO->setCurrentIndex(
3599                         biblioModule->bibtexCO->findData(toqstr("default")));
3600                 biblioModule->bibtexOptionsLE->clear();
3601         }
3602         biblioModule->bibtexOptionsLE->setEnabled(
3603                 biblioModule->bibtexCO->currentIndex() != 0);
3604
3605         biblioChanged_ = false;
3606
3607         // indices
3608         // We may be called when there is no Buffer, e.g., when
3609         // the last view has just been closed.
3610         bool const isReadOnly = isBufferAvailable() ? buffer().isReadonly() : false;
3611         indicesModule->update(bp_, isReadOnly);
3612
3613         // language & quotes
3614         int const pos = langModule->languageCO->findData(toqstr(
3615                 bp_.language->lang()));
3616         langModule->languageCO->setCurrentIndex(pos);
3617
3618         updateQuoteStyles();
3619
3620         langModule->quoteStyleCO->setCurrentIndex(
3621                 langModule->quoteStyleCO->findData(bp_.quotes_style));
3622         langModule->dynamicQuotesCB->setChecked(bp_.dynamic_quotes);
3623
3624         bool default_enc = true;
3625         if (bp_.inputenc != "auto") {
3626                 default_enc = false;
3627                 if (bp_.inputenc == "default") {
3628                         langModule->encodingCO->setCurrentIndex(0);
3629                 } else {
3630                         string enc_gui;
3631                         Encodings::const_iterator it = encodings.begin();
3632                         Encodings::const_iterator const end = encodings.end();
3633                         for (; it != end; ++it) {
3634                                 if (it->name() == bp_.inputenc &&
3635                                     !it->unsafe()) {
3636                                         enc_gui = it->guiName();
3637                                         break;
3638                                 }
3639                         }
3640                         int const i = langModule->encodingCO->findText(
3641                                         qt_(enc_gui));
3642                         if (i >= 0)
3643                                 langModule->encodingCO->setCurrentIndex(i);
3644                         else
3645                                 // unknown encoding. Set to default.
3646                                 default_enc = true;
3647                 }
3648         }
3649         langModule->defaultencodingRB->setChecked(default_enc);
3650         langModule->otherencodingRB->setChecked(!default_enc);
3651
3652         int const p = langModule->languagePackageCO->findData(toqstr(bp_.lang_package));
3653         if (p == -1) {
3654                 langModule->languagePackageCO->setCurrentIndex(
3655                           langModule->languagePackageCO->findData("custom"));
3656                 langModule->languagePackageLE->setText(toqstr(bp_.lang_package));
3657         } else {
3658                 langModule->languagePackageCO->setCurrentIndex(p);
3659                 langModule->languagePackageLE->clear();
3660         }
3661
3662         //color
3663         if (bp_.isfontcolor) {
3664                 colorModule->fontColorPB->setStyleSheet(
3665                         colorButtonStyleSheet(rgb2qcolor(bp_.fontcolor)));
3666         }
3667         set_fontcolor = bp_.fontcolor;
3668         is_fontcolor = bp_.isfontcolor;
3669
3670         colorModule->noteFontColorPB->setStyleSheet(
3671                 colorButtonStyleSheet(rgb2qcolor(bp_.notefontcolor)));
3672         set_notefontcolor = bp_.notefontcolor;
3673
3674         if (bp_.isbackgroundcolor) {
3675                 colorModule->backgroundPB->setStyleSheet(
3676                         colorButtonStyleSheet(rgb2qcolor(bp_.backgroundcolor)));
3677         }
3678         set_backgroundcolor = bp_.backgroundcolor;
3679         is_backgroundcolor = bp_.isbackgroundcolor;
3680
3681         colorModule->boxBackgroundPB->setStyleSheet(
3682                 colorButtonStyleSheet(rgb2qcolor(bp_.boxbgcolor)));
3683         set_boxbgcolor = bp_.boxbgcolor;
3684
3685         // numbering
3686         int const min_toclevel = documentClass().min_toclevel();
3687         int const max_toclevel = documentClass().max_toclevel();
3688         if (documentClass().hasTocLevels()) {
3689                 numberingModule->setEnabled(true);
3690                 numberingModule->depthSL->setMinimum(min_toclevel - 1);
3691                 numberingModule->depthSL->setMaximum(max_toclevel);
3692                 numberingModule->depthSL->setValue(bp_.secnumdepth);
3693                 numberingModule->tocSL->setMaximum(min_toclevel - 1);
3694                 numberingModule->tocSL->setMaximum(max_toclevel);
3695                 numberingModule->tocSL->setValue(bp_.tocdepth);
3696                 updateNumbering();
3697         } else {
3698                 numberingModule->setEnabled(false);
3699                 numberingModule->tocTW->clear();
3700         }
3701
3702         // bullets
3703         bulletsModule->setBullet(0, bp_.user_defined_bullet(0));
3704         bulletsModule->setBullet(1, bp_.user_defined_bullet(1));
3705         bulletsModule->setBullet(2, bp_.user_defined_bullet(2));
3706         bulletsModule->setBullet(3, bp_.user_defined_bullet(3));
3707         bulletsModule->init();
3708
3709         // packages
3710         int nitem = findToken(tex_graphics, bp_.graphics_driver);
3711         if (nitem >= 0)
3712                 latexModule->psdriverCO->setCurrentIndex(nitem);
3713         updateModuleInfo();
3714
3715         // math
3716         mathsModule->MathIndentCB->setChecked(bp_.is_math_indent);
3717         if (bp_.is_math_indent) {
3718                 Length const mathindent = bp_.getMathIndent();
3719                 int indent = 0;
3720                 if (!mathindent.empty()) {
3721                         lengthToWidgets(mathsModule->MathIndentLE,
3722                                         mathsModule->MathIndentLengthCO,
3723                                         mathindent, default_unit);
3724                         indent = 1;
3725                 }
3726                 mathsModule->MathIndentCO->setCurrentIndex(indent);
3727                 enableMathIndent(indent);
3728         }
3729         switch(bp_.math_numbering_side) {
3730         case BufferParams::LEFT:
3731                 mathsModule->MathNumberingPosCO->setCurrentIndex(0);
3732                 break;
3733         case BufferParams::DEFAULT:
3734                 mathsModule->MathNumberingPosCO->setCurrentIndex(1);
3735                 break;
3736         case BufferParams::RIGHT:
3737                 mathsModule->MathNumberingPosCO->setCurrentIndex(2);
3738         }
3739
3740         map<string, string> const & packages = BufferParams::auto_packages();
3741         for (map<string, string>::const_iterator it = packages.begin();
3742              it != packages.end(); ++it) {
3743                 QTableWidgetItem * item = mathsModule->packagesTW->findItems(toqstr(it->first), Qt::MatchExactly)[0];
3744                 if (!item)
3745                         continue;
3746                 int row = mathsModule->packagesTW->row(item);
3747                 switch (bp_.use_package(it->first)) {
3748                         case BufferParams::package_off: {
3749                                 QRadioButton * rb =
3750                                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 3)->layout()->itemAt(0)->widget();
3751                                 rb->setChecked(true);
3752                                 break;
3753                         }
3754                         case BufferParams::package_on: {
3755                                 QRadioButton * rb =
3756                                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 2)->layout()->itemAt(0)->widget();
3757                                 rb->setChecked(true);
3758                                 break;
3759                         }
3760                         case BufferParams::package_auto: {
3761                                 QRadioButton * rb =
3762                                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 1)->layout()->itemAt(0)->widget();
3763                                 rb->setChecked(true);
3764                                 break;
3765                         }
3766                 }
3767         }
3768
3769         switch (bp_.spacing().getSpace()) {
3770                 case Spacing::Other: nitem = 3; break;
3771                 case Spacing::Double: nitem = 2; break;
3772                 case Spacing::Onehalf: nitem = 1; break;
3773                 case Spacing::Default: case Spacing::Single: nitem = 0; break;
3774         }
3775
3776         // text layout
3777         string const & layoutID = bp_.baseClassID();
3778         setLayoutComboByIDString(layoutID);
3779
3780         updatePagestyle(documentClass().opt_pagestyle(),
3781                                  bp_.pagestyle);
3782
3783         textLayoutModule->lspacingCO->setCurrentIndex(nitem);
3784         if (bp_.spacing().getSpace() == Spacing::Other) {
3785                 doubleToWidget(textLayoutModule->lspacingLE,
3786                         bp_.spacing().getValueAsString());
3787         }
3788         setLSpacing(nitem);
3789         int ts = textLayoutModule->tableStyleCO->findData(toqstr(bp_.tablestyle));
3790         if (ts != -1)
3791                 textLayoutModule->tableStyleCO->setCurrentIndex(ts);
3792
3793         if (bp_.paragraph_separation == BufferParams::ParagraphIndentSeparation) {
3794                 textLayoutModule->indentRB->setChecked(true);
3795                 string parindent = bp_.getParIndent().asString();
3796                 int indent = 0;
3797                 if (!parindent.empty()) {
3798                         lengthToWidgets(textLayoutModule->indentLE,
3799                                         textLayoutModule->indentLengthCO,
3800                                         parindent, default_unit);
3801                         indent = 1;
3802                 }
3803                 textLayoutModule->indentCO->setCurrentIndex(indent);
3804                 setIndent(indent);
3805         } else {
3806                 textLayoutModule->skipRB->setChecked(true);
3807                 int skip = 0;
3808                 switch (bp_.getDefSkip().kind()) {
3809                 case VSpace::SMALLSKIP:
3810                         skip = 0;
3811                         break;
3812                 case VSpace::MEDSKIP:
3813                         skip = 1;
3814                         break;
3815                 case VSpace::BIGSKIP:
3816                         skip = 2;
3817                         break;
3818                 case VSpace::LENGTH:
3819                         {
3820                         skip = 3;
3821                         string const length = bp_.getDefSkip().asLyXCommand();
3822                         lengthToWidgets(textLayoutModule->skipLE,
3823                                 textLayoutModule->skipLengthCO,
3824                                 length, default_unit);
3825                         break;
3826                         }
3827                 default:
3828                         skip = 0;
3829                         break;
3830                 }
3831                 textLayoutModule->skipCO->setCurrentIndex(skip);
3832                 setSkip(skip);
3833         }
3834
3835         textLayoutModule->twoColumnCB->setChecked(
3836                 bp_.columns == 2);
3837         textLayoutModule->justCB->setChecked(bp_.justification);
3838
3839         if (!bp_.options.empty()) {
3840                 latexModule->optionsLE->setText(
3841                         toqstr(bp_.options));
3842         } else {
3843                 latexModule->optionsLE->setText(QString());
3844         }
3845
3846         // latex
3847         latexModule->defaultOptionsCB->setChecked(
3848                         bp_.use_default_options);
3849         updateSelectedModules();
3850         selectionManager->updateProvidedModules(
3851                         bp_.baseClass()->providedModules());
3852         selectionManager->updateExcludedModules(
3853                         bp_.baseClass()->excludedModules());
3854
3855         if (!documentClass().options().empty()) {
3856                 latexModule->defaultOptionsLE->setText(
3857                         toqstr(documentClass().options()));
3858         } else {
3859                 latexModule->defaultOptionsLE->setText(
3860                         toqstr(_("[No options predefined]")));
3861         }
3862
3863         latexModule->defaultOptionsLE->setEnabled(
3864                 bp_.use_default_options
3865                 && !documentClass().options().empty());
3866
3867         latexModule->defaultOptionsCB->setEnabled(
3868                 !documentClass().options().empty());
3869
3870         if (!bp_.master.empty()) {
3871                 latexModule->childDocGB->setChecked(true);
3872                 latexModule->childDocLE->setText(
3873                         toqstr(bp_.master));
3874         } else {
3875                 latexModule->childDocLE->setText(QString());
3876                 latexModule->childDocGB->setChecked(false);
3877         }
3878
3879         // Master/Child
3880         if (!bufferview() || !buffer().hasChildren()) {
3881                 masterChildModule->childrenTW->clear();
3882                 includeonlys_.clear();
3883                 docPS->showPanel("Child Documents", false);
3884                 if (docPS->isCurrentPanel("Child Documents"))
3885                         docPS->setCurrentPanel("Document Class");
3886         } else {
3887                 docPS->showPanel("Child Documents", true);
3888                 masterChildModule->setEnabled(true);
3889                 includeonlys_ = bp_.getIncludedChildren();
3890                 updateIncludeonlys();
3891         }
3892         masterChildModule->maintainAuxCB->setChecked(
3893                 bp_.maintain_unincluded_children);
3894
3895         // Float Settings
3896         floatModule->setPlacement(bp_.float_placement);
3897         floatModule->setAlignment(bp_.float_alignment);
3898
3899         // ListingsSettings
3900         // break listings_params to multiple lines
3901         string lstparams =
3902                 InsetListingsParams(bp_.listings_params).separatedParams();
3903         listingsModule->listingsED->setPlainText(toqstr(lstparams));
3904         int nn = findToken(lst_packages, bp_.use_minted ? "Minted" : "Listings");
3905         if (nn >= 0)
3906                 listingsModule->packageCO->setCurrentIndex(nn);
3907
3908         // Fonts
3909         // some languages only work with Polyglossia (which requires non-TeX fonts)
3910         Language const * lang = lyx::languages.getLanguage(
3911                 fromqstr(langModule->languageCO->itemData(
3912                         langModule->languageCO->currentIndex()).toString()));
3913         bool const need_fontspec =
3914                 lang->babel().empty() && !lang->polyglossia().empty();
3915         bool const os_fonts_available =
3916                 bp_.baseClass()->outputType() == lyx::LATEX
3917                 && LaTeXFeatures::isAvailable("fontspec");
3918         fontModule->osFontsCB->setEnabled(os_fonts_available && !need_fontspec);
3919         fontModule->osFontsCB->setChecked(
3920                 (os_fonts_available && bp_.useNonTeXFonts) || need_fontspec);
3921         updateFontsize(documentClass().opt_fontsize(),
3922                         bp_.fontsize);
3923
3924         QString font = toqstr(bp_.fontsRoman());
3925         int rpos = fontModule->fontsRomanCO->findData(font);
3926         if (rpos == -1) {
3927                 rpos = fontModule->fontsRomanCO->count();
3928                 fontModule->fontsRomanCO->addItem(font + qt_(" (not installed)"), font);
3929         }
3930         fontModule->fontsRomanCO->setCurrentIndex(rpos);
3931         fontModule->font_roman = toqstr(bp_.fonts_roman[!bp_.useNonTeXFonts]);
3932
3933         font = toqstr(bp_.fontsSans());
3934         int spos = fontModule->fontsSansCO->findData(font);
3935         if (spos == -1) {
3936                 spos = fontModule->fontsSansCO->count();
3937                 fontModule->fontsSansCO->addItem(font + qt_(" (not installed)"), font);
3938         }
3939         fontModule->fontsSansCO->setCurrentIndex(spos);
3940         fontModule->font_sans = toqstr(bp_.fonts_sans[!bp_.useNonTeXFonts]);
3941
3942         font = toqstr(bp_.fontsTypewriter());
3943         int tpos = fontModule->fontsTypewriterCO->findData(font);
3944         if (tpos == -1) {
3945                 tpos = fontModule->fontsTypewriterCO->count();
3946                 fontModule->fontsTypewriterCO->addItem(font + qt_(" (not installed)"), font);
3947         }
3948         fontModule->fontsTypewriterCO->setCurrentIndex(tpos);
3949         fontModule->font_typewriter = toqstr(bp_.fonts_typewriter[!bp_.useNonTeXFonts]);
3950
3951         font = toqstr(bp_.fontsMath());
3952         int mpos = fontModule->fontsMathCO->findData(font);
3953         if (mpos == -1) {
3954                 mpos = fontModule->fontsMathCO->count();
3955                 fontModule->fontsMathCO->addItem(font + qt_(" (not installed)"), font);
3956         }
3957         fontModule->fontsMathCO->setCurrentIndex(mpos);
3958         fontModule->font_math = toqstr(bp_.fonts_math[!bp_.useNonTeXFonts]);
3959
3960         if (bp_.useNonTeXFonts && os_fonts_available) {
3961                 fontModule->fontencLA->setEnabled(false);
3962                 fontModule->fontencCO->setEnabled(false);
3963                 fontModule->fontencLE->setEnabled(false);
3964         } else {
3965                 fontModule->fontencLA->setEnabled(true);
3966                 fontModule->fontencCO->setEnabled(true);
3967                 fontModule->fontencLE->setEnabled(true);
3968                 romanChanged(rpos);
3969                 sansChanged(spos);
3970                 ttChanged(tpos);
3971         }
3972
3973         if (!bp_.fonts_cjk.empty())
3974                 fontModule->cjkFontLE->setText(
3975                         toqstr(bp_.fonts_cjk));
3976         else
3977                 fontModule->cjkFontLE->setText(QString());
3978
3979         fontModule->microtypeCB->setChecked(bp_.use_microtype);
3980         fontModule->dashesCB->setChecked(!bp_.use_dash_ligatures);
3981
3982         fontModule->fontScCB->setChecked(bp_.fonts_expert_sc);
3983         fontModule->fontOsfCB->setChecked(bp_.fonts_old_figures);
3984         fontModule->scaleSansSB->setValue(bp_.fontsSansScale());
3985         fontModule->font_sf_scale = bp_.fonts_sans_scale[!bp_.useNonTeXFonts];
3986         fontModule->scaleTypewriterSB->setValue(bp_.fontsTypewriterScale());
3987         fontModule->font_tt_scale = bp_.fonts_typewriter_scale[!bp_.useNonTeXFonts];
3988
3989         nn = findToken(GuiDocument::fontfamilies, bp_.fonts_default_family);
3990         if (nn >= 0)
3991                 fontModule->fontsDefaultCO->setCurrentIndex(nn);
3992
3993         if (bp_.fontenc == "auto" || bp_.fontenc == "default") {
3994                 fontModule->fontencCO->setCurrentIndex(
3995                         fontModule->fontencCO->findData(toqstr(bp_.fontenc)));
3996                 fontModule->fontencLE->setEnabled(false);
3997         } else {
3998                 fontModule->fontencCO->setCurrentIndex(
3999                                         fontModule->fontencCO->findData("custom"));
4000                 fontModule->fontencLE->setText(toqstr(bp_.fontenc));
4001         }
4002
4003         // Formats
4004         // This must be set _after_ fonts since updateDefaultFormat()
4005         // checks osFontsCB settings.
4006         // update combobox with formats
4007         updateDefaultFormat();
4008         int index = outputModule->defaultFormatCO->findData(toqstr(
4009                 bp_.default_output_format));
4010         // set to default if format is not found
4011         if (index == -1)
4012                 index = 0;
4013         outputModule->defaultFormatCO->setCurrentIndex(index);
4014
4015         outputModule->shellescapeCB->setChecked(bp_.shell_escape);
4016         outputModule->outputsyncCB->setChecked(bp_.output_sync);
4017         outputModule->synccustomCB->setEditText(toqstr(bp_.output_sync_macro));
4018
4019         outputModule->mathimgSB->setValue(bp_.html_math_img_scale);
4020         outputModule->mathoutCB->setCurrentIndex(bp_.html_math_output);
4021         outputModule->strictCB->setChecked(bp_.html_be_strict);
4022         outputModule->cssCB->setChecked(bp_.html_css_as_file);
4023
4024         outputModule->saveTransientPropertiesCB
4025                 ->setChecked(bp_.save_transient_properties);
4026
4027         // paper
4028         bool const extern_geometry =
4029                 documentClass().provides("geometry");
4030         int const psize = bp_.papersize;
4031         pageLayoutModule->papersizeCO->setCurrentIndex(psize);
4032         setCustomPapersize(!extern_geometry && psize == 1);
4033         pageLayoutModule->papersizeCO->setEnabled(!extern_geometry);
4034
4035         bool const landscape =
4036                 bp_.orientation == ORIENTATION_LANDSCAPE;
4037         pageLayoutModule->landscapeRB->setChecked(landscape);
4038         pageLayoutModule->portraitRB->setChecked(!landscape);
4039         pageLayoutModule->landscapeRB->setEnabled(!extern_geometry);
4040         pageLayoutModule->portraitRB->setEnabled(!extern_geometry);
4041
4042         pageLayoutModule->facingPagesCB->setChecked(
4043                 bp_.sides == TwoSides);
4044
4045         lengthToWidgets(pageLayoutModule->paperwidthLE,
4046                 pageLayoutModule->paperwidthUnitCO, bp_.paperwidth, default_unit);
4047         lengthToWidgets(pageLayoutModule->paperheightLE,
4048                 pageLayoutModule->paperheightUnitCO, bp_.paperheight, default_unit);
4049
4050         // margins
4051         Ui::MarginsUi * m = marginsModule;
4052
4053         setMargins();
4054
4055         lengthToWidgets(m->topLE, m->topUnit,
4056                 bp_.topmargin, default_unit);
4057
4058         lengthToWidgets(m->bottomLE, m->bottomUnit,
4059                 bp_.bottommargin, default_unit);
4060
4061         lengthToWidgets(m->innerLE, m->innerUnit,
4062                 bp_.leftmargin, default_unit);
4063
4064         lengthToWidgets(m->outerLE, m->outerUnit,
4065                 bp_.rightmargin, default_unit);
4066
4067         lengthToWidgets(m->headheightLE, m->headheightUnit,
4068                 bp_.headheight, default_unit);
4069
4070         lengthToWidgets(m->headsepLE, m->headsepUnit,
4071                 bp_.headsep, default_unit);
4072
4073         lengthToWidgets(m->footskipLE, m->footskipUnit,
4074                 bp_.footskip, default_unit);
4075
4076         lengthToWidgets(m->columnsepLE, m->columnsepUnit,
4077                 bp_.columnsep, default_unit);
4078
4079         // branches
4080         updateUnknownBranches();
4081         branchesModule->update(bp_);
4082
4083         // PDF support
4084         PDFOptions const & pdf = bp_.pdfoptions();
4085         pdfSupportModule->use_hyperrefGB->setChecked(pdf.use_hyperref);
4086         if (bp_.documentClass().provides("hyperref"))
4087                 pdfSupportModule->use_hyperrefGB->setTitle(qt_("C&ustomize Hyperref Options"));
4088         else
4089                 pdfSupportModule->use_hyperrefGB->setTitle(qt_("&Use Hyperref Support"));
4090         pdfSupportModule->titleLE->setText(toqstr(pdf.title));
4091         pdfSupportModule->authorLE->setText(toqstr(pdf.author));
4092         pdfSupportModule->subjectLE->setText(toqstr(pdf.subject));
4093         pdfSupportModule->keywordsLE->setText(toqstr(pdf.keywords));
4094
4095         pdfSupportModule->bookmarksGB->setChecked(pdf.bookmarks);
4096         pdfSupportModule->bookmarksnumberedCB->setChecked(pdf.bookmarksnumbered);
4097         pdfSupportModule->bookmarksopenGB->setChecked(pdf.bookmarksopen);
4098
4099         pdfSupportModule->bookmarksopenlevelSB->setValue(pdf.bookmarksopenlevel);
4100
4101         pdfSupportModule->breaklinksCB->setChecked(pdf.breaklinks);
4102         pdfSupportModule->pdfborderCB->setChecked(pdf.pdfborder);
4103         pdfSupportModule->pdfusetitleCB->setChecked(pdf.pdfusetitle);
4104         pdfSupportModule->colorlinksCB->setChecked(pdf.colorlinks);
4105
4106         nn = findToken(backref_opts, pdf.backref);
4107         if (nn >= 0)
4108                 pdfSupportModule->backrefCO->setCurrentIndex(nn);
4109
4110         pdfSupportModule->fullscreenCB->setChecked
4111                 (pdf.pagemode == pdf.pagemode_fullscreen);
4112
4113         pdfSupportModule->optionsLE->setText(
4114                 toqstr(pdf.quoted_options));
4115
4116         // Make sure that the bc is in the INITIAL state
4117         if (bc().policy().buttonStatus(ButtonPolicy::RESTORE))
4118                 bc().restore();
4119
4120         // clear changed branches cache
4121         changedBranches_.clear();
4122
4123         // reset trackers
4124         nonModuleChanged_ = false;
4125         shellescapeChanged_ = false;
4126 }
4127
4128
4129 void GuiDocument::saveDocDefault()
4130 {
4131         // we have to apply the params first
4132         applyView();
4133         saveAsDefault();
4134 }
4135
4136
4137 void GuiDocument::updateAvailableModules()
4138 {
4139         modules_av_model_.clear();
4140         list<modInfoStruct> modInfoList = getModuleInfo();
4141         // Sort names according to the locale
4142         modInfoList.sort([](modInfoStruct const & a, modInfoStruct const & b) {
4143                         return 0 < b.name.localeAwareCompare(a.name);
4144                 });
4145         int i = 0;
4146         for (modInfoStruct const & m : modInfoList) {
4147                 modules_av_model_.insertRow(i, m.name, m.id, m.description);
4148                 ++i;
4149         }
4150 }
4151
4152
4153 void GuiDocument::updateSelectedModules()
4154 {
4155         modules_sel_model_.clear();
4156         list<modInfoStruct> const selModList = getSelectedModules();
4157         int i = 0;
4158         for (modInfoStruct const & m : selModList) {
4159                 modules_sel_model_.insertRow(i, m.name, m.id, m.description);
4160                 ++i;
4161         }
4162 }
4163
4164
4165 void GuiDocument::updateIncludeonlys()
4166 {
4167         masterChildModule->childrenTW->clear();
4168         QString const no = qt_("No");
4169         QString const yes = qt_("Yes");
4170
4171         if (includeonlys_.empty()) {
4172                 masterChildModule->includeallRB->setChecked(true);
4173                 masterChildModule->childrenTW->setEnabled(false);
4174                 masterChildModule->maintainAuxCB->setEnabled(false);
4175         } else {
4176                 masterChildModule->includeonlyRB->setChecked(true);
4177                 masterChildModule->childrenTW->setEnabled(true);
4178                 masterChildModule->maintainAuxCB->setEnabled(true);
4179         }
4180         ListOfBuffers children = buffer().getChildren();
4181         ListOfBuffers::const_iterator it  = children.begin();
4182         ListOfBuffers::const_iterator end = children.end();
4183         bool has_unincluded = false;
4184         bool all_unincluded = true;
4185         for (; it != end; ++it) {
4186                 QTreeWidgetItem * item = new QTreeWidgetItem(masterChildModule->childrenTW);
4187                 // FIXME Unicode
4188                 string const name =
4189                         to_utf8(makeRelPath(from_utf8((*it)->fileName().absFileName()),
4190                                                         from_utf8(buffer().filePath())));
4191                 item->setText(0, toqstr(name));
4192                 item->setText(1, isChildIncluded(name) ? yes : no);
4193                 if (!isChildIncluded(name))
4194                         has_unincluded = true;
4195                 else
4196                         all_unincluded = false;
4197         }
4198         // Both if all childs are included and if none is included
4199         // is equal to "include all" (i.e., omit \includeonly).
4200         // Thus, reset the GUI.
4201         if (!has_unincluded || all_unincluded) {
4202                 masterChildModule->includeallRB->setChecked(true);
4203                 masterChildModule->childrenTW->setEnabled(false);
4204                 includeonlys_.clear();
4205         }
4206         // If all are included, we need to update again.
4207         if (!has_unincluded)
4208                 updateIncludeonlys();
4209 }
4210
4211
4212 bool GuiDocument::isBiblatex() const
4213 {
4214         QString const engine =
4215                 biblioModule->citeEngineCO->itemData(
4216                                 biblioModule->citeEngineCO->currentIndex()).toString();
4217
4218         // this can happen if the cite engine is unknown, which can happen
4219         // if one is using a file that came from someone else, etc. in that
4220         // case, we crash if we proceed.
4221         if (engine.isEmpty())
4222             return false;
4223
4224         return theCiteEnginesList[fromqstr(engine)]->getCiteFramework() == "biblatex";
4225 }
4226
4227
4228 void GuiDocument::updateDefaultBiblio(string const & style,
4229                                       string const & which)
4230 {
4231         QString const bibstyle = toqstr(style);
4232         biblioModule->defaultBiblioCO->clear();
4233
4234         int item_nr = -1;
4235
4236         if (isBiblatex()) {
4237                 if (which != "cbx") {
4238                         // First the bbx styles
4239                         biblioModule->biblatexBbxCO->clear();
4240                         QStringList str = texFileList("bbxFiles.lst");
4241                         // test whether we have a valid list, otherwise run rescan
4242                         if (str.isEmpty()) {
4243                                 rescanTexStyles("bbx");
4244                                 str = texFileList("bbxFiles.lst");
4245                         }
4246                         for (int i = 0; i != str.size(); ++i)
4247                                 str[i] = onlyFileName(str[i]);
4248                         // sort on filename only (no path)
4249                         str.sort();
4250
4251                         for (int i = 0; i != str.count(); ++i) {
4252                                 QString item = changeExtension(str[i], "");
4253                                 if (item == bibstyle)
4254                                         item_nr = i;
4255                                 biblioModule->biblatexBbxCO->addItem(item);
4256                         }
4257
4258                         if (item_nr == -1 && !bibstyle.isEmpty()) {
4259                                 biblioModule->biblatexBbxCO->addItem(bibstyle);
4260                                 item_nr = biblioModule->biblatexBbxCO->count() - 1;
4261                         }
4262
4263                         if (item_nr != -1)
4264                                 biblioModule->biblatexBbxCO->setCurrentIndex(item_nr);
4265                         else
4266                                 biblioModule->biblatexBbxCO->clearEditText();
4267                 }
4268
4269                 if (which != "bbx") {
4270                         // now the cbx styles
4271                         biblioModule->biblatexCbxCO->clear();
4272                         QStringList str = texFileList("cbxFiles.lst");
4273                         // test whether we have a valid list, otherwise run rescan
4274                         if (str.isEmpty()) {
4275                                 rescanTexStyles("cbx");
4276                                 str = texFileList("cbxFiles.lst");
4277                         }
4278                         for (int i = 0; i != str.size(); ++i)
4279                                 str[i] = onlyFileName(str[i]);
4280                         // sort on filename only (no path)
4281                         str.sort();
4282
4283                         for (int i = 0; i != str.count(); ++i) {
4284                                 QString item = changeExtension(str[i], "");
4285                                 if (item == bibstyle)
4286                                         item_nr = i;
4287                                 biblioModule->biblatexCbxCO->addItem(item);
4288                         }
4289
4290                         if (item_nr == -1 && !bibstyle.isEmpty()) {
4291                                 biblioModule->biblatexCbxCO->addItem(bibstyle);
4292                                 item_nr = biblioModule->biblatexCbxCO->count() - 1;
4293                         }
4294
4295                         if (item_nr != -1)
4296                                 biblioModule->biblatexCbxCO->setCurrentIndex(item_nr);
4297                         else
4298                                 biblioModule->biblatexCbxCO->clearEditText();
4299                 }
4300         } else {// BibTeX
4301                 biblioModule->biblatexBbxCO->clear();
4302                 biblioModule->biblatexCbxCO->clear();
4303                 QStringList str = texFileList("bstFiles.lst");
4304                 // test whether we have a valid list, otherwise run rescan
4305                 if (str.isEmpty()) {
4306                         rescanTexStyles("bst");
4307                         str = texFileList("bstFiles.lst");
4308                 }
4309                 for (int i = 0; i != str.size(); ++i)
4310                         str[i] = onlyFileName(str[i]);
4311                 // sort on filename only (no path)
4312                 str.sort();
4313
4314                 for (int i = 0; i != str.count(); ++i) {
4315                         QString item = changeExtension(str[i], "");
4316                         if (item == bibstyle)
4317                                 item_nr = i;
4318                         biblioModule->defaultBiblioCO->addItem(item);
4319                 }
4320
4321                 if (item_nr == -1 && !bibstyle.isEmpty()) {
4322                         biblioModule->defaultBiblioCO->addItem(bibstyle);
4323                         item_nr = biblioModule->defaultBiblioCO->count() - 1;
4324                 }
4325
4326                 if (item_nr != -1)
4327                         biblioModule->defaultBiblioCO->setCurrentIndex(item_nr);
4328                 else
4329                         biblioModule->defaultBiblioCO->clearEditText();
4330         }
4331
4332         updateResetDefaultBiblio();
4333 }
4334
4335
4336 void GuiDocument::updateResetDefaultBiblio()
4337 {
4338         QString const engine =
4339                 biblioModule->citeEngineCO->itemData(
4340                                 biblioModule->citeEngineCO->currentIndex()).toString();
4341         CiteEngineType const cet =
4342                 CiteEngineType(biblioModule->citeStyleCO->itemData(
4343                                                           biblioModule->citeStyleCO->currentIndex()).toInt());
4344
4345         string const defbib = theCiteEnginesList[fromqstr(engine)]->getDefaultBiblio(cet);
4346         if (isBiblatex()) {
4347                 QString const bbx = biblioModule->biblatexBbxCO->currentText();
4348                 QString const cbx = biblioModule->biblatexCbxCO->currentText();
4349                 biblioModule->resetCbxPB->setEnabled(defbib != fromqstr(cbx));
4350                 biblioModule->resetBbxPB->setEnabled(defbib != fromqstr(bbx));
4351                 biblioModule->matchBbxPB->setEnabled(bbx != cbx && !cbx.isEmpty()
4352                         && biblioModule->biblatexBbxCO->findText(cbx) != -1);
4353         } else
4354                 biblioModule->resetDefaultBiblioPB->setEnabled(
4355                         defbib != fromqstr(biblioModule->defaultBiblioCO->currentText()));
4356 }
4357
4358
4359 void GuiDocument::matchBiblatexStyles()
4360 {
4361         updateDefaultBiblio(fromqstr(biblioModule->biblatexCbxCO->currentText()), "bbx");
4362         biblioChanged();
4363 }
4364
4365
4366 void GuiDocument::updateContents()
4367 {
4368         // Nothing to do here as the document settings is not cursor dependant.
4369         return;
4370 }
4371
4372
4373 void GuiDocument::useClassDefaults()
4374 {
4375         if (buttonBox->button(QDialogButtonBox::Apply)->isEnabled()) {
4376                 int const ret = Alert::prompt(_("Unapplied changes"),
4377                                 _("Some changes in the dialog were not yet applied.\n"
4378                                   "If you do not apply now, they will be lost after this action."),
4379                                 1, 1, _("&Apply"), _("&Dismiss"));
4380                 if (ret == 0)
4381                         applyView();
4382         }
4383
4384         int idx = latexModule->classCO->currentIndex();
4385         string const classname = fromqstr(latexModule->classCO->getData(idx));
4386         if (!bp_.setBaseClass(classname, buffer().layoutPos())) {
4387                 Alert::error(_("Error"), _("Unable to set document class."));
4388                 return;
4389         }
4390         bp_.useClassDefaults();
4391         paramsToDialog();
4392         changed();
4393 }
4394
4395
4396 void GuiDocument::setLayoutComboByIDString(string const & idString)
4397 {
4398         if (!latexModule->classCO->set(toqstr(idString)))
4399                 Alert::warning(_("Can't set layout!"),
4400                         bformat(_("Unable to set layout for ID: %1$s"), from_utf8(idString)));
4401 }
4402
4403
4404 bool GuiDocument::isValid()
4405 {
4406         return
4407                 validateListingsParameters().isEmpty() &&
4408                 localLayout->isValid() &&
4409                 !localLayout->editing() &&
4410                 !preambleModule->editing() &&
4411                 (
4412                         // if we're asking for skips between paragraphs
4413                         !textLayoutModule->skipRB->isChecked() ||
4414                         // then either we haven't chosen custom
4415                         textLayoutModule->skipCO->currentIndex() != 3 ||
4416                         // or else a length has been given
4417                         !textLayoutModule->skipLE->text().isEmpty()
4418                 ) &&
4419                 (
4420                         // if we're asking for indentation
4421                         !textLayoutModule->indentRB->isChecked() ||
4422                         // then either we haven't chosen custom
4423                         textLayoutModule->indentCO->currentIndex() != 1 ||
4424                         // or else a length has been given
4425                         !textLayoutModule->indentLE->text().isEmpty()
4426                 ) &&
4427                 (
4428                         // if we're asking for math indentation
4429                         !mathsModule->MathIndentCB->isChecked() ||
4430                         // then either we haven't chosen custom
4431                         mathsModule->MathIndentCO->currentIndex() != 1 ||
4432                         // or else a length has been given
4433                         !mathsModule->MathIndentLE->text().isEmpty()
4434                 );
4435 }
4436
4437
4438 char const * const GuiDocument::fontfamilies[5] = {
4439         "default", "rmdefault", "sfdefault", "ttdefault", ""
4440 };
4441
4442
4443 char const * GuiDocument::fontfamilies_gui[5] = {
4444         N_("Default"), N_("Roman"), N_("Sans Serif"), N_("Typewriter"), ""
4445 };
4446
4447
4448 bool GuiDocument::initialiseParams(string const &)
4449 {
4450         BufferView const * view = bufferview();
4451         if (!view) {
4452                 bp_ = BufferParams();
4453                 paramsToDialog();
4454                 return true;
4455         }
4456         bp_ = view->buffer().params();
4457         loadModuleInfo();
4458         updateAvailableModules();
4459         //FIXME It'd be nice to make sure here that the selected
4460         //modules are consistent: That required modules are actually
4461         //selected, and that we don't have conflicts. If so, we could
4462         //at least pop up a warning.
4463         paramsToDialog();
4464         return true;
4465 }
4466
4467
4468 void GuiDocument::clearParams()
4469 {
4470         bp_ = BufferParams();
4471 }
4472
4473
4474 BufferId GuiDocument::id() const
4475 {
4476         BufferView const * const view = bufferview();
4477         return view? &view->buffer() : 0;
4478 }
4479
4480
4481 list<GuiDocument::modInfoStruct> const & GuiDocument::getModuleInfo()
4482 {
4483         return moduleNames_;
4484 }
4485
4486
4487 list<GuiDocument::modInfoStruct> const
4488 GuiDocument::makeModuleInfo(LayoutModuleList const & mods)
4489 {
4490         list<modInfoStruct> mInfo;
4491         for (string const & name : mods) {
4492                 modInfoStruct m;
4493                 LyXModule const * const mod = theModuleList[name];
4494                 if (mod)
4495                         m = modInfo(*mod);
4496                 else {
4497                         m.id = name;
4498                         m.name = toqstr(name + " (") + qt_("Not Found") + toqstr(")");
4499                 }
4500                 mInfo.push_back(m);
4501         }
4502         return mInfo;
4503 }
4504
4505
4506 list<GuiDocument::modInfoStruct> const GuiDocument::getSelectedModules()
4507 {
4508         return makeModuleInfo(params().getModules());
4509 }
4510
4511
4512 list<GuiDocument::modInfoStruct> const GuiDocument::getProvidedModules()
4513 {
4514         return makeModuleInfo(params().baseClass()->providedModules());
4515 }
4516
4517
4518 DocumentClass const & GuiDocument::documentClass() const
4519 {
4520         return bp_.documentClass();
4521 }
4522
4523
4524 static void dispatch_bufferparams(Dialog const & dialog,
4525         BufferParams const & bp, FuncCode lfun, Buffer const * buf)
4526 {
4527         ostringstream ss;
4528         ss << "\\begin_header\n";
4529         bp.writeFile(ss, buf);
4530         ss << "\\end_header\n";
4531         dialog.dispatch(FuncRequest(lfun, ss.str()));
4532 }
4533
4534
4535 void GuiDocument::dispatchParams()
4536 {
4537         // We need a non-const buffer object.
4538         Buffer & buf = const_cast<BufferView *>(bufferview())->buffer();
4539         // There may be several undo records; group them (bug #8998)
4540         // This handles undo groups automagically
4541         UndoGroupHelper ugh(&buf);
4542
4543         // This must come first so that a language change is correctly noticed
4544         setLanguage();
4545
4546         // We need to load the master before we formally update the params,
4547         // since otherwise we run updateBuffer, etc, before the child's master
4548         // has been set.
4549         if (!params().master.empty()) {
4550                 FileName const master_file = support::makeAbsPath(params().master,
4551                            support::onlyPath(buffer().absFileName()));
4552                 if (isLyXFileName(master_file.absFileName())) {
4553                         Buffer * master = checkAndLoadLyXFile(master_file);
4554                         if (master) {
4555                                 if (master->isChild(const_cast<Buffer *>(&buffer())))
4556                                         const_cast<Buffer &>(buffer()).setParent(master);
4557                                 else
4558                                         Alert::warning(_("Assigned master does not include this file"),
4559                                                 bformat(_("You must include this file in the document\n"
4560                                                           "'%1$s' in order to use the master document\n"
4561                                                           "feature."), from_utf8(params().master)));
4562                         } else
4563                                 Alert::warning(_("Could not load master"),
4564                                                 bformat(_("The master document '%1$s'\n"
4565                                                            "could not be loaded."),
4566                                                            from_utf8(params().master)));
4567                 }
4568         }
4569
4570         // Apply the BufferParams. Note that this will set the base class
4571         // and then update the buffer's layout.
4572         dispatch_bufferparams(*this, params(), LFUN_BUFFER_PARAMS_APPLY, &buffer());
4573
4574         // Generate the colours requested by each new branch.
4575         BranchList & branchlist = params().branchlist();
4576         if (!branchlist.empty()) {
4577                 BranchList::const_iterator it = branchlist.begin();
4578                 BranchList::const_iterator const end = branchlist.end();
4579                 for (; it != end; ++it) {
4580                         docstring const & current_branch = it->branch();
4581                         Branch const * branch = branchlist.find(current_branch);
4582                         string const x11hexname = X11hexname(branch->color());
4583                         // display the new color
4584                         docstring const str = current_branch + ' ' + from_ascii(x11hexname);
4585                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
4586                 }
4587         }
4588         // rename branches in the document
4589         executeBranchRenaming();
4590         // and clear changed branches cache
4591         changedBranches_.clear();
4592
4593         // Generate the colours requested by indices.
4594         IndicesList & indiceslist = params().indiceslist();
4595         if (!indiceslist.empty()) {
4596                 IndicesList::const_iterator it = indiceslist.begin();
4597                 IndicesList::const_iterator const end = indiceslist.end();
4598                 for (; it != end; ++it) {
4599                         docstring const & current_index = it->shortcut();
4600                         Index const * index = indiceslist.findShortcut(current_index);
4601                         string const x11hexname = X11hexname(index->color());
4602                         // display the new color
4603                         docstring const str = current_index + ' ' + from_ascii(x11hexname);
4604                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
4605                 }
4606         }
4607         // FIXME LFUN
4608         // If we used an LFUN, we would not need these two lines:
4609         BufferView * bv = const_cast<BufferView *>(bufferview());
4610         bv->processUpdateFlags(Update::Force | Update::FitCursor);
4611 }
4612
4613
4614 void GuiDocument::setLanguage() const
4615 {
4616         Language const * const newL = bp_.language;
4617         if (buffer().params().language == newL)
4618                 return;
4619
4620         string const & lang_name = newL->lang();
4621         dispatch(FuncRequest(LFUN_BUFFER_LANGUAGE, lang_name));
4622 }
4623
4624
4625 void GuiDocument::saveAsDefault() const
4626 {
4627         dispatch_bufferparams(*this, params(), LFUN_BUFFER_SAVE_AS_DEFAULT, &buffer());
4628 }
4629
4630
4631 bool GuiDocument::providesOSF(QString const & font) const
4632 {
4633         if (fontModule->osFontsCB->isChecked())
4634                 // FIXME: we should check if the fonts really
4635                 // have OSF support. But how?
4636                 return true;
4637         return theLaTeXFonts().getLaTeXFont(
4638                                 qstring_to_ucs4(font)).providesOSF(ot1(),
4639                                                                    completeFontset(),
4640                                                                    noMathFont());
4641 }
4642
4643
4644 bool GuiDocument::providesSC(QString const & font) const
4645 {
4646         if (fontModule->osFontsCB->isChecked())
4647                 return false;
4648         return theLaTeXFonts().getLaTeXFont(
4649                                 qstring_to_ucs4(font)).providesSC(ot1(),
4650                                                                   completeFontset(),
4651                                                                   noMathFont());
4652 }
4653
4654
4655 bool GuiDocument::providesScale(QString const & font) const
4656 {
4657         if (fontModule->osFontsCB->isChecked())
4658                 return true;
4659         return theLaTeXFonts().getLaTeXFont(
4660                                 qstring_to_ucs4(font)).providesScale(ot1(),
4661                                                                      completeFontset(),
4662                                                                      noMathFont());
4663 }
4664
4665
4666 bool GuiDocument::providesNoMath(QString const & font) const
4667 {
4668         if (fontModule->osFontsCB->isChecked())
4669                 return false;
4670         return theLaTeXFonts().getLaTeXFont(
4671                                 qstring_to_ucs4(font)).providesNoMath(ot1(),
4672                                                                       completeFontset());
4673 }
4674
4675
4676 bool GuiDocument::hasMonolithicExpertSet(QString const & font) const
4677 {
4678         if (fontModule->osFontsCB->isChecked())
4679                 return false;
4680         return theLaTeXFonts().getLaTeXFont(
4681                                 qstring_to_ucs4(font)).hasMonolithicExpertSet(ot1(),
4682                                                                               completeFontset(),
4683                                                                               noMathFont());
4684 }
4685
4686
4687 //static
4688 GuiDocument::modInfoStruct GuiDocument::modInfo(LyXModule const & mod)
4689 {
4690         // FIXME Unicode: docstrings would be better for these parameters but this
4691         // change requires a lot of others
4692         modInfoStruct m;
4693         m.id = mod.getID();
4694         m.name = toqstr(translateIfPossible(from_utf8(mod.getName())));
4695         QString desc = toqstr(translateIfPossible(from_utf8(mod.getDescription())));
4696         // Find the first sentence of the description
4697         QTextBoundaryFinder bf(QTextBoundaryFinder::Sentence, desc);
4698         int pos = bf.toNextBoundary();
4699         if (pos > 0)
4700                 desc.truncate(pos);
4701         QString modulename = QString(qt_("(Module name: %1)")).arg(toqstr(m.id));
4702         // Tooltip is the desc followed by the module name
4703         m.description = QString("%1<i>%2</i>")
4704                 .arg(desc.isEmpty() ? QString() : QString("<p>%1</p>").arg(desc),
4705                      modulename);
4706         return m;
4707 }
4708
4709
4710 void GuiDocument::loadModuleInfo()
4711 {
4712         moduleNames_.clear();
4713         for (LyXModule const & mod : theModuleList)
4714                 if (mod.category().substr(0, 8) != "Citation")
4715                         moduleNames_.push_back(modInfo(mod));
4716 }
4717
4718
4719 void GuiDocument::updateUnknownBranches()
4720 {
4721         if (!bufferview())
4722                 return;
4723         list<docstring> used_branches;
4724         buffer().getUsedBranches(used_branches);
4725         list<docstring>::const_iterator it = used_branches.begin();
4726         QStringList unknown_branches;
4727         for (; it != used_branches.end() ; ++it) {
4728                 if (!buffer().params().branchlist().find(*it))
4729                         unknown_branches.append(toqstr(*it));
4730         }
4731         branchesModule->setUnknownBranches(unknown_branches);
4732 }
4733
4734
4735 void GuiDocument::branchesRename(docstring const & oldname, docstring const & newname)
4736 {
4737         map<docstring, docstring>::iterator it = changedBranches_.begin();
4738         for (; it != changedBranches_.end() ; ++it) {
4739                 if (it->second == oldname) {
4740                         // branch has already been renamed
4741                         it->second = newname;
4742                         return;
4743                 }
4744         }
4745         // store new name
4746         changedBranches_[oldname] = newname;
4747 }
4748
4749
4750 void GuiDocument::executeBranchRenaming() const
4751 {
4752         map<docstring, docstring>::const_iterator it = changedBranches_.begin();
4753         for (; it != changedBranches_.end() ; ++it) {
4754                 docstring const arg = '"' + it->first + '"' + " " + '"' + it->second + '"';
4755                 dispatch(FuncRequest(LFUN_BRANCHES_RENAME, arg));
4756         }
4757 }
4758
4759
4760 void GuiDocument::allPackagesAuto()
4761 {
4762         allPackages(1);
4763 }
4764
4765
4766 void GuiDocument::allPackagesAlways()
4767 {
4768         allPackages(2);
4769 }
4770
4771
4772 void GuiDocument::allPackagesNot()
4773 {
4774         allPackages(3);
4775 }
4776
4777
4778 void GuiDocument::allPackages(int col)
4779 {
4780         for (int row = 0; row < mathsModule->packagesTW->rowCount(); ++row) {
4781                 QRadioButton * rb =
4782                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, col)->layout()->itemAt(0)->widget();
4783                 rb->setChecked(true);
4784         }
4785 }
4786
4787
4788 Dialog * createGuiDocument(GuiView & lv) { return new GuiDocument(lv); }
4789
4790
4791 } // namespace frontend
4792 } // namespace lyx
4793
4794 #include "moc_GuiDocument.cpp"