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