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