]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiDocument.cpp
Read line edit label
[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) [default]"), 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                         // If we force to switch fontspec on, store
2195                         // current state (#8717)
2196                         if (fontModule->osFontsCB->isEnabled())
2197                                 forced_fontspec_activation =
2198                                         !fontModule->osFontsCB->isChecked();
2199                         fontModule->osFontsCB->setChecked(true);
2200                         fontModule->osFontsCB->setEnabled(false);
2201         }
2202         else {
2203                 fontModule->osFontsCB->setEnabled(true);
2204                 // If we have forced to switch fontspec on,
2205                 // restore previous state (#8717)
2206                 if (forced_fontspec_activation)
2207                         fontModule->osFontsCB->setChecked(false);
2208                 forced_fontspec_activation = false;
2209         }
2210
2211         // set appropriate quotation mark style
2212         updateQuoteStyles(true);
2213 }
2214
2215
2216 void GuiDocument::osFontsChanged(bool nontexfonts)
2217 {
2218         bool const tex_fonts = !nontexfonts;
2219         // store current fonts
2220         QString const font_roman = fontModule->fontsRomanCO->itemData(
2221                         fontModule->fontsRomanCO->currentIndex()).toString();
2222         QString const font_sans = fontModule->fontsSansCO->itemData(
2223                         fontModule->fontsSansCO->currentIndex()).toString();
2224         QString const font_typewriter = fontModule->fontsTypewriterCO->itemData(
2225                         fontModule->fontsTypewriterCO->currentIndex()).toString();
2226         QString const font_math = fontModule->fontsMathCO->itemData(
2227                         fontModule->fontsMathCO->currentIndex()).toString();
2228         int const font_sf_scale = fontModule->scaleSansSB->value();
2229         int const font_tt_scale = fontModule->scaleTypewriterSB->value();
2230
2231         updateFontlist();
2232         // store default format
2233         QString const dformat = outputModule->defaultFormatCO->itemData(
2234                 outputModule->defaultFormatCO->currentIndex()).toString();
2235         updateDefaultFormat();
2236         // try to restore default format
2237         int index = outputModule->defaultFormatCO->findData(dformat);
2238         // set to default if format is not found
2239         if (index == -1)
2240                 index = 0;
2241         outputModule->defaultFormatCO->setCurrentIndex(index);
2242
2243         // try to restore fonts which were selected two toggles ago
2244         index = fontModule->fontsRomanCO->findData(fontModule->font_roman);
2245         if (index != -1)
2246                 fontModule->fontsRomanCO->setCurrentIndex(index);
2247         index = fontModule->fontsSansCO->findData(fontModule->font_sans);
2248         if (index != -1)
2249                 fontModule->fontsSansCO->setCurrentIndex(index);
2250         index = fontModule->fontsTypewriterCO->findData(fontModule->font_typewriter);
2251         if (index != -1)
2252                 fontModule->fontsTypewriterCO->setCurrentIndex(index);
2253         index = fontModule->fontsMathCO->findData(fontModule->font_math);
2254         if (index != -1)
2255                 fontModule->fontsMathCO->setCurrentIndex(index);
2256         // save fonts for next next toggle
2257         fontModule->font_roman = font_roman;
2258         fontModule->font_sans = font_sans;
2259         fontModule->font_typewriter = font_typewriter;
2260         fontModule->font_math = font_math;
2261         fontModule->font_sf_scale = font_sf_scale;
2262         fontModule->font_tt_scale = font_tt_scale;
2263
2264         langModule->customEncodingCO->setEnabled(tex_fonts &&
2265                 langModule->encodingCO->itemData(
2266                         langModule->encodingCO->currentIndex()).toString() == "custom");
2267         langModule->encodingCO->setEnabled(tex_fonts);
2268         langModule->noInputencCB->setEnabled(tex_fonts
2269                                              && langModule->encodingCO->currentIndex() < 2);
2270         if (!tex_fonts)
2271                 langModule->noInputencCB->setChecked(false);
2272
2273         fontModule->fontsDefaultCO->setEnabled(tex_fonts);
2274         fontModule->fontsDefaultLA->setEnabled(tex_fonts);
2275         fontModule->cjkFontLE->setEnabled(tex_fonts);
2276         fontModule->cjkFontLA->setEnabled(tex_fonts);
2277
2278         updateFontOptions();
2279
2280         fontModule->fontencLA->setEnabled(tex_fonts);
2281         fontModule->fontencCO->setEnabled(tex_fonts);
2282         if (!tex_fonts)
2283                 fontModule->fontencLE->setEnabled(false);
2284         else
2285                 fontencChanged(fontModule->fontencCO->currentIndex());
2286 }
2287
2288
2289 void GuiDocument::encodingSwitched(int i)
2290 {
2291         langModule->customEncodingCO->setEnabled(
2292                                 !fontModule->osFontsCB->isChecked()
2293                                 && langModule->encodingCO->itemData(i).toString() == "custom");
2294         langModule->noInputencCB->setEnabled(!fontModule->osFontsCB->isChecked()
2295                                              && langModule->encodingCO->currentIndex() < 2);
2296         if (!langModule->noInputencCB->isEnabled())
2297                 langModule->noInputencCB->setChecked(false);
2298
2299 }
2300
2301
2302 void GuiDocument::mathFontChanged(int)
2303 {
2304         updateFontOptions();
2305 }
2306
2307 void GuiDocument::fontOsfToggled(bool state)
2308 {
2309         if (fontModule->osFontsCB->isChecked())
2310                 return;
2311         QString font = fontModule->fontsRomanCO->itemData(
2312                         fontModule->fontsRomanCO->currentIndex()).toString();
2313         if (hasMonolithicExpertSet(font))
2314                 fontModule->fontScCB->setChecked(state);
2315 }
2316
2317
2318 void GuiDocument::fontScToggled(bool state)
2319 {
2320         if (fontModule->osFontsCB->isChecked())
2321                 return;
2322         QString font = fontModule->fontsRomanCO->itemData(
2323                         fontModule->fontsRomanCO->currentIndex()).toString();
2324         if (hasMonolithicExpertSet(font))
2325                 fontModule->fontOsfCB->setChecked(state);
2326 }
2327
2328
2329 void GuiDocument::updateFontOptions()
2330 {
2331         bool const tex_fonts = !fontModule->osFontsCB->isChecked();
2332         QString font;
2333         if (tex_fonts)
2334                 font = fontModule->fontsSansCO->itemData(
2335                                 fontModule->fontsSansCO->currentIndex()).toString();
2336         bool scaleable = providesScale(font);
2337         fontModule->scaleSansSB->setEnabled(scaleable);
2338         fontModule->scaleSansLA->setEnabled(scaleable);
2339         if (tex_fonts)
2340                 font = fontModule->fontsTypewriterCO->itemData(
2341                                 fontModule->fontsTypewriterCO->currentIndex()).toString();
2342         scaleable = providesScale(font);
2343         fontModule->scaleTypewriterSB->setEnabled(scaleable);
2344         fontModule->scaleTypewriterLA->setEnabled(scaleable);
2345         if (tex_fonts)
2346                 font = fontModule->fontsRomanCO->itemData(
2347                                 fontModule->fontsRomanCO->currentIndex()).toString();
2348         fontModule->fontScCB->setEnabled(providesSC(font));
2349         fontModule->fontOsfCB->setEnabled(providesOSF(font));
2350         updateMathFonts(font);
2351 }
2352
2353
2354 void GuiDocument::updateFontsize(string const & items, string const & sel)
2355 {
2356         fontModule->fontsizeCO->clear();
2357         fontModule->fontsizeCO->addItem(qt_("Default"));
2358
2359         for (int n = 0; !token(items,'|',n).empty(); ++n)
2360                 fontModule->fontsizeCO->
2361                         addItem(toqstr(token(items,'|',n)));
2362
2363         for (int n = 0; n < fontModule->fontsizeCO->count(); ++n) {
2364                 if (fromqstr(fontModule->fontsizeCO->itemText(n)) == sel) {
2365                         fontModule->fontsizeCO->setCurrentIndex(n);
2366                         break;
2367                 }
2368         }
2369 }
2370
2371
2372 bool GuiDocument::ot1() const
2373 {
2374         QString const fontenc =
2375                 fontModule->fontencCO->itemData(fontModule->fontencCO->currentIndex()).toString();
2376         int const i = langModule->languageCO->currentIndex();
2377         if (i == -1)
2378                 return false;
2379         QString const langname = langModule->languageCO->itemData(i).toString();
2380         Language const * newlang = lyx::languages.getLanguage(fromqstr(langname));
2381         return (fontenc == "default"
2382                 || (fontenc == "auto" && newlang->fontenc(buffer().params()) == "OT1")
2383                 || (fontenc == "custom" && fontModule->fontencLE->text() == "OT1"));
2384 }
2385
2386
2387 bool GuiDocument::completeFontset() const
2388 {
2389         return (fontModule->fontsSansCO->itemData(
2390                         fontModule->fontsSansCO->currentIndex()).toString() == "default"
2391                 && fontModule->fontsSansCO->itemData(
2392                         fontModule->fontsTypewriterCO->currentIndex()).toString() == "default");
2393 }
2394
2395
2396 bool GuiDocument::noMathFont() const
2397 {
2398         return (fontModule->fontsMathCO->itemData(
2399                 fontModule->fontsMathCO->currentIndex()).toString() == "default");
2400 }
2401
2402
2403 void GuiDocument::updateTexFonts()
2404 {
2405         LaTeXFonts::TexFontMap texfontmap = theLaTeXFonts().getLaTeXFonts();
2406
2407         LaTeXFonts::TexFontMap::const_iterator it = texfontmap.begin();
2408         LaTeXFonts::TexFontMap::const_iterator end = texfontmap.end();
2409         for (; it != end; ++it) {
2410                 LaTeXFont lf = it->second;
2411                 if (lf.name().empty()) {
2412                         LYXERR0("Error: Unnamed font: " << it->first);
2413                         continue;
2414                 }
2415                 docstring const family = lf.family();
2416                 docstring guiname = translateIfPossible(lf.guiname());
2417                 if (!lf.available(ot1(), noMathFont()))
2418                         guiname += _(" (not installed)");
2419                 if (family == "rm")
2420                         rmfonts_.insert(toqstr(guiname), toqstr(it->first));
2421                 else if (family == "sf")
2422                         sffonts_.insert(toqstr(guiname), toqstr(it->first));
2423                 else if (family == "tt")
2424                         ttfonts_.insert(toqstr(guiname), toqstr(it->first));
2425                 else if (family == "math")
2426                         mathfonts_.insert(toqstr(guiname), toqstr(it->first));
2427         }
2428 }
2429
2430
2431 void GuiDocument::updateFontlist()
2432 {
2433         fontModule->fontsRomanCO->clear();
2434         fontModule->fontsSansCO->clear();
2435         fontModule->fontsTypewriterCO->clear();
2436         fontModule->fontsMathCO->clear();
2437
2438         // With fontspec (XeTeX, LuaTeX), we have access to all system fonts, but not the LaTeX fonts
2439         if (fontModule->osFontsCB->isChecked()) {
2440                 fontModule->fontsRomanCO->addItem(qt_("Default"), QString("default"));
2441                 fontModule->fontsSansCO->addItem(qt_("Default"), QString("default"));
2442                 fontModule->fontsTypewriterCO->addItem(qt_("Default"), QString("default"));
2443                 QString unimath = qt_("Non-TeX Fonts Default");
2444                 if (!LaTeXFeatures::isAvailable("unicode-math"))
2445                         unimath += qt_(" (not available)");
2446                 fontModule->fontsMathCO->addItem(qt_("Class Default (TeX Fonts)"), QString("auto"));
2447                 fontModule->fontsMathCO->addItem(unimath, QString("default"));
2448
2449                 QFontDatabase fontdb;
2450                 QStringList families(fontdb.families());
2451                 for (QStringList::Iterator it = families.begin(); it != families.end(); ++it) {
2452                         fontModule->fontsRomanCO->addItem(*it, *it);
2453                         fontModule->fontsSansCO->addItem(*it, *it);
2454                         fontModule->fontsTypewriterCO->addItem(*it, *it);
2455                 }
2456                 return;
2457         }
2458
2459         if (rmfonts_.empty())
2460                 updateTexFonts();
2461
2462         fontModule->fontsRomanCO->addItem(qt_("Default"), QString("default"));
2463         QMap<QString, QString>::const_iterator rmi = rmfonts_.constBegin();
2464         while (rmi != rmfonts_.constEnd()) {
2465                 fontModule->fontsRomanCO->addItem(rmi.key(), rmi.value());
2466                 ++rmi;
2467         }
2468
2469         fontModule->fontsSansCO->addItem(qt_("Default"), QString("default"));
2470         QMap<QString, QString>::const_iterator sfi = sffonts_.constBegin();
2471         while (sfi != sffonts_.constEnd()) {
2472                 fontModule->fontsSansCO->addItem(sfi.key(), sfi.value());
2473                 ++sfi;
2474         }
2475
2476         fontModule->fontsTypewriterCO->addItem(qt_("Default"), QString("default"));
2477         QMap<QString, QString>::const_iterator tti = ttfonts_.constBegin();
2478         while (tti != ttfonts_.constEnd()) {
2479                 fontModule->fontsTypewriterCO->addItem(tti.key(), tti.value());
2480                 ++tti;
2481         }
2482
2483         fontModule->fontsMathCO->addItem(qt_("Automatic"), QString("auto"));
2484         fontModule->fontsMathCO->addItem(qt_("Class Default"), QString("default"));
2485         QMap<QString, QString>::const_iterator mmi = mathfonts_.constBegin();
2486         while (mmi != mathfonts_.constEnd()) {
2487                 fontModule->fontsMathCO->addItem(mmi.key(), mmi.value());
2488                 ++mmi;
2489         }
2490 }
2491
2492
2493 void GuiDocument::fontencChanged(int item)
2494 {
2495         fontModule->fontencLE->setEnabled(
2496                 fontModule->fontencCO->itemData(item).toString() == "custom");
2497         // The availability of TeX fonts depends on the font encoding
2498         updateTexFonts();
2499         updateFontOptions();
2500 }
2501
2502
2503 void GuiDocument::updateMathFonts(QString const & rm)
2504 {
2505         if (fontModule->osFontsCB->isChecked())
2506                 return;
2507         QString const math =
2508                 fontModule->fontsMathCO->itemData(fontModule->fontsMathCO->currentIndex()).toString();
2509         int const i = fontModule->fontsMathCO->findData("default");
2510         if (providesNoMath(rm) && i == -1)
2511                 fontModule->fontsMathCO->insertItem(1, qt_("Class Default"), QString("default"));
2512         else if (!providesNoMath(rm) && i != -1) {
2513                 int const c = fontModule->fontsMathCO->currentIndex();
2514                 fontModule->fontsMathCO->removeItem(i);
2515                 if (c == i)
2516                         fontModule->fontsMathCO->setCurrentIndex(0);
2517         }
2518 }
2519
2520
2521 void GuiDocument::romanChanged(int item)
2522 {
2523         if (fontModule->osFontsCB->isChecked())
2524                 return;
2525         QString const font =
2526                 fontModule->fontsRomanCO->itemData(item).toString();
2527         fontModule->fontScCB->setEnabled(providesSC(font));
2528         fontModule->fontOsfCB->setEnabled(providesOSF(font));
2529         updateMathFonts(font);
2530 }
2531
2532
2533 void GuiDocument::sansChanged(int item)
2534 {
2535         if (fontModule->osFontsCB->isChecked())
2536                 return;
2537         QString const font =
2538                 fontModule->fontsSansCO->itemData(item).toString();
2539         bool scaleable = providesScale(font);
2540         fontModule->scaleSansSB->setEnabled(scaleable);
2541         fontModule->scaleSansLA->setEnabled(scaleable);
2542 }
2543
2544
2545 void GuiDocument::ttChanged(int item)
2546 {
2547         if (fontModule->osFontsCB->isChecked())
2548                 return;
2549         QString const font =
2550                 fontModule->fontsTypewriterCO->itemData(item).toString();
2551         bool scaleable = providesScale(font);
2552         fontModule->scaleTypewriterSB->setEnabled(scaleable);
2553         fontModule->scaleTypewriterLA->setEnabled(scaleable);
2554 }
2555
2556
2557 void GuiDocument::updatePagestyle(string const & items, string const & sel)
2558 {
2559         pagestyles.clear();
2560         pageLayoutModule->pagestyleCO->clear();
2561         pageLayoutModule->pagestyleCO->addItem(qt_("Default"));
2562
2563         for (int n = 0; !token(items, '|', n).empty(); ++n) {
2564                 string style = token(items, '|', n);
2565                 QString style_gui = qt_(style);
2566                 pagestyles.push_back(pair<string, QString>(style, style_gui));
2567                 pageLayoutModule->pagestyleCO->addItem(style_gui);
2568         }
2569
2570         if (sel == "default") {
2571                 pageLayoutModule->pagestyleCO->setCurrentIndex(0);
2572                 return;
2573         }
2574
2575         int nn = 0;
2576
2577         for (size_t i = 0; i < pagestyles.size(); ++i)
2578                 if (pagestyles[i].first == sel)
2579                         nn = pageLayoutModule->pagestyleCO->findText(pagestyles[i].second);
2580
2581         if (nn > 0)
2582                 pageLayoutModule->pagestyleCO->setCurrentIndex(nn);
2583 }
2584
2585
2586 void GuiDocument::browseLayout()
2587 {
2588         QString const label1 = qt_("Lay&outs");
2589         QString const dir1 = toqstr(lyxrc.document_path);
2590         QStringList const filter(qt_("LyX Layout (*.layout)"));
2591         QString file = browseRelToParent(QString(), bufferFilePath(),
2592                 qt_("Local layout file"), filter, false,
2593                 label1, dir1);
2594
2595         if (!file.endsWith(".layout"))
2596                 return;
2597
2598         FileName layoutFile = support::makeAbsPath(fromqstr(file),
2599                 fromqstr(bufferFilePath()));
2600
2601         int const ret = Alert::prompt(_("Local layout file"),
2602                 _("The layout file you have selected is a local layout\n"
2603                   "file, not one in the system or user directory.\n"
2604                   "Your document will not work with this layout if you\n"
2605                   "move the layout file to a different directory."),
2606                   1, 1, _("&Set Layout"), _("&Cancel"));
2607         if (ret == 1)
2608                 return;
2609
2610         // load the layout file
2611         LayoutFileList & bcl = LayoutFileList::get();
2612         string classname = layoutFile.onlyFileName();
2613         // this will update an existing layout if that layout has been loaded before.
2614         LayoutFileIndex name = support::onlyFileName(bcl.addLocalLayout(
2615                 classname.substr(0, classname.size() - 7),
2616                 layoutFile.onlyPath().absFileName()));
2617
2618         if (name.empty()) {
2619                 Alert::error(_("Error"),
2620                         _("Unable to read local layout file."));
2621                 return;
2622         }
2623
2624         const_cast<Buffer &>(buffer()).setLayoutPos(layoutFile.onlyPath().absFileName());
2625
2626         // do not trigger classChanged if there is no change.
2627         if (latexModule->classCO->currentText() == toqstr(name))
2628                 return;
2629
2630         // add to combo box
2631         bool const avail = latexModule->classCO->set(toqstr(name));
2632         if (!avail) {
2633                 LayoutFile const & tc = bcl[name];
2634                 docstring const guiname = translateIfPossible(from_utf8(tc.description()));
2635                 // tooltip sensu "KOMA-Script Article [Class 'scrartcl']"
2636                 QString tooltip = toqstr(bformat(_("%1$s [Class '%2$s']"), guiname, from_utf8(tc.latexname())));
2637                 tooltip += '\n' + qt_("This is a local layout file.");
2638                 latexModule->classCO->addItemSort(toqstr(tc.name()), toqstr(guiname),
2639                                                   toqstr(translateIfPossible(from_utf8(tc.category()))),
2640                                                   tooltip,
2641                                                   true, true, true, true);
2642                 latexModule->classCO->set(toqstr(name));
2643         }
2644
2645         classChanged();
2646 }
2647
2648
2649 void GuiDocument::browseMaster()
2650 {
2651         QString const title = qt_("Select master document");
2652         QString const dir1 = toqstr(lyxrc.document_path);
2653         QString const old = latexModule->childDocLE->text();
2654         QString const docpath = toqstr(support::onlyPath(buffer().absFileName()));
2655         QStringList const filter(qt_("LyX Files (*.lyx)"));
2656         QString file = browseRelToSub(old, docpath, title, filter, false,
2657                 qt_("D&ocuments"), toqstr(lyxrc.document_path));
2658
2659         if (!file.isEmpty())
2660                 latexModule->childDocLE->setText(file);
2661 }
2662
2663
2664 void GuiDocument::classChanged_adaptor()
2665 {
2666         const_cast<Buffer &>(buffer()).setLayoutPos(string());
2667         classChanged();
2668 }
2669
2670
2671 void GuiDocument::classChanged()
2672 {
2673         int idx = latexModule->classCO->currentIndex();
2674         if (idx < 0)
2675                 return;
2676         string const classname = fromqstr(latexModule->classCO->getData(idx));
2677
2678         if (buttonBox->button(QDialogButtonBox::Apply)->isEnabled()) {
2679                 int const ret = Alert::prompt(_("Unapplied changes"),
2680                                 _("Some changes in the dialog were not yet applied.\n"
2681                                 "If you do not apply now, they will be lost after this action."),
2682                                 1, 1, _("&Apply"), _("&Dismiss"));
2683                 if (ret == 0)
2684                         applyView();
2685         }
2686
2687         // We load the TextClass as soon as it is selected. This is
2688         // necessary so that other options in the dialog can be updated
2689         // according to the new class. Note, however, that, if you use
2690         // the scroll wheel when sitting on the combo box, we'll load a
2691         // lot of TextClass objects very quickly....
2692         if (!bp_.setBaseClass(classname, buffer().layoutPos())) {
2693                 Alert::error(_("Error"), _("Unable to set document class."));
2694                 return;
2695         }
2696         if (lyxrc.auto_reset_options)
2697                 bp_.useClassDefaults();
2698
2699         // With the introduction of modules came a distinction between the base
2700         // class and the document class. The former corresponds to the main layout
2701         // file; the latter is that plus the modules (or the document-specific layout,
2702         // or  whatever else there could be). Our parameters come from the document
2703         // class. So when we set the base class, we also need to recreate the document
2704         // class. Otherwise, we still have the old one.
2705         bp_.makeDocumentClass();
2706         paramsToDialog();
2707 }
2708
2709
2710 void GuiDocument::languagePackageChanged(int i)
2711 {
2712          langModule->languagePackageLE->setEnabled(
2713                 langModule->languagePackageCO->itemData(i).toString() == "custom");
2714 }
2715
2716
2717 void GuiDocument::biblioChanged()
2718 {
2719         biblioChanged_ = true;
2720         change_adaptor();
2721 }
2722
2723
2724 void GuiDocument::checkPossibleCiteEngines()
2725 {
2726         // Check if the class provides a specific engine,
2727         // and if so, enforce this.
2728         string force_engine;
2729         if (documentClass().provides("natbib")
2730             || documentClass().provides("natbib-internal"))
2731                 force_engine = "natbib";
2732         else if (documentClass().provides("jurabib"))
2733                 force_engine = "jurabib";
2734         else if (documentClass().provides("biblatex"))
2735                 force_engine = "biblatex";
2736         else if (documentClass().provides("biblatex-natbib"))
2737                 force_engine = "biblatex-natbib";
2738
2739         if (!force_engine.empty())
2740                 biblioModule->citeEngineCO->setCurrentIndex(
2741                         biblioModule->citeEngineCO->findData(toqstr(force_engine)));
2742         biblioModule->citeEngineCO->setEnabled(force_engine.empty());
2743 }
2744
2745
2746 void GuiDocument::rescanBibFiles()
2747 {
2748         if (isBiblatex())
2749                 rescanTexStyles("bbx cbx");
2750         else
2751                 rescanTexStyles("bst");
2752 }
2753
2754
2755 void GuiDocument::resetDefaultBibfile(string const & which)
2756 {
2757         QString const engine =
2758                 biblioModule->citeEngineCO->itemData(
2759                                 biblioModule->citeEngineCO->currentIndex()).toString();
2760
2761         CiteEngineType const cet =
2762                 CiteEngineType(biblioModule->citeStyleCO->itemData(
2763                                                           biblioModule->citeStyleCO->currentIndex()).toInt());
2764
2765         updateDefaultBiblio(theCiteEnginesList[fromqstr(engine)]->getDefaultBiblio(cet), which);
2766 }
2767
2768
2769 void GuiDocument::resetDefaultBbxBibfile()
2770 {
2771         resetDefaultBibfile("bbx");
2772 }
2773
2774
2775 void GuiDocument::resetDefaultCbxBibfile()
2776 {
2777         resetDefaultBibfile("cbx");
2778 }
2779
2780
2781 void GuiDocument::citeEngineChanged(int n)
2782 {
2783         QString const engine =
2784                 biblioModule->citeEngineCO->itemData(n).toString();
2785
2786         vector<string> const engs =
2787                 theCiteEnginesList[fromqstr(engine)]->getEngineType();
2788
2789         updateCiteStyles(engs);
2790         updateEngineDependends();
2791         resetDefaultBibfile();
2792         biblioChanged();
2793 }
2794
2795
2796 void GuiDocument::updateEngineDependends()
2797 {
2798         bool const biblatex = isBiblatex();
2799
2800         // These are only useful with BibTeX
2801         biblioModule->defaultBiblioCO->setEnabled(!biblatex);
2802         biblioModule->bibtexStyleLA->setEnabled(!biblatex);
2803         biblioModule->resetDefaultBiblioPB->setEnabled(!biblatex);
2804         biblioModule->bibtopicCB->setEnabled(!biblatex);
2805
2806         // These are only useful with Biblatex
2807         biblioModule->biblatexBbxCO->setEnabled(biblatex);
2808         biblioModule->biblatexBbxLA->setEnabled(biblatex);
2809         biblioModule->biblatexCbxCO->setEnabled(biblatex);
2810         biblioModule->biblatexCbxLA->setEnabled(biblatex);
2811         biblioModule->resetBbxPB->setEnabled(biblatex);
2812         biblioModule->resetCbxPB->setEnabled(biblatex);
2813         biblioModule->matchBbxPB->setEnabled(biblatex);
2814
2815         // These are useful with biblatex, jurabib and natbib
2816         QString const engine =
2817                 biblioModule->citeEngineCO->itemData(
2818                                 biblioModule->citeEngineCO->currentIndex()).toString();
2819         LyXCiteEngine const * ce = theCiteEnginesList[fromqstr(engine)];
2820
2821         bool const citepack = ce->requires("biblatex.sty") || ce->requires("jurabib.sty")
2822                         || ce->requires("natbib.sty");
2823         biblioModule->citePackageOptionsLE->setEnabled(citepack);
2824         biblioModule->citePackageOptionsL->setEnabled(citepack);
2825 }
2826
2827
2828 void GuiDocument::citeStyleChanged()
2829 {
2830         QString const engine =
2831                 biblioModule->citeEngineCO->itemData(
2832                                 biblioModule->citeEngineCO->currentIndex()).toString();
2833         QString const currentDef = isBiblatex() ?
2834                 biblioModule->biblatexBbxCO->currentText()
2835                 : biblioModule->defaultBiblioCO->currentText();
2836         if (theCiteEnginesList[fromqstr(engine)]->isDefaultBiblio(fromqstr(currentDef)))
2837                 resetDefaultBibfile();
2838
2839         biblioChanged();
2840 }
2841
2842
2843 void GuiDocument::bibtexChanged(int n)
2844 {
2845         biblioModule->bibtexOptionsLE->setEnabled(
2846                 biblioModule->bibtexCO->itemData(n).toString() != "default");
2847         biblioChanged();
2848 }
2849
2850
2851 void GuiDocument::updateCiteStyles(vector<string> const & engs, CiteEngineType const & sel)
2852 {
2853         biblioModule->citeStyleCO->clear();
2854
2855         vector<string>::const_iterator it  = engs.begin();
2856         vector<string>::const_iterator end = engs.end();
2857         for (; it != end; ++it) {
2858                 if (*it == "default")
2859                         biblioModule->citeStyleCO->addItem(qt_("Basic numerical"),
2860                                                            ENGINE_TYPE_DEFAULT);
2861                 else if (*it == "authoryear")
2862                         biblioModule->citeStyleCO->addItem(qt_("Author-year"),
2863                                                            ENGINE_TYPE_AUTHORYEAR);
2864                 else if (*it == "numerical")
2865                         biblioModule->citeStyleCO->addItem(qt_("Author-number"),
2866                                                            ENGINE_TYPE_NUMERICAL);
2867         }
2868         int i = biblioModule->citeStyleCO->findData(sel);
2869         if (biblioModule->citeStyleCO->findData(sel) == -1)
2870                 i = 0;
2871         biblioModule->citeStyleCO->setCurrentIndex(i);
2872
2873         biblioModule->citationStyleL->setEnabled(engs.size() > 1);
2874         biblioModule->citeStyleCO->setEnabled(engs.size() > 1);
2875 }
2876
2877
2878 void GuiDocument::updateEngineType(string const & items, CiteEngineType const & sel)
2879 {
2880         engine_types_.clear();
2881
2882         int nn = 0;
2883
2884         for (int n = 0; !token(items, '|', n).empty(); ++n) {
2885                 nn += 1;
2886                 string style = token(items, '|', n);
2887                 engine_types_.push_back(style);
2888         }
2889
2890         updateCiteStyles(engine_types_, sel);
2891 }
2892
2893
2894 namespace {
2895         // FIXME unicode
2896         // both of these should take a vector<docstring>
2897
2898         // This is an insanely complicated attempt to make this sort of thing
2899         // work with RTL languages.
2900         docstring formatStrVec(vector<string> const & v, docstring const & s)
2901         {
2902                 //this mess formats the list as "v[0], v[1], ..., [s] v[n]"
2903                 if (v.empty())
2904                         return docstring();
2905                 if (v.size() == 1)
2906                         return translateIfPossible(from_utf8(v[0]));
2907                 if (v.size() == 2) {
2908                         docstring retval = _("%1$s and %2$s");
2909                         retval = subst(retval, _("and"), s);
2910                         return bformat(retval, translateIfPossible(from_utf8(v[0])),
2911                                        translateIfPossible(from_utf8(v[1])));
2912                 }
2913                 // The idea here is to format all but the last two items...
2914                 int const vSize = v.size();
2915                 docstring t2 = _("%1$s, %2$s");
2916                 docstring retval = translateIfPossible(from_utf8(v[0]));
2917                 for (int i = 1; i < vSize - 2; ++i)
2918                         retval = bformat(t2, retval, translateIfPossible(from_utf8(v[i])));
2919                 //...and then to  plug them, and the last two, into this schema
2920                 docstring t = _("%1$s, %2$s, and %3$s");
2921                 t = subst(t, _("and"), s);
2922                 return bformat(t, retval, translateIfPossible(from_utf8(v[vSize - 2])),
2923                                translateIfPossible(from_utf8(v[vSize - 1])));
2924         }
2925
2926         vector<string> idsToNames(vector<string> const & idList)
2927         {
2928                 vector<string> retval;
2929                 vector<string>::const_iterator it  = idList.begin();
2930                 vector<string>::const_iterator end = idList.end();
2931                 for (; it != end; ++it) {
2932                         LyXModule const * const mod = theModuleList[*it];
2933                         if (!mod)
2934                                 retval.push_back(to_utf8(bformat(_("%1$s (unavailable)"),
2935                                                 translateIfPossible(from_utf8(*it)))));
2936                         else
2937                                 retval.push_back(mod->getName());
2938                 }
2939                 return retval;
2940         }
2941 } // end anonymous namespace
2942
2943
2944 void GuiDocument::modulesToParams(BufferParams & bp)
2945 {
2946         // update list of loaded modules
2947         bp.clearLayoutModules();
2948         int const srows = modules_sel_model_.rowCount();
2949         for (int i = 0; i < srows; ++i)
2950                 bp.addLayoutModule(modules_sel_model_.getIDString(i));
2951         updateSelectedModules();
2952
2953         // update the list of removed modules
2954         bp.clearRemovedModules();
2955         LayoutModuleList const & reqmods = bp.baseClass()->defaultModules();
2956         list<string>::const_iterator rit = reqmods.begin();
2957         list<string>::const_iterator ren = reqmods.end();
2958
2959         // check each of the default modules
2960         for (; rit != ren; ++rit) {
2961                 list<string>::const_iterator mit = bp.getModules().begin();
2962                 list<string>::const_iterator men = bp.getModules().end();
2963                 bool found = false;
2964                 for (; mit != men; ++mit) {
2965                         if (*rit == *mit) {
2966                                 found = true;
2967                                 break;
2968                         }
2969                 }
2970                 if (!found) {
2971                         // the module isn't present so must have been removed by the user
2972                         bp.addRemovedModule(*rit);
2973                 }
2974         }
2975 }
2976
2977 void GuiDocument::modulesChanged()
2978 {
2979         modulesToParams(bp_);
2980
2981         if (buttonBox->button(QDialogButtonBox::Apply)->isEnabled()
2982             && (nonModuleChanged_ || shellescapeChanged_)) {
2983                 int const ret = Alert::prompt(_("Unapplied changes"),
2984                                 _("Some changes in the dialog were not yet applied.\n"
2985                                 "If you do not apply now, they will be lost after this action."),
2986                                 1, 1, _("&Apply"), _("&Dismiss"));
2987                 if (ret == 0)
2988                         applyView();
2989         }
2990
2991         modulesChanged_ = true;
2992         bp_.makeDocumentClass();
2993         paramsToDialog();
2994         changed();
2995 }
2996
2997
2998 void GuiDocument::updateModuleInfo()
2999 {
3000         selectionManager->update();
3001
3002         //Module description
3003         bool const focus_on_selected = selectionManager->selectedFocused();
3004         QAbstractItemView * lv;
3005         bool category = false;
3006         if (focus_on_selected) {
3007                 lv = modulesModule->selectedLV;
3008                 category = true;
3009         } else
3010                 lv = modulesModule->availableLV;
3011         if (lv->selectionModel()->selectedIndexes().isEmpty()) {
3012                 modulesModule->infoML->document()->clear();
3013                 return;
3014         }
3015         QModelIndex const & idx = lv->selectionModel()->currentIndex();
3016
3017         if (!focus_on_selected
3018             && modules_av_model_.itemFromIndex(idx)->hasChildren()) {
3019                 // This is a category header
3020                 modulesModule->infoML->document()->clear();
3021                 return;
3022         }
3023
3024         string const modName = focus_on_selected ?
3025                                 modules_sel_model_.getIDString(idx.row())
3026                               : fromqstr(modules_av_model_.data(idx, Qt::UserRole).toString());
3027         docstring desc = getModuleDescription(modName);
3028
3029         LayoutModuleList const & provmods = bp_.baseClass()->providedModules();
3030         if (std::find(provmods.begin(), provmods.end(), modName) != provmods.end()) {
3031                 if (!desc.empty())
3032                         desc += "\n";
3033                 desc += _("Module provided by document class.");
3034         }
3035
3036         if (category) {
3037                 docstring cat = getModuleCategory(modName);
3038                 if (!cat.empty()) {
3039                         if (!desc.empty())
3040                                 desc += "\n";
3041                         desc += bformat(_("<p><b>Category:</b> %1$s.</p>"),
3042                                         translateIfPossible(cat));
3043                 }
3044         }
3045
3046         vector<string> pkglist = getPackageList(modName);
3047         docstring pkgdesc = formatStrVec(pkglist, _("and"));
3048         if (!pkgdesc.empty()) {
3049                 if (!desc.empty())
3050                         desc += "\n";
3051                 desc += bformat(_("<p><b>Package(s) required:</b> %1$s.</p>"), pkgdesc);
3052         }
3053
3054         pkglist = getRequiredList(modName);
3055         if (!pkglist.empty()) {
3056                 vector<string> const reqdescs = idsToNames(pkglist);
3057                 pkgdesc = formatStrVec(reqdescs, _("or"));
3058                 if (!desc.empty())
3059                         desc += "\n";
3060                 desc += bformat(_("<p><b>Modules required:</b> %1$s.</p>"), pkgdesc);
3061         }
3062
3063         pkglist = getExcludedList(modName);
3064         if (!pkglist.empty()) {
3065                 vector<string> const reqdescs = idsToNames(pkglist);
3066                 pkgdesc = formatStrVec(reqdescs, _( "and"));
3067                 if (!desc.empty())
3068                         desc += "\n";
3069                 desc += bformat(_("<p><b>Modules excluded:</b> %1$s.</p>"), pkgdesc);
3070         }
3071
3072         if (!desc.empty())
3073                 desc += "\n";
3074         desc += bformat(_("<p><b>Filename:</b> <tt>%1$s.module</tt>.</p>"), from_utf8(modName));
3075
3076         if (!isModuleAvailable(modName)) {
3077                 if (!desc.empty())
3078                         desc += "\n";
3079                 desc += _("<p><font color=red><b>WARNING: Some required packages are unavailable!</b></font></p>");
3080         }
3081
3082         modulesModule->infoML->document()->setHtml(toqstr(desc));
3083 }
3084
3085
3086 void GuiDocument::updateNumbering()
3087 {
3088         DocumentClass const & tclass = documentClass();
3089
3090         numberingModule->tocTW->setUpdatesEnabled(false);
3091         numberingModule->tocTW->clear();
3092
3093         int const depth = numberingModule->depthSL->value();
3094         int const toc = numberingModule->tocSL->value();
3095         QString const no = qt_("No");
3096         QString const yes = qt_("Yes");
3097         QTreeWidgetItem * item = 0;
3098
3099         DocumentClass::const_iterator lit = tclass.begin();
3100         DocumentClass::const_iterator len = tclass.end();
3101         for (; lit != len; ++lit) {
3102                 int const toclevel = lit->toclevel;
3103                 if (toclevel != Layout::NOT_IN_TOC && !lit->counter.empty()) {
3104                         item = new QTreeWidgetItem(numberingModule->tocTW);
3105                         item->setText(0, toqstr(translateIfPossible(lit->name())));
3106                         item->setText(1, (toclevel <= depth) ? yes : no);
3107                         item->setText(2, (toclevel <= toc) ? yes : no);
3108                 }
3109         }
3110
3111         numberingModule->tocTW->setUpdatesEnabled(true);
3112         numberingModule->tocTW->update();
3113 }
3114
3115
3116 void GuiDocument::getTableStyles()
3117 {
3118         // We look for lyx files in the subdirectory dir of
3119         //   1) user_lyxdir
3120         //   2) build_lyxdir (if not empty)
3121         //   3) system_lyxdir
3122         // in this order. Files with a given sub-hierarchy will
3123         // only be listed once.
3124         // We also consider i18n subdirectories and store them separately.
3125         QStringList dirs;
3126
3127         // The three locations to look at.
3128         string const user = addPath(package().user_support().absFileName(), "tabletemplates");
3129         string const build = addPath(package().build_support().absFileName(), "tabletemplates");
3130         string const system = addPath(package().system_support().absFileName(), "tabletemplates");
3131
3132         dirs << toqstr(user)
3133              << toqstr(build)
3134              << toqstr(system);
3135
3136         for (int i = 0; i < dirs.size(); ++i) {
3137                 QString const dir = dirs.at(i);
3138                 QDirIterator it(dir, QDir::Files, QDirIterator::Subdirectories);
3139                 while (it.hasNext()) {
3140                         QString fn = QFileInfo(it.next()).fileName();
3141                         if (!fn.endsWith(".lyx") || fn.contains("_1x"))
3142                                 continue;
3143                         QString data = fn.left(fn.lastIndexOf(".lyx"));
3144                         QString guiname = data;
3145                         guiname = toqstr(translateIfPossible(qstring_to_ucs4(guiname.replace('_', ' '))));
3146                         QString relpath = toqstr(makeRelPath(qstring_to_ucs4(fn),
3147                                                              qstring_to_ucs4(dir)));
3148                         if (textLayoutModule->tableStyleCO->findData(data) == -1)
3149                                 textLayoutModule->tableStyleCO->addItem(guiname, data);
3150                 }
3151         }
3152 }
3153
3154
3155 void GuiDocument::updateDefaultFormat()
3156 {
3157         if (!bufferview())
3158                 return;
3159         // make a copy in order to consider unapplied changes
3160         BufferParams param_copy = buffer().params();
3161         param_copy.useNonTeXFonts = fontModule->osFontsCB->isChecked();
3162         int const idx = latexModule->classCO->currentIndex();
3163         if (idx >= 0) {
3164                 string const classname = fromqstr(latexModule->classCO->getData(idx));
3165                 param_copy.setBaseClass(classname, buffer().layoutPos());
3166                 param_copy.makeDocumentClass(true);
3167         }
3168         outputModule->defaultFormatCO->blockSignals(true);
3169         outputModule->defaultFormatCO->clear();
3170         outputModule->defaultFormatCO->addItem(qt_("Default"),
3171                                 QVariant(QString("default")));
3172         FormatList const & formats =
3173                                 param_copy.exportableFormats(true);
3174         for (Format const * f : formats)
3175                 outputModule->defaultFormatCO->addItem
3176                         (toqstr(translateIfPossible(f->prettyname())),
3177                          QVariant(toqstr(f->name())));
3178         outputModule->defaultFormatCO->blockSignals(false);
3179 }
3180
3181
3182 bool GuiDocument::isChildIncluded(string const & child)
3183 {
3184         if (includeonlys_.empty())
3185                 return false;
3186         return (std::find(includeonlys_.begin(),
3187                           includeonlys_.end(), child) != includeonlys_.end());
3188 }
3189
3190
3191 void GuiDocument::applyView()
3192 {
3193         // preamble
3194         preambleModule->apply(bp_);
3195         localLayout->apply(bp_);
3196
3197         // date
3198         bp_.suppress_date = latexModule->suppressDateCB->isChecked();
3199         bp_.use_refstyle  = latexModule->refstyleCB->isChecked();
3200
3201         // biblio
3202         string const engine =
3203                 fromqstr(biblioModule->citeEngineCO->itemData(
3204                                 biblioModule->citeEngineCO->currentIndex()).toString());
3205         bp_.setCiteEngine(engine);
3206
3207         CiteEngineType const style = CiteEngineType(biblioModule->citeStyleCO->itemData(
3208                 biblioModule->citeStyleCO->currentIndex()).toInt());
3209         if (theCiteEnginesList[engine]->hasEngineType(style))
3210                 bp_.setCiteEngineType(style);
3211         else
3212                 bp_.setCiteEngineType(ENGINE_TYPE_DEFAULT);
3213
3214         bp_.splitbib(biblioModule->bibtopicCB->isChecked());
3215
3216         bp_.multibib = fromqstr(biblioModule->bibunitsCO->itemData(
3217                                 biblioModule->bibunitsCO->currentIndex()).toString());
3218
3219         bp_.setDefaultBiblioStyle(fromqstr(biblioModule->defaultBiblioCO->currentText()));
3220
3221         bp_.biblatex_bibstyle = fromqstr(biblioModule->biblatexBbxCO->currentText());
3222         bp_.biblatex_citestyle = fromqstr(biblioModule->biblatexCbxCO->currentText());
3223         bp_.biblio_opts = fromqstr(biblioModule->citePackageOptionsLE->text());
3224
3225         string const bibtex_command =
3226                 fromqstr(biblioModule->bibtexCO->itemData(
3227                         biblioModule->bibtexCO->currentIndex()).toString());
3228         string const bibtex_options =
3229                 fromqstr(biblioModule->bibtexOptionsLE->text());
3230         if (bibtex_command == "default" || bibtex_options.empty())
3231                 bp_.bibtex_command = bibtex_command;
3232         else
3233                 bp_.bibtex_command = bibtex_command + " " + bibtex_options;
3234
3235         if (biblioChanged_) {
3236                 buffer().invalidateBibinfoCache();
3237                 buffer().removeBiblioTempFiles();
3238         }
3239
3240         // Indices
3241         indicesModule->apply(bp_);
3242
3243         // language & quotes
3244         QString const encoding = langModule->encodingCO->itemData(
3245                                 langModule->encodingCO->currentIndex()).toString();
3246         if (encoding != "custom")
3247                 bp_.inputenc = fromqstr(encoding);
3248         else
3249                 bp_.inputenc = fromqstr(langModule->customEncodingCO->itemData(
3250                                         langModule->customEncodingCO->currentIndex()).toString());
3251         if (langModule->noInputencCB->isChecked()
3252             && (encoding == "auto-legacy" || encoding == "utf8"))
3253                 bp_.inputenc += "-plain";
3254
3255         bp_.quotes_style = (InsetQuotesParams::QuoteStyle) langModule->quoteStyleCO->itemData(
3256                 langModule->quoteStyleCO->currentIndex()).toInt();
3257         bp_.dynamic_quotes = langModule->dynamicQuotesCB->isChecked();
3258
3259         QString const langname = langModule->languageCO->itemData(
3260                 langModule->languageCO->currentIndex()).toString();
3261         Language const * newlang = lyx::languages.getLanguage(fromqstr(langname));
3262         Cursor & cur = const_cast<BufferView *>(bufferview())->cursor();
3263         // If current cursor language was the document language, then update it too.
3264         if (cur.current_font.language() == bp_.language) {
3265                 cur.current_font.setLanguage(newlang);
3266                 cur.real_current_font.setLanguage(newlang);
3267         }
3268         bp_.language = newlang;
3269
3270         QString const pack = langModule->languagePackageCO->itemData(
3271                 langModule->languagePackageCO->currentIndex()).toString();
3272         if (pack == "custom")
3273                 bp_.lang_package =
3274                         fromqstr(langModule->languagePackageLE->text());
3275         else
3276                 bp_.lang_package = fromqstr(pack);
3277
3278         //color
3279         bp_.backgroundcolor = set_backgroundcolor;
3280         bp_.isbackgroundcolor = is_backgroundcolor;
3281         bp_.fontcolor = set_fontcolor;
3282         bp_.isfontcolor = is_fontcolor;
3283         bp_.notefontcolor = set_notefontcolor;
3284         bp_.boxbgcolor = set_boxbgcolor;
3285
3286         // numbering
3287         if (bp_.documentClass().hasTocLevels()) {
3288                 bp_.tocdepth = numberingModule->tocSL->value();
3289                 bp_.secnumdepth = numberingModule->depthSL->value();
3290         }
3291         bp_.use_lineno = numberingModule->linenoCB->isChecked();
3292         bp_.lineno_opts = fromqstr(numberingModule->linenoLE->text());
3293
3294         // bullets
3295         bp_.user_defined_bullet(0) = bulletsModule->bullet(0);
3296         bp_.user_defined_bullet(1) = bulletsModule->bullet(1);
3297         bp_.user_defined_bullet(2) = bulletsModule->bullet(2);
3298         bp_.user_defined_bullet(3) = bulletsModule->bullet(3);
3299
3300         // packages
3301         bp_.graphics_driver =
3302                 tex_graphics[latexModule->psdriverCO->currentIndex()];
3303
3304         // text layout
3305         int idx = latexModule->classCO->currentIndex();
3306         if (idx >= 0) {
3307                 string const classname = fromqstr(latexModule->classCO->getData(idx));
3308                 bp_.setBaseClass(classname, buffer().layoutPos());
3309         }
3310
3311         // Modules
3312         modulesToParams(bp_);
3313
3314         // Math
3315         map<string, string> const & packages = BufferParams::auto_packages();
3316         for (map<string, string>::const_iterator it = packages.begin();
3317              it != packages.end(); ++it) {
3318                 QTableWidgetItem * item = mathsModule->packagesTW->findItems(toqstr(it->first), Qt::MatchExactly)[0];
3319                 if (!item)
3320                         continue;
3321                 int row = mathsModule->packagesTW->row(item);
3322
3323                 QRadioButton * rb =
3324                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 1)->layout()->itemAt(0)->widget();
3325                 if (rb->isChecked()) {
3326                         bp_.use_package(it->first, BufferParams::package_auto);
3327                         continue;
3328                 }
3329                 rb = (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 2)->layout()->itemAt(0)->widget();
3330                 if (rb->isChecked()) {
3331                         bp_.use_package(it->first, BufferParams::package_on);
3332                         continue;
3333                 }
3334                 rb = (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 3)->layout()->itemAt(0)->widget();
3335                 if (rb->isChecked())
3336                         bp_.use_package(it->first, BufferParams::package_off);
3337         }
3338         // if math is indented
3339         bp_.is_math_indent = mathsModule->MathIndentCB->isChecked();
3340         if (bp_.is_math_indent) {
3341                 // if formulas are indented
3342                 switch (mathsModule->MathIndentCO->currentIndex()) {
3343                 case 0:
3344                         bp_.setMathIndent(Length());
3345                         break;
3346                 case 1: {
3347                         Length mathindent(widgetsToLength(mathsModule->MathIndentLE,
3348                                                           mathsModule->MathIndentLengthCO));
3349                         bp_.setMathIndent(mathindent);
3350                         break;
3351                 }
3352                 default:
3353                         // this should never happen
3354                         bp_.setMathIndent(Length());
3355                         break;
3356                 }
3357         }
3358         switch (mathsModule->MathNumberingPosCO->currentIndex()) {
3359                 case 0:
3360                         bp_.math_numbering_side = BufferParams::LEFT;
3361                         break;
3362                 case 1:
3363                         bp_.math_numbering_side = BufferParams::DEFAULT;
3364                         break;
3365                 case 2:
3366                         bp_.math_numbering_side = BufferParams::RIGHT;
3367                         break;
3368                 default:
3369                         // this should never happen
3370                         bp_.math_numbering_side = BufferParams::DEFAULT;
3371                         break;
3372         }
3373
3374         // Page Layout
3375         if (pageLayoutModule->pagestyleCO->currentIndex() == 0)
3376                 bp_.pagestyle = "default";
3377         else {
3378                 QString style_gui = pageLayoutModule->pagestyleCO->currentText();
3379                 for (size_t i = 0; i != pagestyles.size(); ++i)
3380                         if (pagestyles[i].second == style_gui)
3381                                 bp_.pagestyle = pagestyles[i].first;
3382         }
3383
3384         // Text Layout
3385         switch (textLayoutModule->lspacingCO->currentIndex()) {
3386         case 0:
3387                 bp_.spacing().set(Spacing::Single);
3388                 break;
3389         case 1:
3390                 bp_.spacing().set(Spacing::Onehalf);
3391                 break;
3392         case 2:
3393                 bp_.spacing().set(Spacing::Double);
3394                 break;
3395         case 3: {
3396                 string s = widgetToDoubleStr(textLayoutModule->lspacingLE);
3397                 if (s.empty())
3398                         bp_.spacing().set(Spacing::Single);
3399                 else
3400                         bp_.spacing().set(Spacing::Other, s);
3401                 break;
3402                 }
3403         }
3404
3405         if (textLayoutModule->twoColumnCB->isChecked())
3406                 bp_.columns = 2;
3407         else
3408                 bp_.columns = 1;
3409
3410         bp_.justification = textLayoutModule->justCB->isChecked();
3411
3412         if (textLayoutModule->indentRB->isChecked()) {
3413                 // if paragraphs are separated by an indentation
3414                 bp_.paragraph_separation = BufferParams::ParagraphIndentSeparation;
3415                 switch (textLayoutModule->indentCO->currentIndex()) {
3416                 case 0:
3417                         bp_.setParIndent(Length());
3418                         break;
3419                 case 1: {
3420                         Length parindent(widgetsToLength(textLayoutModule->indentLE,
3421                                                          textLayoutModule->indentLengthCO));
3422                         bp_.setParIndent(parindent);
3423                         break;
3424                 }
3425                 default:
3426                         // this should never happen
3427                         bp_.setParIndent(Length());
3428                         break;
3429                 }
3430         } else {
3431                 // if paragraphs are separated by a skip
3432                 bp_.paragraph_separation = BufferParams::ParagraphSkipSeparation;
3433                 switch (textLayoutModule->skipCO->currentIndex()) {
3434                 case 0:
3435                         bp_.setDefSkip(VSpace(VSpace::SMALLSKIP));
3436                         break;
3437                 case 1:
3438                         bp_.setDefSkip(VSpace(VSpace::MEDSKIP));
3439                         break;
3440                 case 2:
3441                         bp_.setDefSkip(VSpace(VSpace::BIGSKIP));
3442                         break;
3443                 case 3:
3444                         {
3445                         VSpace vs = VSpace(
3446                                 widgetsToLength(textLayoutModule->skipLE,
3447                                 textLayoutModule->skipLengthCO)
3448                                 );
3449                         bp_.setDefSkip(vs);
3450                         break;
3451                         }
3452                 default:
3453                         // this should never happen
3454                         bp_.setDefSkip(VSpace(VSpace::MEDSKIP));
3455                         break;
3456                 }
3457         }
3458         bp_.tablestyle = fromqstr(textLayoutModule->tableStyleCO->itemData(
3459                                       textLayoutModule->tableStyleCO->currentIndex()).toString());
3460
3461         bp_.options =
3462                 fromqstr(latexModule->optionsLE->text());
3463
3464         bp_.use_default_options =
3465                 latexModule->defaultOptionsCB->isChecked();
3466
3467         if (latexModule->childDocGB->isChecked())
3468                 bp_.master =
3469                         fromqstr(latexModule->childDocLE->text());
3470         else
3471                 bp_.master = string();
3472
3473         // Master/Child
3474         bp_.clearIncludedChildren();
3475         if (masterChildModule->includeonlyRB->isChecked()) {
3476                 list<string>::const_iterator it = includeonlys_.begin();
3477                 for (; it != includeonlys_.end() ; ++it) {
3478                         bp_.addIncludedChildren(*it);
3479                 }
3480         }
3481         bp_.maintain_unincluded_children =
3482                 masterChildModule->maintainAuxCB->isChecked();
3483
3484         // Float Settings
3485         bp_.float_placement = floatModule->getPlacement();
3486         bp_.float_alignment = floatModule->getAlignment();
3487
3488         // Listings
3489         // text should have passed validation
3490         idx = listingsModule->packageCO->currentIndex();
3491         bp_.use_minted = string(lst_packages[idx]) == "Minted";
3492         bp_.listings_params =
3493                 InsetListingsParams(fromqstr(listingsModule->listingsED->toPlainText())).params();
3494
3495         // Formats
3496         bp_.default_output_format = fromqstr(outputModule->defaultFormatCO->itemData(
3497                 outputModule->defaultFormatCO->currentIndex()).toString());
3498
3499         bool const nontexfonts = fontModule->osFontsCB->isChecked();
3500         bp_.useNonTeXFonts = nontexfonts;
3501
3502         bp_.shell_escape = outputModule->shellescapeCB->isChecked();
3503         if (!bp_.shell_escape)
3504             theSession().shellescapeFiles().remove(buffer().absFileName());
3505         else if (!theSession().shellescapeFiles().find(buffer().absFileName()))
3506             theSession().shellescapeFiles().insert(buffer().absFileName());
3507         Buffer & buf = const_cast<Buffer &>(buffer());
3508         buf.params().shell_escape = bp_.shell_escape;
3509
3510         bp_.output_sync = outputModule->outputsyncCB->isChecked();
3511
3512         bp_.output_sync_macro = fromqstr(outputModule->synccustomCB->currentText());
3513
3514         int mathfmt = outputModule->mathoutCB->currentIndex();
3515         if (mathfmt == -1)
3516                 mathfmt = 0;
3517         BufferParams::MathOutput const mo =
3518                 static_cast<BufferParams::MathOutput>(mathfmt);
3519         bp_.html_math_output = mo;
3520         bp_.html_be_strict = outputModule->strictCB->isChecked();
3521         bp_.html_css_as_file = outputModule->cssCB->isChecked();
3522         bp_.html_math_img_scale = outputModule->mathimgSB->value();
3523         bp_.display_pixel_ratio = theGuiApp()->pixelRatio();
3524
3525         bp_.save_transient_properties =
3526                 outputModule->saveTransientPropertiesCB->isChecked();
3527
3528         // fonts
3529         bp_.fonts_roman[nontexfonts] =
3530                 fromqstr(fontModule->fontsRomanCO->
3531                         itemData(fontModule->fontsRomanCO->currentIndex()).toString());
3532         bp_.fonts_roman[!nontexfonts] = fromqstr(fontModule->font_roman);
3533
3534         bp_.fonts_sans[nontexfonts] =
3535                 fromqstr(fontModule->fontsSansCO->
3536                         itemData(fontModule->fontsSansCO->currentIndex()).toString());
3537         bp_.fonts_sans[!nontexfonts] = fromqstr(fontModule->font_sans);
3538
3539         bp_.fonts_typewriter[nontexfonts] =
3540                 fromqstr(fontModule->fontsTypewriterCO->
3541                         itemData(fontModule->fontsTypewriterCO->currentIndex()).toString());
3542         bp_.fonts_typewriter[!nontexfonts] = fromqstr(fontModule->font_typewriter);
3543
3544         bp_.fonts_math[nontexfonts] =
3545                 fromqstr(fontModule->fontsMathCO->
3546                         itemData(fontModule->fontsMathCO->currentIndex()).toString());
3547         bp_.fonts_math[!nontexfonts] = fromqstr(fontModule->font_math);
3548
3549         QString const fontenc =
3550                 fontModule->fontencCO->itemData(fontModule->fontencCO->currentIndex()).toString();
3551         if (fontenc == "custom")
3552                 bp_.fontenc = fromqstr(fontModule->fontencLE->text());
3553         else
3554                 bp_.fontenc = fromqstr(fontenc);
3555
3556         bp_.fonts_cjk =
3557                 fromqstr(fontModule->cjkFontLE->text());
3558
3559         bp_.use_microtype = fontModule->microtypeCB->isChecked();
3560         bp_.use_dash_ligatures = !fontModule->dashesCB->isChecked();
3561
3562         bp_.fonts_sans_scale[nontexfonts] = fontModule->scaleSansSB->value();
3563         bp_.fonts_sans_scale[!nontexfonts] = fontModule->font_sf_scale;
3564
3565         bp_.fonts_typewriter_scale[nontexfonts] = fontModule->scaleTypewriterSB->value();
3566         bp_.fonts_typewriter_scale[!nontexfonts] = fontModule->font_tt_scale;
3567
3568         bp_.fonts_expert_sc = fontModule->fontScCB->isChecked();
3569
3570         bp_.fonts_old_figures = fontModule->fontOsfCB->isChecked();
3571
3572         if (nontexfonts)
3573                 bp_.fonts_default_family = "default";
3574         else
3575                 bp_.fonts_default_family = GuiDocument::fontfamilies[
3576                         fontModule->fontsDefaultCO->currentIndex()];
3577
3578         if (fontModule->fontsizeCO->currentIndex() == 0)
3579                 bp_.fontsize = "default";
3580         else
3581                 bp_.fontsize =
3582                         fromqstr(fontModule->fontsizeCO->currentText());
3583
3584         // paper
3585         bp_.papersize = PAPER_SIZE(
3586                 pageLayoutModule->papersizeCO->currentIndex());
3587
3588         bp_.paperwidth = widgetsToLength(pageLayoutModule->paperwidthLE,
3589                 pageLayoutModule->paperwidthUnitCO);
3590
3591         bp_.paperheight = widgetsToLength(pageLayoutModule->paperheightLE,
3592                 pageLayoutModule->paperheightUnitCO);
3593
3594         if (pageLayoutModule->facingPagesCB->isChecked())
3595                 bp_.sides = TwoSides;
3596         else
3597                 bp_.sides = OneSide;
3598
3599         if (pageLayoutModule->landscapeRB->isChecked())
3600                 bp_.orientation = ORIENTATION_LANDSCAPE;
3601         else
3602                 bp_.orientation = ORIENTATION_PORTRAIT;
3603
3604         // margins
3605         bp_.use_geometry = !marginsModule->marginCB->isChecked();
3606
3607         Ui::MarginsUi const * m = marginsModule;
3608
3609         bp_.leftmargin = widgetsToLength(m->innerLE, m->innerUnit);
3610         bp_.topmargin = widgetsToLength(m->topLE, m->topUnit);
3611         bp_.rightmargin = widgetsToLength(m->outerLE, m->outerUnit);
3612         bp_.bottommargin = widgetsToLength(m->bottomLE, m->bottomUnit);
3613         bp_.headheight = widgetsToLength(m->headheightLE, m->headheightUnit);
3614         bp_.headsep = widgetsToLength(m->headsepLE, m->headsepUnit);
3615         bp_.footskip = widgetsToLength(m->footskipLE, m->footskipUnit);
3616         bp_.columnsep = widgetsToLength(m->columnsepLE, m->columnsepUnit);
3617
3618         // branches
3619         branchesModule->apply(bp_);
3620
3621         // PDF support
3622         PDFOptions & pdf = bp_.pdfoptions();
3623         pdf.use_hyperref = pdfSupportModule->use_hyperrefGB->isChecked();
3624         pdf.title = fromqstr(pdfSupportModule->titleLE->text());
3625         pdf.author = fromqstr(pdfSupportModule->authorLE->text());
3626         pdf.subject = fromqstr(pdfSupportModule->subjectLE->text());
3627         pdf.keywords = fromqstr(pdfSupportModule->keywordsLE->text());
3628
3629         pdf.bookmarks = pdfSupportModule->bookmarksGB->isChecked();
3630         pdf.bookmarksnumbered = pdfSupportModule->bookmarksnumberedCB->isChecked();
3631         pdf.bookmarksopen = pdfSupportModule->bookmarksopenGB->isChecked();
3632         pdf.bookmarksopenlevel = pdfSupportModule->bookmarksopenlevelSB->value();
3633
3634         pdf.breaklinks = pdfSupportModule->breaklinksCB->isChecked();
3635         pdf.pdfborder = pdfSupportModule->pdfborderCB->isChecked();
3636         pdf.pdfusetitle = pdfSupportModule->pdfusetitleCB->isChecked();
3637         pdf.colorlinks = pdfSupportModule->colorlinksCB->isChecked();
3638         pdf.backref =
3639                 backref_opts[pdfSupportModule->backrefCO->currentIndex()];
3640         if (pdfSupportModule->fullscreenCB->isChecked())
3641                 pdf.pagemode = pdf.pagemode_fullscreen;
3642         else
3643                 pdf.pagemode.clear();
3644         pdf.quoted_options = pdf.quoted_options_check(
3645                                 fromqstr(pdfSupportModule->optionsLE->text()));
3646
3647         // reset trackers
3648         nonModuleChanged_ = false;
3649         shellescapeChanged_ = false;
3650 }
3651
3652
3653 void GuiDocument::paramsToDialog()
3654 {
3655         // set the default unit
3656         Length::UNIT const default_unit = Length::defaultUnit();
3657
3658         // preamble
3659         preambleModule->update(bp_, id());
3660         localLayout->update(bp_, id());
3661
3662         // date
3663         latexModule->suppressDateCB->setChecked(bp_.suppress_date);
3664         latexModule->refstyleCB->setChecked(bp_.use_refstyle);
3665
3666         // biblio
3667         string const cite_engine = bp_.citeEngine();
3668
3669         biblioModule->citeEngineCO->setCurrentIndex(
3670                 biblioModule->citeEngineCO->findData(toqstr(cite_engine)));
3671
3672         updateEngineType(documentClass().opt_enginetype(),
3673                 bp_.citeEngineType());
3674
3675         checkPossibleCiteEngines();
3676
3677         biblioModule->citeStyleCO->setCurrentIndex(
3678                 biblioModule->citeStyleCO->findData(bp_.citeEngineType()));
3679
3680         biblioModule->bibtopicCB->setChecked(bp_.splitbib());
3681
3682         biblioModule->bibunitsCO->clear();
3683         biblioModule->bibunitsCO->addItem(qt_("No"), QString());
3684         if (documentClass().hasLaTeXLayout("part"))
3685                 biblioModule->bibunitsCO->addItem(qt_("per part"), toqstr("part"));
3686         if (documentClass().hasLaTeXLayout("chapter"))
3687                 biblioModule->bibunitsCO->addItem(qt_("per chapter"), toqstr("chapter"));
3688         if (documentClass().hasLaTeXLayout("section"))
3689                 biblioModule->bibunitsCO->addItem(qt_("per section"), toqstr("section"));
3690         if (documentClass().hasLaTeXLayout("subsection"))
3691                 biblioModule->bibunitsCO->addItem(qt_("per subsection"), toqstr("subsection"));
3692         biblioModule->bibunitsCO->addItem(qt_("per child document"), toqstr("child"));
3693
3694         int const mbpos = biblioModule->bibunitsCO->findData(toqstr(bp_.multibib));
3695         if (mbpos != -1)
3696                 biblioModule->bibunitsCO->setCurrentIndex(mbpos);
3697         else
3698                 biblioModule->bibunitsCO->setCurrentIndex(0);
3699
3700         updateEngineDependends();
3701
3702         if (isBiblatex()) {
3703                 updateDefaultBiblio(bp_.biblatex_bibstyle, "bbx");
3704                 updateDefaultBiblio(bp_.biblatex_citestyle, "cbx");
3705         } else
3706                 updateDefaultBiblio(bp_.defaultBiblioStyle());
3707
3708         biblioModule->citePackageOptionsLE->setText(toqstr(bp_.biblio_opts));
3709
3710         string command;
3711         string options =
3712                 split(bp_.bibtex_command, command, ' ');
3713
3714         int const bpos = biblioModule->bibtexCO->findData(toqstr(command));
3715         if (bpos != -1) {
3716                 biblioModule->bibtexCO->setCurrentIndex(bpos);
3717                 biblioModule->bibtexOptionsLE->setText(toqstr(options).trimmed());
3718         } else {
3719                 // We reset to default if we do not know the specified compiler
3720                 // This is for security reasons
3721                 biblioModule->bibtexCO->setCurrentIndex(
3722                         biblioModule->bibtexCO->findData(toqstr("default")));
3723                 biblioModule->bibtexOptionsLE->clear();
3724         }
3725         biblioModule->bibtexOptionsLE->setEnabled(
3726                 biblioModule->bibtexCO->currentIndex() != 0);
3727
3728         biblioChanged_ = false;
3729
3730         // indices
3731         // We may be called when there is no Buffer, e.g., when
3732         // the last view has just been closed.
3733         bool const isReadOnly = isBufferAvailable() ? buffer().isReadonly() : false;
3734         indicesModule->update(bp_, isReadOnly);
3735
3736         // language & quotes
3737         int const pos = langModule->languageCO->findData(toqstr(
3738                 bp_.language->lang()));
3739         langModule->languageCO->setCurrentIndex(pos);
3740
3741         updateQuoteStyles();
3742
3743         langModule->quoteStyleCO->setCurrentIndex(
3744                 langModule->quoteStyleCO->findData(bp_.quotes_style));
3745         langModule->dynamicQuotesCB->setChecked(bp_.dynamic_quotes);
3746
3747         QString inputenc = toqstr(bp_.inputenc);
3748         bool plain = false;
3749         if (inputenc.endsWith("-plain")) {
3750                 inputenc = inputenc.left(inputenc.lastIndexOf("-plain"));
3751                 plain = true;
3752         }
3753         langModule->noInputencCB->setChecked(plain);
3754         int p = langModule->encodingCO->findData(inputenc);
3755         if (p != -1)
3756                 langModule->encodingCO->setCurrentIndex(p);
3757         else {
3758                 langModule->encodingCO->setCurrentIndex(
3759                           langModule->encodingCO->findData("custom"));
3760                 p = langModule->customEncodingCO->findData(inputenc);
3761                 if (p != -1)
3762                         langModule->customEncodingCO->setCurrentIndex(p);
3763                 else
3764                         langModule->encodingCO->setCurrentIndex(0);
3765         }
3766
3767         p = langModule->languagePackageCO->findData(toqstr(bp_.lang_package));
3768         if (p == -1) {
3769                 langModule->languagePackageCO->setCurrentIndex(
3770                           langModule->languagePackageCO->findData("custom"));
3771                 langModule->languagePackageLE->setText(toqstr(bp_.lang_package));
3772         } else {
3773                 langModule->languagePackageCO->setCurrentIndex(p);
3774                 langModule->languagePackageLE->clear();
3775         }
3776
3777         //color
3778         if (bp_.isfontcolor) {
3779                 colorModule->fontColorPB->setStyleSheet(
3780                         colorButtonStyleSheet(rgb2qcolor(bp_.fontcolor)));
3781         }
3782         set_fontcolor = bp_.fontcolor;
3783         is_fontcolor = bp_.isfontcolor;
3784
3785         colorModule->noteFontColorPB->setStyleSheet(
3786                 colorButtonStyleSheet(rgb2qcolor(bp_.notefontcolor)));
3787         set_notefontcolor = bp_.notefontcolor;
3788
3789         if (bp_.isbackgroundcolor) {
3790                 colorModule->backgroundPB->setStyleSheet(
3791                         colorButtonStyleSheet(rgb2qcolor(bp_.backgroundcolor)));
3792         }
3793         set_backgroundcolor = bp_.backgroundcolor;
3794         is_backgroundcolor = bp_.isbackgroundcolor;
3795
3796         colorModule->boxBackgroundPB->setStyleSheet(
3797                 colorButtonStyleSheet(rgb2qcolor(bp_.boxbgcolor)));
3798         set_boxbgcolor = bp_.boxbgcolor;
3799
3800         // numbering
3801         int const min_toclevel = documentClass().min_toclevel();
3802         int const max_toclevel = documentClass().max_toclevel();
3803         if (documentClass().hasTocLevels()) {
3804                 numberingModule->setEnabled(true);
3805                 numberingModule->depthSL->setMinimum(min_toclevel - 1);
3806                 numberingModule->depthSL->setMaximum(max_toclevel);
3807                 numberingModule->depthSL->setValue(bp_.secnumdepth);
3808                 numberingModule->tocSL->setMaximum(min_toclevel - 1);
3809                 numberingModule->tocSL->setMaximum(max_toclevel);
3810                 numberingModule->tocSL->setValue(bp_.tocdepth);
3811                 updateNumbering();
3812         } else {
3813                 numberingModule->setEnabled(false);
3814                 numberingModule->tocTW->clear();
3815         }
3816
3817         numberingModule->linenoCB->setChecked(bp_.use_lineno);
3818         numberingModule->linenoLE->setEnabled(bp_.use_lineno);
3819         numberingModule->linenoLA->setEnabled(bp_.use_lineno);
3820         numberingModule->linenoLE->setText(toqstr(bp_.lineno_opts));
3821
3822         // bullets
3823         bulletsModule->setBullet(0, bp_.user_defined_bullet(0));
3824         bulletsModule->setBullet(1, bp_.user_defined_bullet(1));
3825         bulletsModule->setBullet(2, bp_.user_defined_bullet(2));
3826         bulletsModule->setBullet(3, bp_.user_defined_bullet(3));
3827         bulletsModule->init();
3828
3829         // packages
3830         int nitem = findToken(tex_graphics, bp_.graphics_driver);
3831         if (nitem >= 0)
3832                 latexModule->psdriverCO->setCurrentIndex(nitem);
3833         updateModuleInfo();
3834
3835         // math
3836         mathsModule->MathIndentCB->setChecked(bp_.is_math_indent);
3837         if (bp_.is_math_indent) {
3838                 Length const mathindent = bp_.getMathIndent();
3839                 int indent = 0;
3840                 if (!mathindent.empty()) {
3841                         lengthToWidgets(mathsModule->MathIndentLE,
3842                                         mathsModule->MathIndentLengthCO,
3843                                         mathindent, default_unit);
3844                         indent = 1;
3845                 }
3846                 mathsModule->MathIndentCO->setCurrentIndex(indent);
3847                 enableMathIndent(indent);
3848         }
3849         switch(bp_.math_numbering_side) {
3850         case BufferParams::LEFT:
3851                 mathsModule->MathNumberingPosCO->setCurrentIndex(0);
3852                 break;
3853         case BufferParams::DEFAULT:
3854                 mathsModule->MathNumberingPosCO->setCurrentIndex(1);
3855                 break;
3856         case BufferParams::RIGHT:
3857                 mathsModule->MathNumberingPosCO->setCurrentIndex(2);
3858         }
3859
3860         map<string, string> const & packages = BufferParams::auto_packages();
3861         for (map<string, string>::const_iterator it = packages.begin();
3862              it != packages.end(); ++it) {
3863                 QTableWidgetItem * item = mathsModule->packagesTW->findItems(toqstr(it->first), Qt::MatchExactly)[0];
3864                 if (!item)
3865                         continue;
3866                 int row = mathsModule->packagesTW->row(item);
3867                 switch (bp_.use_package(it->first)) {
3868                         case BufferParams::package_off: {
3869                                 QRadioButton * rb =
3870                                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 3)->layout()->itemAt(0)->widget();
3871                                 rb->setChecked(true);
3872                                 break;
3873                         }
3874                         case BufferParams::package_on: {
3875                                 QRadioButton * rb =
3876                                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 2)->layout()->itemAt(0)->widget();
3877                                 rb->setChecked(true);
3878                                 break;
3879                         }
3880                         case BufferParams::package_auto: {
3881                                 QRadioButton * rb =
3882                                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, 1)->layout()->itemAt(0)->widget();
3883                                 rb->setChecked(true);
3884                                 break;
3885                         }
3886                 }
3887         }
3888
3889         switch (bp_.spacing().getSpace()) {
3890                 case Spacing::Other: nitem = 3; break;
3891                 case Spacing::Double: nitem = 2; break;
3892                 case Spacing::Onehalf: nitem = 1; break;
3893                 case Spacing::Default: case Spacing::Single: nitem = 0; break;
3894         }
3895
3896         // text layout
3897         string const & layoutID = bp_.baseClassID();
3898         setLayoutComboByIDString(layoutID);
3899
3900         updatePagestyle(documentClass().opt_pagestyle(),
3901                                  bp_.pagestyle);
3902
3903         textLayoutModule->lspacingCO->setCurrentIndex(nitem);
3904         if (bp_.spacing().getSpace() == Spacing::Other) {
3905                 doubleToWidget(textLayoutModule->lspacingLE,
3906                         bp_.spacing().getValueAsString());
3907         }
3908         setLSpacing(nitem);
3909         int ts = textLayoutModule->tableStyleCO->findData(toqstr(bp_.tablestyle));
3910         if (ts != -1)
3911                 textLayoutModule->tableStyleCO->setCurrentIndex(ts);
3912
3913         if (bp_.paragraph_separation == BufferParams::ParagraphIndentSeparation) {
3914                 textLayoutModule->indentRB->setChecked(true);
3915                 string parindent = bp_.getParIndent().asString();
3916                 int indent = 0;
3917                 if (!parindent.empty()) {
3918                         lengthToWidgets(textLayoutModule->indentLE,
3919                                         textLayoutModule->indentLengthCO,
3920                                         parindent, default_unit);
3921                         indent = 1;
3922                 }
3923                 textLayoutModule->indentCO->setCurrentIndex(indent);
3924                 setIndent(indent);
3925         } else {
3926                 textLayoutModule->skipRB->setChecked(true);
3927                 int skip = 0;
3928                 switch (bp_.getDefSkip().kind()) {
3929                 case VSpace::SMALLSKIP:
3930                         skip = 0;
3931                         break;
3932                 case VSpace::MEDSKIP:
3933                         skip = 1;
3934                         break;
3935                 case VSpace::BIGSKIP:
3936                         skip = 2;
3937                         break;
3938                 case VSpace::LENGTH:
3939                         {
3940                         skip = 3;
3941                         string const length = bp_.getDefSkip().asLyXCommand();
3942                         lengthToWidgets(textLayoutModule->skipLE,
3943                                 textLayoutModule->skipLengthCO,
3944                                 length, default_unit);
3945                         break;
3946                         }
3947                 default:
3948                         skip = 0;
3949                         break;
3950                 }
3951                 textLayoutModule->skipCO->setCurrentIndex(skip);
3952                 setSkip(skip);
3953         }
3954
3955         textLayoutModule->twoColumnCB->setChecked(
3956                 bp_.columns == 2);
3957         textLayoutModule->justCB->setChecked(bp_.justification);
3958
3959         if (!bp_.options.empty()) {
3960                 latexModule->optionsLE->setText(
3961                         toqstr(bp_.options));
3962         } else {
3963                 latexModule->optionsLE->setText(QString());
3964         }
3965
3966         // latex
3967         latexModule->defaultOptionsCB->setChecked(
3968                         bp_.use_default_options);
3969         updateSelectedModules();
3970         selectionManager->updateProvidedModules(
3971                         bp_.baseClass()->providedModules());
3972         selectionManager->updateExcludedModules(
3973                         bp_.baseClass()->excludedModules());
3974
3975         if (!documentClass().options().empty()) {
3976                 latexModule->defaultOptionsLE->setText(
3977                         toqstr(documentClass().options()));
3978         } else {
3979                 latexModule->defaultOptionsLE->setText(
3980                         toqstr(_("[No options predefined]")));
3981         }
3982
3983         latexModule->defaultOptionsLE->setEnabled(
3984                 bp_.use_default_options
3985                 && !documentClass().options().empty());
3986
3987         latexModule->defaultOptionsCB->setEnabled(
3988                 !documentClass().options().empty());
3989
3990         if (!bp_.master.empty()) {
3991                 latexModule->childDocGB->setChecked(true);
3992                 latexModule->childDocLE->setText(
3993                         toqstr(bp_.master));
3994         } else {
3995                 latexModule->childDocLE->setText(QString());
3996                 latexModule->childDocGB->setChecked(false);
3997         }
3998
3999         // Master/Child
4000         if (!bufferview() || !buffer().hasChildren()) {
4001                 masterChildModule->childrenTW->clear();
4002                 includeonlys_.clear();
4003                 docPS->showPanel("Child Documents", false);
4004                 if (docPS->isCurrentPanel("Child Documents"))
4005                         docPS->setCurrentPanel("Document Class");
4006         } else {
4007                 docPS->showPanel("Child Documents", true);
4008                 masterChildModule->setEnabled(true);
4009                 includeonlys_ = bp_.getIncludedChildren();
4010                 updateIncludeonlys();
4011         }
4012         masterChildModule->maintainAuxCB->setChecked(
4013                 bp_.maintain_unincluded_children);
4014
4015         // Float Settings
4016         floatModule->setPlacement(bp_.float_placement);
4017         floatModule->setAlignment(bp_.float_alignment);
4018
4019         // ListingsSettings
4020         // break listings_params to multiple lines
4021         string lstparams =
4022                 InsetListingsParams(bp_.listings_params).separatedParams();
4023         listingsModule->listingsED->setPlainText(toqstr(lstparams));
4024         int nn = findToken(lst_packages, bp_.use_minted ? "Minted" : "Listings");
4025         if (nn >= 0)
4026                 listingsModule->packageCO->setCurrentIndex(nn);
4027
4028         // Fonts
4029         // some languages only work with Polyglossia (which requires non-TeX fonts)
4030         Language const * lang = lyx::languages.getLanguage(
4031                 fromqstr(langModule->languageCO->itemData(
4032                         langModule->languageCO->currentIndex()).toString()));
4033         bool const need_fontspec =
4034                 lang->babel().empty() && !lang->polyglossia().empty();
4035         bool const os_fonts_available =
4036                 bp_.baseClass()->outputType() == lyx::LATEX
4037                 && LaTeXFeatures::isAvailable("fontspec");
4038         fontModule->osFontsCB->setEnabled(os_fonts_available && !need_fontspec);
4039         fontModule->osFontsCB->setChecked(
4040                 (os_fonts_available && bp_.useNonTeXFonts) || need_fontspec);
4041         updateFontsize(documentClass().opt_fontsize(),
4042                         bp_.fontsize);
4043
4044         QString font = toqstr(bp_.fontsRoman());
4045         int rpos = fontModule->fontsRomanCO->findData(font);
4046         if (rpos == -1) {
4047                 rpos = fontModule->fontsRomanCO->count();
4048                 fontModule->fontsRomanCO->addItem(font + qt_(" (not installed)"), font);
4049         }
4050         fontModule->fontsRomanCO->setCurrentIndex(rpos);
4051         fontModule->font_roman = toqstr(bp_.fonts_roman[!bp_.useNonTeXFonts]);
4052
4053         font = toqstr(bp_.fontsSans());
4054         int spos = fontModule->fontsSansCO->findData(font);
4055         if (spos == -1) {
4056                 spos = fontModule->fontsSansCO->count();
4057                 fontModule->fontsSansCO->addItem(font + qt_(" (not installed)"), font);
4058         }
4059         fontModule->fontsSansCO->setCurrentIndex(spos);
4060         fontModule->font_sans = toqstr(bp_.fonts_sans[!bp_.useNonTeXFonts]);
4061
4062         font = toqstr(bp_.fontsTypewriter());
4063         int tpos = fontModule->fontsTypewriterCO->findData(font);
4064         if (tpos == -1) {
4065                 tpos = fontModule->fontsTypewriterCO->count();
4066                 fontModule->fontsTypewriterCO->addItem(font + qt_(" (not installed)"), font);
4067         }
4068         fontModule->fontsTypewriterCO->setCurrentIndex(tpos);
4069         fontModule->font_typewriter = toqstr(bp_.fonts_typewriter[!bp_.useNonTeXFonts]);
4070
4071         font = toqstr(bp_.fontsMath());
4072         int mpos = fontModule->fontsMathCO->findData(font);
4073         if (mpos == -1) {
4074                 mpos = fontModule->fontsMathCO->count();
4075                 fontModule->fontsMathCO->addItem(font + qt_(" (not installed)"), font);
4076         }
4077         fontModule->fontsMathCO->setCurrentIndex(mpos);
4078         fontModule->font_math = toqstr(bp_.fonts_math[!bp_.useNonTeXFonts]);
4079
4080         if (bp_.useNonTeXFonts && os_fonts_available) {
4081                 fontModule->fontencLA->setEnabled(false);
4082                 fontModule->fontencCO->setEnabled(false);
4083                 fontModule->fontencLE->setEnabled(false);
4084         } else {
4085                 fontModule->fontencLA->setEnabled(true);
4086                 fontModule->fontencCO->setEnabled(true);
4087                 fontModule->fontencLE->setEnabled(true);
4088                 romanChanged(rpos);
4089                 sansChanged(spos);
4090                 ttChanged(tpos);
4091         }
4092
4093         if (!bp_.fonts_cjk.empty())
4094                 fontModule->cjkFontLE->setText(
4095                         toqstr(bp_.fonts_cjk));
4096         else
4097                 fontModule->cjkFontLE->setText(QString());
4098
4099         fontModule->microtypeCB->setChecked(bp_.use_microtype);
4100         fontModule->dashesCB->setChecked(!bp_.use_dash_ligatures);
4101
4102         fontModule->fontScCB->setChecked(bp_.fonts_expert_sc);
4103         fontModule->fontOsfCB->setChecked(bp_.fonts_old_figures);
4104         fontModule->scaleSansSB->setValue(bp_.fontsSansScale());
4105         fontModule->font_sf_scale = bp_.fonts_sans_scale[!bp_.useNonTeXFonts];
4106         fontModule->scaleTypewriterSB->setValue(bp_.fontsTypewriterScale());
4107         fontModule->font_tt_scale = bp_.fonts_typewriter_scale[!bp_.useNonTeXFonts];
4108
4109         nn = findToken(GuiDocument::fontfamilies, bp_.fonts_default_family);
4110         if (nn >= 0)
4111                 fontModule->fontsDefaultCO->setCurrentIndex(nn);
4112
4113         if (bp_.fontenc == "auto" || bp_.fontenc == "default") {
4114                 fontModule->fontencCO->setCurrentIndex(
4115                         fontModule->fontencCO->findData(toqstr(bp_.fontenc)));
4116                 fontModule->fontencLE->setEnabled(false);
4117         } else {
4118                 fontModule->fontencCO->setCurrentIndex(
4119                                         fontModule->fontencCO->findData("custom"));
4120                 fontModule->fontencLE->setText(toqstr(bp_.fontenc));
4121         }
4122
4123         // Formats
4124         // This must be set _after_ fonts since updateDefaultFormat()
4125         // checks osFontsCB settings.
4126         // update combobox with formats
4127         updateDefaultFormat();
4128         int index = outputModule->defaultFormatCO->findData(toqstr(
4129                 bp_.default_output_format));
4130         // set to default if format is not found
4131         if (index == -1)
4132                 index = 0;
4133         outputModule->defaultFormatCO->setCurrentIndex(index);
4134
4135         outputModule->shellescapeCB->setChecked(bp_.shell_escape);
4136         outputModule->outputsyncCB->setChecked(bp_.output_sync);
4137         outputModule->synccustomCB->setEditText(toqstr(bp_.output_sync_macro));
4138
4139         outputModule->mathimgSB->setValue(bp_.html_math_img_scale);
4140         outputModule->mathoutCB->setCurrentIndex(bp_.html_math_output);
4141         outputModule->strictCB->setChecked(bp_.html_be_strict);
4142         outputModule->cssCB->setChecked(bp_.html_css_as_file);
4143
4144         outputModule->saveTransientPropertiesCB
4145                 ->setChecked(bp_.save_transient_properties);
4146
4147         // paper
4148         bool const extern_geometry =
4149                 documentClass().provides("geometry");
4150         int const psize = bp_.papersize;
4151         pageLayoutModule->papersizeCO->setCurrentIndex(psize);
4152         setCustomPapersize(!extern_geometry && psize == 1);
4153         pageLayoutModule->papersizeCO->setEnabled(!extern_geometry);
4154
4155         bool const landscape =
4156                 bp_.orientation == ORIENTATION_LANDSCAPE;
4157         pageLayoutModule->landscapeRB->setChecked(landscape);
4158         pageLayoutModule->portraitRB->setChecked(!landscape);
4159         pageLayoutModule->landscapeRB->setEnabled(!extern_geometry);
4160         pageLayoutModule->portraitRB->setEnabled(!extern_geometry);
4161
4162         pageLayoutModule->facingPagesCB->setChecked(
4163                 bp_.sides == TwoSides);
4164
4165         lengthToWidgets(pageLayoutModule->paperwidthLE,
4166                 pageLayoutModule->paperwidthUnitCO, bp_.paperwidth, default_unit);
4167         lengthToWidgets(pageLayoutModule->paperheightLE,
4168                 pageLayoutModule->paperheightUnitCO, bp_.paperheight, default_unit);
4169
4170         // margins
4171         Ui::MarginsUi * m = marginsModule;
4172
4173         setMargins();
4174
4175         lengthToWidgets(m->topLE, m->topUnit,
4176                 bp_.topmargin, default_unit);
4177
4178         lengthToWidgets(m->bottomLE, m->bottomUnit,
4179                 bp_.bottommargin, default_unit);
4180
4181         lengthToWidgets(m->innerLE, m->innerUnit,
4182                 bp_.leftmargin, default_unit);
4183
4184         lengthToWidgets(m->outerLE, m->outerUnit,
4185                 bp_.rightmargin, default_unit);
4186
4187         lengthToWidgets(m->headheightLE, m->headheightUnit,
4188                 bp_.headheight, default_unit);
4189
4190         lengthToWidgets(m->headsepLE, m->headsepUnit,
4191                 bp_.headsep, default_unit);
4192
4193         lengthToWidgets(m->footskipLE, m->footskipUnit,
4194                 bp_.footskip, default_unit);
4195
4196         lengthToWidgets(m->columnsepLE, m->columnsepUnit,
4197                 bp_.columnsep, default_unit);
4198
4199         // branches
4200         updateUnknownBranches();
4201         branchesModule->update(bp_);
4202
4203         // PDF support
4204         PDFOptions const & pdf = bp_.pdfoptions();
4205         pdfSupportModule->use_hyperrefGB->setChecked(pdf.use_hyperref);
4206         if (bp_.documentClass().provides("hyperref"))
4207                 pdfSupportModule->use_hyperrefGB->setTitle(qt_("C&ustomize Hyperref Options"));
4208         else
4209                 pdfSupportModule->use_hyperrefGB->setTitle(qt_("&Use Hyperref Support"));
4210         pdfSupportModule->titleLE->setText(toqstr(pdf.title));
4211         pdfSupportModule->authorLE->setText(toqstr(pdf.author));
4212         pdfSupportModule->subjectLE->setText(toqstr(pdf.subject));
4213         pdfSupportModule->keywordsLE->setText(toqstr(pdf.keywords));
4214
4215         pdfSupportModule->bookmarksGB->setChecked(pdf.bookmarks);
4216         pdfSupportModule->bookmarksnumberedCB->setChecked(pdf.bookmarksnumbered);
4217         pdfSupportModule->bookmarksopenGB->setChecked(pdf.bookmarksopen);
4218
4219         pdfSupportModule->bookmarksopenlevelSB->setValue(pdf.bookmarksopenlevel);
4220
4221         pdfSupportModule->breaklinksCB->setChecked(pdf.breaklinks);
4222         pdfSupportModule->pdfborderCB->setChecked(pdf.pdfborder);
4223         pdfSupportModule->pdfusetitleCB->setChecked(pdf.pdfusetitle);
4224         pdfSupportModule->colorlinksCB->setChecked(pdf.colorlinks);
4225
4226         nn = findToken(backref_opts, pdf.backref);
4227         if (nn >= 0)
4228                 pdfSupportModule->backrefCO->setCurrentIndex(nn);
4229
4230         pdfSupportModule->fullscreenCB->setChecked
4231                 (pdf.pagemode == pdf.pagemode_fullscreen);
4232
4233         pdfSupportModule->optionsLE->setText(
4234                 toqstr(pdf.quoted_options));
4235
4236         // Make sure that the bc is in the INITIAL state
4237         if (bc().policy().buttonStatus(ButtonPolicy::RESTORE))
4238                 bc().restore();
4239
4240         // clear changed branches cache
4241         changedBranches_.clear();
4242
4243         // reset trackers
4244         nonModuleChanged_ = false;
4245         shellescapeChanged_ = false;
4246 }
4247
4248
4249 void GuiDocument::saveDocDefault()
4250 {
4251         // we have to apply the params first
4252         applyView();
4253         saveAsDefault();
4254 }
4255
4256
4257 void GuiDocument::updateAvailableModules()
4258 {
4259         modules_av_model_.clear();
4260         list<modInfoStruct> modInfoList = getModuleInfo();
4261         // Sort names according to the locale
4262         modInfoList.sort([](modInfoStruct const & a, modInfoStruct const & b) {
4263                         return 0 < b.name.localeAwareCompare(a.name);
4264                 });
4265         QIcon user_icon(getPixmap("images/", "lyxfiles-user", "svgz,png"));
4266         QIcon system_icon(getPixmap("images/", "lyxfiles-system", "svgz,png"));
4267         int i = 0;
4268         QFont catfont;
4269         catfont.setBold(true);
4270         QBrush unavbrush;
4271         unavbrush.setColor(Qt::gray);
4272         for (modInfoStruct const & m : modInfoList) {
4273                 QStandardItem * item = new QStandardItem();
4274                 QStandardItem * catItem = new QStandardItem();
4275                 QString const catname = m.category;
4276                 QList<QStandardItem *> fcats = modules_av_model_.findItems(catname, Qt::MatchExactly);
4277                 if (!fcats.empty())
4278                         catItem = fcats.first();
4279                 else {
4280                         catItem->setText(catname);
4281                         catItem->setFont(catfont);
4282                         modules_av_model_.insertRow(i, catItem);
4283                         ++i;
4284                 }
4285                 item->setEditable(false);
4286                 catItem->setEditable(false);
4287                 item->setData(m.name, Qt::DisplayRole);
4288                 if (m.missingreqs)
4289                         item->setForeground(unavbrush);
4290                 item->setData(toqstr(m.id), Qt::UserRole);
4291                 item->setData(m.description, Qt::ToolTipRole);
4292                 if (m.local)
4293                         item->setIcon(user_icon);
4294                 else
4295                         item->setIcon(system_icon);
4296                 catItem->appendRow(item);
4297         }
4298         modules_av_model_.sort(0);
4299 }
4300
4301
4302 void GuiDocument::updateSelectedModules()
4303 {
4304         modules_sel_model_.clear();
4305         list<modInfoStruct> const selModList = getSelectedModules();
4306         int i = 0;
4307         for (modInfoStruct const & m : selModList) {
4308                 modules_sel_model_.insertRow(i, m.name, m.id, m.description);
4309                 ++i;
4310         }
4311 }
4312
4313
4314 void GuiDocument::updateIncludeonlys()
4315 {
4316         masterChildModule->childrenTW->clear();
4317         QString const no = qt_("No");
4318         QString const yes = qt_("Yes");
4319
4320         if (includeonlys_.empty()) {
4321                 masterChildModule->includeallRB->setChecked(true);
4322                 masterChildModule->childrenTW->setEnabled(false);
4323                 masterChildModule->maintainAuxCB->setEnabled(false);
4324         } else {
4325                 masterChildModule->includeonlyRB->setChecked(true);
4326                 masterChildModule->childrenTW->setEnabled(true);
4327                 masterChildModule->maintainAuxCB->setEnabled(true);
4328         }
4329         ListOfBuffers children = buffer().getChildren();
4330         ListOfBuffers::const_iterator it  = children.begin();
4331         ListOfBuffers::const_iterator end = children.end();
4332         bool has_unincluded = false;
4333         bool all_unincluded = true;
4334         for (; it != end; ++it) {
4335                 QTreeWidgetItem * item = new QTreeWidgetItem(masterChildModule->childrenTW);
4336                 // FIXME Unicode
4337                 string const name =
4338                         to_utf8(makeRelPath(from_utf8((*it)->fileName().absFileName()),
4339                                                         from_utf8(buffer().filePath())));
4340                 item->setText(0, toqstr(name));
4341                 item->setText(1, isChildIncluded(name) ? yes : no);
4342                 if (!isChildIncluded(name))
4343                         has_unincluded = true;
4344                 else
4345                         all_unincluded = false;
4346         }
4347         // Both if all childs are included and if none is included
4348         // is equal to "include all" (i.e., omit \includeonly).
4349         // Thus, reset the GUI.
4350         if (!has_unincluded || all_unincluded) {
4351                 masterChildModule->includeallRB->setChecked(true);
4352                 masterChildModule->childrenTW->setEnabled(false);
4353                 includeonlys_.clear();
4354         }
4355         // If all are included, we need to update again.
4356         if (!has_unincluded)
4357                 updateIncludeonlys();
4358 }
4359
4360
4361 bool GuiDocument::isBiblatex() const
4362 {
4363         QString const engine =
4364                 biblioModule->citeEngineCO->itemData(
4365                                 biblioModule->citeEngineCO->currentIndex()).toString();
4366
4367         // this can happen if the cite engine is unknown, which can happen
4368         // if one is using a file that came from someone else, etc. in that
4369         // case, we crash if we proceed.
4370         if (engine.isEmpty())
4371             return false;
4372
4373         return theCiteEnginesList[fromqstr(engine)]->getCiteFramework() == "biblatex";
4374 }
4375
4376
4377 void GuiDocument::updateDefaultBiblio(string const & style,
4378                                       string const & which)
4379 {
4380         QString const bibstyle = toqstr(style);
4381         biblioModule->defaultBiblioCO->clear();
4382
4383         int item_nr = -1;
4384
4385         if (isBiblatex()) {
4386                 if (which != "cbx") {
4387                         // First the bbx styles
4388                         biblioModule->biblatexBbxCO->clear();
4389                         QStringList str = texFileList("bbxFiles.lst");
4390                         // test whether we have a valid list, otherwise run rescan
4391                         if (str.isEmpty()) {
4392                                 rescanTexStyles("bbx");
4393                                 str = texFileList("bbxFiles.lst");
4394                         }
4395                         for (int i = 0; i != str.size(); ++i)
4396                                 str[i] = onlyFileName(str[i]);
4397                         // sort on filename only (no path)
4398                         str.sort();
4399
4400                         for (int i = 0; i != str.count(); ++i) {
4401                                 QString item = changeExtension(str[i], "");
4402                                 if (item == bibstyle)
4403                                         item_nr = i;
4404                                 biblioModule->biblatexBbxCO->addItem(item);
4405                         }
4406
4407                         if (item_nr == -1 && !bibstyle.isEmpty()) {
4408                                 biblioModule->biblatexBbxCO->addItem(bibstyle);
4409                                 item_nr = biblioModule->biblatexBbxCO->count() - 1;
4410                         }
4411
4412                         if (item_nr != -1)
4413                                 biblioModule->biblatexBbxCO->setCurrentIndex(item_nr);
4414                         else
4415                                 biblioModule->biblatexBbxCO->clearEditText();
4416                 }
4417
4418                 if (which != "bbx") {
4419                         // now the cbx styles
4420                         biblioModule->biblatexCbxCO->clear();
4421                         QStringList str = texFileList("cbxFiles.lst");
4422                         // test whether we have a valid list, otherwise run rescan
4423                         if (str.isEmpty()) {
4424                                 rescanTexStyles("cbx");
4425                                 str = texFileList("cbxFiles.lst");
4426                         }
4427                         for (int i = 0; i != str.size(); ++i)
4428                                 str[i] = onlyFileName(str[i]);
4429                         // sort on filename only (no path)
4430                         str.sort();
4431
4432                         for (int i = 0; i != str.count(); ++i) {
4433                                 QString item = changeExtension(str[i], "");
4434                                 if (item == bibstyle)
4435                                         item_nr = i;
4436                                 biblioModule->biblatexCbxCO->addItem(item);
4437                         }
4438
4439                         if (item_nr == -1 && !bibstyle.isEmpty()) {
4440                                 biblioModule->biblatexCbxCO->addItem(bibstyle);
4441                                 item_nr = biblioModule->biblatexCbxCO->count() - 1;
4442                         }
4443
4444                         if (item_nr != -1)
4445                                 biblioModule->biblatexCbxCO->setCurrentIndex(item_nr);
4446                         else
4447                                 biblioModule->biblatexCbxCO->clearEditText();
4448                 }
4449         } else {// BibTeX
4450                 biblioModule->biblatexBbxCO->clear();
4451                 biblioModule->biblatexCbxCO->clear();
4452                 QStringList str = texFileList("bstFiles.lst");
4453                 // test whether we have a valid list, otherwise run rescan
4454                 if (str.isEmpty()) {
4455                         rescanTexStyles("bst");
4456                         str = texFileList("bstFiles.lst");
4457                 }
4458                 for (int i = 0; i != str.size(); ++i)
4459                         str[i] = onlyFileName(str[i]);
4460                 // sort on filename only (no path)
4461                 str.sort();
4462
4463                 for (int i = 0; i != str.count(); ++i) {
4464                         QString item = changeExtension(str[i], "");
4465                         if (item == bibstyle)
4466                                 item_nr = i;
4467                         biblioModule->defaultBiblioCO->addItem(item);
4468                 }
4469
4470                 if (item_nr == -1 && !bibstyle.isEmpty()) {
4471                         biblioModule->defaultBiblioCO->addItem(bibstyle);
4472                         item_nr = biblioModule->defaultBiblioCO->count() - 1;
4473                 }
4474
4475                 if (item_nr != -1)
4476                         biblioModule->defaultBiblioCO->setCurrentIndex(item_nr);
4477                 else
4478                         biblioModule->defaultBiblioCO->clearEditText();
4479         }
4480
4481         updateResetDefaultBiblio();
4482 }
4483
4484
4485 void GuiDocument::updateResetDefaultBiblio()
4486 {
4487         QString const engine =
4488                 biblioModule->citeEngineCO->itemData(
4489                                 biblioModule->citeEngineCO->currentIndex()).toString();
4490         CiteEngineType const cet =
4491                 CiteEngineType(biblioModule->citeStyleCO->itemData(
4492                                                           biblioModule->citeStyleCO->currentIndex()).toInt());
4493
4494         string const defbib = theCiteEnginesList[fromqstr(engine)]->getDefaultBiblio(cet);
4495         if (isBiblatex()) {
4496                 QString const bbx = biblioModule->biblatexBbxCO->currentText();
4497                 QString const cbx = biblioModule->biblatexCbxCO->currentText();
4498                 biblioModule->resetCbxPB->setEnabled(defbib != fromqstr(cbx));
4499                 biblioModule->resetBbxPB->setEnabled(defbib != fromqstr(bbx));
4500                 biblioModule->matchBbxPB->setEnabled(bbx != cbx && !cbx.isEmpty()
4501                         && biblioModule->biblatexBbxCO->findText(cbx) != -1);
4502         } else
4503                 biblioModule->resetDefaultBiblioPB->setEnabled(
4504                         defbib != fromqstr(biblioModule->defaultBiblioCO->currentText()));
4505 }
4506
4507
4508 void GuiDocument::matchBiblatexStyles()
4509 {
4510         updateDefaultBiblio(fromqstr(biblioModule->biblatexCbxCO->currentText()), "bbx");
4511         biblioChanged();
4512 }
4513
4514
4515 void GuiDocument::updateContents()
4516 {
4517         // Nothing to do here as the document settings is not cursor dependant.
4518         return;
4519 }
4520
4521
4522 void GuiDocument::useClassDefaults()
4523 {
4524         if (buttonBox->button(QDialogButtonBox::Apply)->isEnabled()) {
4525                 int const ret = Alert::prompt(_("Unapplied changes"),
4526                                 _("Some changes in the dialog were not yet applied.\n"
4527                                   "If you do not apply now, they will be lost after this action."),
4528                                 1, 1, _("&Apply"), _("&Dismiss"));
4529                 if (ret == 0)
4530                         applyView();
4531         }
4532
4533         int idx = latexModule->classCO->currentIndex();
4534         string const classname = fromqstr(latexModule->classCO->getData(idx));
4535         if (!bp_.setBaseClass(classname, buffer().layoutPos())) {
4536                 Alert::error(_("Error"), _("Unable to set document class."));
4537                 return;
4538         }
4539         bp_.useClassDefaults();
4540         paramsToDialog();
4541         changed();
4542 }
4543
4544
4545 void GuiDocument::setLayoutComboByIDString(string const & idString)
4546 {
4547         if (!latexModule->classCO->set(toqstr(idString)))
4548                 Alert::warning(_("Can't set layout!"),
4549                         bformat(_("Unable to set layout for ID: %1$s"), from_utf8(idString)));
4550 }
4551
4552
4553 bool GuiDocument::isValid()
4554 {
4555         return
4556                 validateListingsParameters().isEmpty() &&
4557                 localLayout->isValid() &&
4558                 !localLayout->editing() &&
4559                 !preambleModule->editing() &&
4560                 (
4561                         // if we're asking for skips between paragraphs
4562                         !textLayoutModule->skipRB->isChecked() ||
4563                         // then either we haven't chosen custom
4564                         textLayoutModule->skipCO->currentIndex() != 3 ||
4565                         // or else a length has been given
4566                         !textLayoutModule->skipLE->text().isEmpty()
4567                 ) &&
4568                 (
4569                         // if we're asking for indentation
4570                         !textLayoutModule->indentRB->isChecked() ||
4571                         // then either we haven't chosen custom
4572                         textLayoutModule->indentCO->currentIndex() != 1 ||
4573                         // or else a length has been given
4574                         !textLayoutModule->indentLE->text().isEmpty()
4575                 ) &&
4576                 (
4577                         // if we're asking for math indentation
4578                         !mathsModule->MathIndentCB->isChecked() ||
4579                         // then either we haven't chosen custom
4580                         mathsModule->MathIndentCO->currentIndex() != 1 ||
4581                         // or else a length has been given
4582                         !mathsModule->MathIndentLE->text().isEmpty()
4583                 );
4584 }
4585
4586
4587 char const * const GuiDocument::fontfamilies[5] = {
4588         "default", "rmdefault", "sfdefault", "ttdefault", ""
4589 };
4590
4591
4592 char const * GuiDocument::fontfamilies_gui[5] = {
4593         N_("Default"), N_("Roman"), N_("Sans Serif"), N_("Typewriter"), ""
4594 };
4595
4596
4597 bool GuiDocument::initialiseParams(string const &)
4598 {
4599         BufferView const * view = bufferview();
4600         if (!view) {
4601                 bp_ = BufferParams();
4602                 paramsToDialog();
4603                 return true;
4604         }
4605         bp_ = view->buffer().params();
4606         loadModuleInfo();
4607         updateAvailableModules();
4608         //FIXME It'd be nice to make sure here that the selected
4609         //modules are consistent: That required modules are actually
4610         //selected, and that we don't have conflicts. If so, we could
4611         //at least pop up a warning.
4612         paramsToDialog();
4613         return true;
4614 }
4615
4616
4617 void GuiDocument::clearParams()
4618 {
4619         bp_ = BufferParams();
4620 }
4621
4622
4623 BufferId GuiDocument::id() const
4624 {
4625         BufferView const * const view = bufferview();
4626         return view? &view->buffer() : 0;
4627 }
4628
4629
4630 list<GuiDocument::modInfoStruct> const & GuiDocument::getModuleInfo()
4631 {
4632         return moduleNames_;
4633 }
4634
4635
4636 list<GuiDocument::modInfoStruct> const
4637 GuiDocument::makeModuleInfo(LayoutModuleList const & mods)
4638 {
4639         list<modInfoStruct> mInfo;
4640         for (string const & name : mods) {
4641                 modInfoStruct m;
4642                 LyXModule const * const mod = theModuleList[name];
4643                 if (mod)
4644                         m = modInfo(*mod);
4645                 else {
4646                         m.id = name;
4647                         m.name = toqstr(name + " (") + qt_("Not Found") + toqstr(")");
4648                         m.local = false;
4649                         m.missingreqs = true;
4650                 }
4651                 mInfo.push_back(m);
4652         }
4653         return mInfo;
4654 }
4655
4656
4657 list<GuiDocument::modInfoStruct> const GuiDocument::getSelectedModules()
4658 {
4659         return makeModuleInfo(params().getModules());
4660 }
4661
4662
4663 list<GuiDocument::modInfoStruct> const GuiDocument::getProvidedModules()
4664 {
4665         return makeModuleInfo(params().baseClass()->providedModules());
4666 }
4667
4668
4669 DocumentClass const & GuiDocument::documentClass() const
4670 {
4671         return bp_.documentClass();
4672 }
4673
4674
4675 static void dispatch_bufferparams(Dialog const & dialog,
4676         BufferParams const & bp, FuncCode lfun, Buffer const * buf)
4677 {
4678         ostringstream ss;
4679         ss << "\\begin_header\n";
4680         bp.writeFile(ss, buf);
4681         ss << "\\end_header\n";
4682         dialog.dispatch(FuncRequest(lfun, ss.str()));
4683 }
4684
4685
4686 void GuiDocument::dispatchParams()
4687 {
4688         // We need a non-const buffer object.
4689         Buffer & buf = const_cast<BufferView *>(bufferview())->buffer();
4690         // There may be several undo records; group them (bug #8998)
4691         // This handles undo groups automagically
4692         UndoGroupHelper ugh(&buf);
4693
4694         // This must come first so that a language change is correctly noticed
4695         setLanguage();
4696
4697         // We need to load the master before we formally update the params,
4698         // since otherwise we run updateBuffer, etc, before the child's master
4699         // has been set.
4700         if (!params().master.empty()) {
4701                 FileName const master_file = support::makeAbsPath(params().master,
4702                            support::onlyPath(buffer().absFileName()));
4703                 if (isLyXFileName(master_file.absFileName())) {
4704                         Buffer * master = checkAndLoadLyXFile(master_file);
4705                         if (master) {
4706                                 if (master->isChild(const_cast<Buffer *>(&buffer())))
4707                                         const_cast<Buffer &>(buffer()).setParent(master);
4708                                 else
4709                                         Alert::warning(_("Assigned master does not include this file"),
4710                                                 bformat(_("You must include this file in the document\n"
4711                                                           "'%1$s' in order to use the master document\n"
4712                                                           "feature."), from_utf8(params().master)));
4713                         } else
4714                                 Alert::warning(_("Could not load master"),
4715                                                 bformat(_("The master document '%1$s'\n"
4716                                                            "could not be loaded."),
4717                                                            from_utf8(params().master)));
4718                 }
4719         }
4720
4721         // Apply the BufferParams. Note that this will set the base class
4722         // and then update the buffer's layout.
4723         dispatch_bufferparams(*this, params(), LFUN_BUFFER_PARAMS_APPLY, &buffer());
4724
4725         // Generate the colours requested by each new branch.
4726         BranchList & branchlist = params().branchlist();
4727         if (!branchlist.empty()) {
4728                 BranchList::const_iterator it = branchlist.begin();
4729                 BranchList::const_iterator const end = branchlist.end();
4730                 for (; it != end; ++it) {
4731                         docstring const & current_branch = it->branch();
4732                         Branch const * branch = branchlist.find(current_branch);
4733                         string const x11hexname = X11hexname(branch->color());
4734                         // display the new color
4735                         docstring const str = current_branch + ' ' + from_ascii(x11hexname);
4736                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
4737                 }
4738         }
4739         // rename branches in the document
4740         executeBranchRenaming();
4741         // and clear changed branches cache
4742         changedBranches_.clear();
4743
4744         // Generate the colours requested by indices.
4745         IndicesList & indiceslist = params().indiceslist();
4746         if (!indiceslist.empty()) {
4747                 IndicesList::const_iterator it = indiceslist.begin();
4748                 IndicesList::const_iterator const end = indiceslist.end();
4749                 for (; it != end; ++it) {
4750                         docstring const & current_index = it->shortcut();
4751                         Index const * index = indiceslist.findShortcut(current_index);
4752                         string const x11hexname = X11hexname(index->color());
4753                         // display the new color
4754                         docstring const str = current_index + ' ' + from_ascii(x11hexname);
4755                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
4756                 }
4757         }
4758         // FIXME LFUN
4759         // If we used an LFUN, we would not need these two lines:
4760         BufferView * bv = const_cast<BufferView *>(bufferview());
4761         bv->processUpdateFlags(Update::Force | Update::FitCursor);
4762 }
4763
4764
4765 void GuiDocument::setLanguage() const
4766 {
4767         Language const * const newL = bp_.language;
4768         if (buffer().params().language == newL)
4769                 return;
4770
4771         string const & lang_name = newL->lang();
4772         dispatch(FuncRequest(LFUN_BUFFER_LANGUAGE, lang_name));
4773 }
4774
4775
4776 void GuiDocument::saveAsDefault() const
4777 {
4778         dispatch_bufferparams(*this, params(), LFUN_BUFFER_SAVE_AS_DEFAULT, &buffer());
4779 }
4780
4781
4782 bool GuiDocument::providesOSF(QString const & font) const
4783 {
4784         if (fontModule->osFontsCB->isChecked())
4785                 // FIXME: we should check if the fonts really
4786                 // have OSF support. But how?
4787                 return true;
4788         return theLaTeXFonts().getLaTeXFont(
4789                                 qstring_to_ucs4(font)).providesOSF(ot1(),
4790                                                                    completeFontset(),
4791                                                                    noMathFont());
4792 }
4793
4794
4795 bool GuiDocument::providesSC(QString const & font) const
4796 {
4797         if (fontModule->osFontsCB->isChecked())
4798                 return false;
4799         return theLaTeXFonts().getLaTeXFont(
4800                                 qstring_to_ucs4(font)).providesSC(ot1(),
4801                                                                   completeFontset(),
4802                                                                   noMathFont());
4803 }
4804
4805
4806 bool GuiDocument::providesScale(QString const & font) const
4807 {
4808         if (fontModule->osFontsCB->isChecked())
4809                 return true;
4810         return theLaTeXFonts().getLaTeXFont(
4811                                 qstring_to_ucs4(font)).providesScale(ot1(),
4812                                                                      completeFontset(),
4813                                                                      noMathFont());
4814 }
4815
4816
4817 bool GuiDocument::providesNoMath(QString const & font) const
4818 {
4819         if (fontModule->osFontsCB->isChecked())
4820                 return false;
4821         return theLaTeXFonts().getLaTeXFont(
4822                                 qstring_to_ucs4(font)).providesNoMath(ot1(),
4823                                                                       completeFontset());
4824 }
4825
4826
4827 bool GuiDocument::hasMonolithicExpertSet(QString const & font) const
4828 {
4829         if (fontModule->osFontsCB->isChecked())
4830                 return false;
4831         return theLaTeXFonts().getLaTeXFont(
4832                                 qstring_to_ucs4(font)).hasMonolithicExpertSet(ot1(),
4833                                                                               completeFontset(),
4834                                                                               noMathFont());
4835 }
4836
4837
4838 //static
4839 GuiDocument::modInfoStruct GuiDocument::modInfo(LyXModule const & mod)
4840 {
4841         // FIXME Unicode: docstrings would be better for these parameters but this
4842         // change requires a lot of others
4843         modInfoStruct m;
4844         m.id = mod.getID();
4845         QString const guiname = toqstr(translateIfPossible(from_utf8(mod.getName())));
4846         m.missingreqs = !isModuleAvailable(mod.getID());
4847         if (m.missingreqs) {
4848                 m.name = QString(qt_("%1 (missing req.)")).arg(guiname);
4849         } else
4850                 m.name = guiname;
4851         m.category = mod.category().empty() ? qt_("Miscellaneous")
4852                                             : toqstr(translateIfPossible(from_utf8(mod.category())));
4853         QString desc = toqstr(translateIfPossible(from_utf8(mod.getDescription())));
4854         // Find the first sentence of the description
4855         QTextBoundaryFinder bf(QTextBoundaryFinder::Sentence, desc);
4856         int pos = bf.toNextBoundary();
4857         if (pos > 0)
4858                 desc.truncate(pos);
4859         m.local = mod.isLocal();
4860         QString const mtype = m.local ? qt_("personal module") : qt_("distributed module");
4861         QString modulename = QString(qt_("<b>Module name:</b> <i>%1</i> (%2)")).arg(toqstr(m.id)).arg(mtype);
4862         // Tooltip is the desc followed by the module name and the type
4863         m.description = QString("%1%2")
4864                 .arg(desc.isEmpty() ? QString() : QString("<p>%1</p>").arg(desc),
4865                      modulename);
4866         if (m.missingreqs)
4867                 m.description += QString("<p>%1</p>").arg(qt_("<b>Note:</b> Some requirements for this module are missing!"));
4868         return m;
4869 }
4870
4871
4872 void GuiDocument::loadModuleInfo()
4873 {
4874         moduleNames_.clear();
4875         for (LyXModule const & mod : theModuleList)
4876                 moduleNames_.push_back(modInfo(mod));
4877 }
4878
4879
4880 void GuiDocument::updateUnknownBranches()
4881 {
4882         if (!bufferview())
4883                 return;
4884         list<docstring> used_branches;
4885         buffer().getUsedBranches(used_branches);
4886         list<docstring>::const_iterator it = used_branches.begin();
4887         QStringList unknown_branches;
4888         for (; it != used_branches.end() ; ++it) {
4889                 if (!buffer().params().branchlist().find(*it))
4890                         unknown_branches.append(toqstr(*it));
4891         }
4892         branchesModule->setUnknownBranches(unknown_branches);
4893 }
4894
4895
4896 void GuiDocument::branchesRename(docstring const & oldname, docstring const & newname)
4897 {
4898         map<docstring, docstring>::iterator it = changedBranches_.begin();
4899         for (; it != changedBranches_.end() ; ++it) {
4900                 if (it->second == oldname) {
4901                         // branch has already been renamed
4902                         it->second = newname;
4903                         return;
4904                 }
4905         }
4906         // store new name
4907         changedBranches_[oldname] = newname;
4908 }
4909
4910
4911 void GuiDocument::executeBranchRenaming() const
4912 {
4913         map<docstring, docstring>::const_iterator it = changedBranches_.begin();
4914         for (; it != changedBranches_.end() ; ++it) {
4915                 docstring const arg = '"' + it->first + '"' + " " + '"' + it->second + '"';
4916                 dispatch(FuncRequest(LFUN_BRANCHES_RENAME, arg));
4917         }
4918 }
4919
4920
4921 void GuiDocument::allPackagesAuto()
4922 {
4923         allPackages(1);
4924 }
4925
4926
4927 void GuiDocument::allPackagesAlways()
4928 {
4929         allPackages(2);
4930 }
4931
4932
4933 void GuiDocument::allPackagesNot()
4934 {
4935         allPackages(3);
4936 }
4937
4938
4939 void GuiDocument::allPackages(int col)
4940 {
4941         for (int row = 0; row < mathsModule->packagesTW->rowCount(); ++row) {
4942                 QRadioButton * rb =
4943                         (QRadioButton*)mathsModule->packagesTW->cellWidget(row, col)->layout()->itemAt(0)->widget();
4944                 rb->setChecked(true);
4945         }
4946 }
4947
4948
4949 void GuiDocument::linenoToggled(bool on)
4950 {
4951         numberingModule->linenoLE->setEnabled(on);
4952         numberingModule->linenoLA->setEnabled(on);
4953 }
4954
4955
4956
4957 Dialog * createGuiDocument(GuiView & lv) { return new GuiDocument(lv); }
4958
4959
4960 } // namespace frontend
4961 } // namespace lyx
4962
4963 #include "moc_GuiDocument.cpp"