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