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