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