]> git.lyx.org Git - features.git/blob - src/frontends/qt4/GuiDocument.cpp
* GuiDocument.cpp:
[features.git] / src / frontends / qt4 / GuiDocument.cpp
1 /**
2  * \file GuiDocument.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Edwin Leuven
7  * \author Richard Heck (modules)
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "GuiDocument.h"
15
16 #include "GuiApplication.h"
17 #include "GuiBranches.h"
18 #include "GuiIndices.h"
19 #include "GuiSelectionManager.h"
20 #include "LaTeXHighlighter.h"
21 #include "LengthCombo.h"
22 #include "PanelStack.h"
23 #include "Validator.h"
24
25 #include "LayoutFile.h"
26 #include "BranchList.h"
27 #include "buffer_funcs.h"
28 #include "Buffer.h"
29 #include "BufferParams.h"
30 #include "BufferView.h"
31 #include "Color.h"
32 #include "ColorCache.h"
33 #include "Encoding.h"
34 #include "FloatPlacement.h"
35 #include "Format.h"
36 #include "FuncRequest.h"
37 #include "IndicesList.h"
38 #include "Language.h"
39 #include "LaTeXFeatures.h"
40 #include "Layout.h"
41 #include "LayoutModuleList.h"
42 #include "LyXRC.h"
43 #include "ModuleList.h"
44 #include "OutputParams.h"
45 #include "PDFOptions.h"
46 #include "qt_helpers.h"
47 #include "Spacing.h"
48
49 #include "insets/InsetListingsParams.h"
50
51 #include "support/debug.h"
52 #include "support/FileName.h"
53 #include "support/filetools.h"
54 #include "support/gettext.h"
55 #include "support/lstrings.h"
56
57 #include "frontends/alert.h"
58
59 #include <QAbstractItemModel>
60 #include <QColor>
61 #include <QColorDialog>
62 #include <QCloseEvent>
63 #include <QFontDatabase>
64 #include <QScrollBar>
65 #include <QTextCursor>
66
67 #include <sstream>
68 #include <vector>
69
70 #ifdef IN
71 #undef IN
72 #endif
73
74
75 // a style sheet for buttons
76 // this is for example used for the background color setting button
77 static inline QString colorButtonStyleSheet(QColor const & bgColor)
78 {
79         if (bgColor.isValid()) {
80                 QString rc = QLatin1String("background:");
81                 rc += bgColor.name();
82                 return rc;
83         }
84         return QString();
85 }
86
87
88 using namespace std;
89 using namespace lyx::support;
90
91
92 namespace {
93
94 char const * const tex_graphics[] =
95 {
96         "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
97         "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
98         "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
99         "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
100         "xetex", "none", ""
101 };
102
103
104 char const * const tex_graphics_gui[] =
105 {
106         N_("Default"), "dvialw", "DviLaser", "dvipdf", "DVIPDFM", "DVIPDFMx",
107         "Dvips", "DVIPSONE", "DVItoPS", "DVIWIN", "DVIWindo", "dvi2ps", "EmTeX",
108         "LN", "OzTeX", "pctexhp", "pctexps", "pctexwin", "PCTeX32", "pdfTeX",
109         "psprint", "pubps", "tcidvi", "Textures", "TrueTeX", "VTeX", "xdvi",
110         "XeTeX", N_("None"), ""
111 };
112
113
114 char const * const tex_fonts_roman[] =
115 {
116         "default", "cmr", "lmodern", "ae", "times", "palatino",
117         "charter", "newcent", "bookman", "utopia", "beraserif",
118         "ccfonts", "chancery", ""
119 };
120
121
122 char const * tex_fonts_roman_gui[] =
123 {
124         N_("Default"), N_("Computer Modern Roman"), N_("Latin Modern Roman"),
125         N_("AE (Almost European)"), N_("Times Roman"), N_("Palatino"),
126         N_("Bitstream Charter"), N_("New Century Schoolbook"), N_("Bookman"),
127         N_("Utopia"),  N_("Bera Serif"), N_("Concrete Roman"), N_("Zapf Chancery"),
128         ""
129 };
130
131
132 char const * const tex_fonts_sans[] =
133 {
134         "default", "cmss", "lmss", "helvet", "avant", "berasans", "cmbr", ""
135 };
136
137
138 char const * tex_fonts_sans_gui[] =
139 {
140         N_("Default"), N_("Computer Modern Sans"), N_("Latin Modern Sans"),
141         N_("Helvetica"), N_("Avant Garde"), N_("Bera Sans"), N_("CM Bright"), ""
142 };
143
144
145 char const * const tex_fonts_monospaced[] =
146 {
147         "default", "cmtt", "lmtt", "courier", "beramono", "luximono", "cmtl", ""
148 };
149
150
151 char const * tex_fonts_monospaced_gui[] =
152 {
153         N_("Default"), N_("Computer Modern Typewriter"),
154         N_("Latin Modern Typewriter"), N_("Courier"), N_("Bera Mono"),
155         N_("LuxiMono"), N_("CM Typewriter Light"), ""
156 };
157
158
159 char const * backref_opts[] =
160 {
161         "false", "section", "slide", "page", ""
162 };
163
164
165 char const * backref_opts_gui[] =
166 {
167         N_("Off"), N_("Section"), N_("Slide"), N_("Page"), ""
168 };
169
170
171 vector<pair<string, QString> > pagestyles;
172
173
174 } // anonymous namespace
175
176 namespace lyx {
177
178 RGBColor set_backgroundcolor;
179
180 namespace {
181 // used when sorting the textclass list.
182 class less_textclass_avail_desc
183         : public binary_function<string, string, int>
184 {
185 public:
186         bool operator()(string const & lhs, string const & rhs) const
187         {
188                 // Ordering criteria:
189                 //   1. Availability of text class
190                 //   2. Description (lexicographic)
191                 LayoutFile const & tc1 = LayoutFileList::get()[lhs];
192                 LayoutFile const & tc2 = LayoutFileList::get()[rhs];
193                 int const rel = compare_no_case(
194                         translateIfPossible(from_utf8(tc1.description())),
195                         translateIfPossible(from_utf8(tc2.description())));
196                 return (tc1.isTeXClassAvailable() && !tc2.isTeXClassAvailable()) ||
197                         (tc1.isTeXClassAvailable() == tc2.isTeXClassAvailable() && rel < 0);
198         }
199 };
200
201 }
202
203 namespace frontend {
204 namespace {
205
206 vector<string> getRequiredList(string const & modName) 
207 {
208         LyXModule const * const mod = moduleList[modName];
209         if (!mod)
210                 return vector<string>(); //empty such thing
211         return mod->getRequiredModules();
212 }
213
214
215 vector<string> getExcludedList(string const & modName)
216 {
217         LyXModule const * const mod = moduleList[modName];
218         if (!mod)
219                 return vector<string>(); //empty such thing
220         return mod->getExcludedModules();
221 }
222
223
224 docstring getModuleDescription(string const & modName)
225 {
226         LyXModule const * const mod = moduleList[modName];
227         if (!mod)
228                 return _("Module not found!");
229         // FIXME Unicode
230         return translateIfPossible(from_utf8(mod->getDescription()));
231 }
232
233
234 vector<string> getPackageList(string const & modName)
235 {
236         LyXModule const * const mod = moduleList[modName];
237         if (!mod)
238                 return vector<string>(); //empty such thing
239         return mod->getPackageList();
240 }
241
242
243 bool isModuleAvailable(string const & modName)
244 {
245         LyXModule * mod = moduleList[modName];
246         if (!mod)
247                 return false;
248         return mod->isAvailable();
249 }
250
251 } // anonymous namespace
252
253
254 /////////////////////////////////////////////////////////////////////
255 //
256 // ModuleSelectionManager
257 //
258 /////////////////////////////////////////////////////////////////////
259
260 /// SelectionManager for use with modules
261 class ModuleSelectionManager : public GuiSelectionManager 
262 {
263 public:
264         ///
265         ModuleSelectionManager(
266                 QListView * availableLV, 
267                 QListView * selectedLV,
268                 QPushButton * addPB, 
269                 QPushButton * delPB, 
270                 QPushButton * upPB, 
271                 QPushButton * downPB,
272                 GuiIdListModel * availableModel,
273                 GuiIdListModel * selectedModel,
274                 GuiDocument const * container)
275         : GuiSelectionManager(availableLV, selectedLV, addPB, delPB,
276                                 upPB, downPB, availableModel, selectedModel), container_(container)
277                 {}
278         ///
279         void updateProvidedModules(LayoutModuleList const & pm) 
280                         { provided_modules_ = pm.list(); }
281         ///
282         void updateExcludedModules(LayoutModuleList const & em) 
283                         { excluded_modules_ = em.list(); }
284 private:
285         ///
286         virtual void updateAddPB();
287         ///
288         virtual void updateUpPB();
289         ///
290         virtual void updateDownPB();
291         ///
292         virtual void updateDelPB();
293         /// returns availableModel as a GuiIdListModel
294         GuiIdListModel * getAvailableModel() 
295         {
296                 return dynamic_cast<GuiIdListModel *>(availableModel);
297         }
298         /// returns selectedModel as a GuiIdListModel
299         GuiIdListModel * getSelectedModel() 
300         {
301                 return dynamic_cast<GuiIdListModel *>(selectedModel);
302         }
303         /// keeps a list of the modules the text class provides
304         std::list<std::string> provided_modules_;
305         /// similarly...
306         std::list<std::string> excluded_modules_;
307         /// 
308         GuiDocument const * container_;
309 };
310
311 void ModuleSelectionManager::updateAddPB() 
312 {
313         int const arows = availableModel->rowCount();
314         QModelIndexList const avail_sels = 
315                         availableLV->selectionModel()->selectedIndexes();
316
317         // disable if there aren't any modules (?), if none of them is chosen
318         // in the dialog, or if the chosen one is already selected for use.
319         if (arows == 0 || avail_sels.isEmpty() || isSelected(avail_sels.first())) {
320                 addPB->setEnabled(false);
321                 return;
322         }
323
324         QModelIndex const & idx = availableLV->selectionModel()->currentIndex();
325         string const modname = getAvailableModel()->getIDString(idx.row());
326
327         bool const enable = 
328                 container_->params().moduleCanBeAdded(modname);
329         addPB->setEnabled(enable);
330 }
331
332
333 void ModuleSelectionManager::updateDownPB()
334 {
335         int const srows = selectedModel->rowCount();
336         if (srows == 0) {
337                 downPB->setEnabled(false);
338                 return;
339         }
340         QModelIndex const & curidx = selectedLV->selectionModel()->currentIndex();
341         int const curRow = curidx.row();
342         if (curRow < 0 || curRow >= srows - 1) { // invalid or last item
343                 downPB->setEnabled(false);
344                 return;
345         }
346
347         // determine whether immediately succeding element requires this one
348         string const curmodname = getSelectedModel()->getIDString(curRow);
349         string const nextmodname = getSelectedModel()->getIDString(curRow + 1);
350
351         vector<string> reqs = getRequiredList(nextmodname);
352
353         // if it doesn't require anything....
354         if (reqs.empty()) {
355                 downPB->setEnabled(true);
356                 return;
357         }
358
359         // Enable it if this module isn't required.
360         // FIXME This should perhaps be more flexible and check whether, even 
361         // if the next one is required, there is also an earlier one that will do.
362         downPB->setEnabled(
363                         find(reqs.begin(), reqs.end(), curmodname) == reqs.end());
364 }
365
366 void ModuleSelectionManager::updateUpPB() 
367 {
368         int const srows = selectedModel->rowCount();
369         if (srows == 0) {
370                 upPB->setEnabled(false);
371                 return;
372         }
373
374         QModelIndex const & curIdx = selectedLV->selectionModel()->currentIndex();
375         int curRow = curIdx.row();
376         if (curRow <= 0 || curRow > srows - 1) { // first item or invalid
377                 upPB->setEnabled(false);
378                 return;
379         }
380         string const curmodname = getSelectedModel()->getIDString(curRow);
381
382         // determine whether immediately preceding element is required by this one
383         vector<string> reqs = getRequiredList(curmodname);
384
385         // if this one doesn't require anything....
386         if (reqs.empty()) {
387                 upPB->setEnabled(true);
388                 return;
389         }
390
391
392         // Enable it if the preceding module isn't required.
393         // NOTE This is less flexible than it might be. We could check whether, even 
394         // if the previous one is required, there is an earlier one that would do.
395         string const premod = getSelectedModel()->getIDString(curRow - 1);
396         upPB->setEnabled(find(reqs.begin(), reqs.end(), premod) == reqs.end());
397 }
398
399 void ModuleSelectionManager::updateDelPB() 
400 {
401         int const srows = selectedModel->rowCount();
402         if (srows == 0) {
403                 deletePB->setEnabled(false);
404                 return;
405         }
406
407         QModelIndex const & curidx = 
408                 selectedLV->selectionModel()->currentIndex();
409         int const curRow = curidx.row();
410         if (curRow < 0 || curRow >= srows) { // invalid index?
411                 deletePB->setEnabled(false);
412                 return;
413         }
414
415         string const curmodname = getSelectedModel()->getIDString(curRow);
416
417         // We're looking here for a reason NOT to enable the button. If we
418         // find one, we disable it and return. If we don't, we'll end up at
419         // the end of the function, and then we enable it.
420         for (int i = curRow + 1; i < srows; ++i) {
421                 string const thisMod = getSelectedModel()->getIDString(i);
422                 vector<string> reqs = getRequiredList(thisMod);
423                 //does this one require us?
424                 if (find(reqs.begin(), reqs.end(), curmodname) == reqs.end())
425                         //no...
426                         continue;
427
428                 // OK, so this module requires us
429                 // is there an EARLIER module that also satisfies the require?
430                 // NOTE We demand that it be earlier to keep the list of modules
431                 // consistent with the rule that a module must be proceeded by a
432                 // required module. There would be more flexible ways to proceed,
433                 // but that would be a lot more complicated, and the logic here is
434                 // already complicated. (That's why I've left the debugging code.)
435                 // lyxerr << "Testing " << thisMod << std::endl;
436                 bool foundone = false;
437                 for (int j = 0; j < curRow; ++j) {
438                         string const mod = getSelectedModel()->getIDString(j);
439                         // lyxerr << "In loop: Testing " << mod << std::endl;
440                         // do we satisfy the require? 
441                         if (find(reqs.begin(), reqs.end(), mod) != reqs.end()) {
442                                 // lyxerr << mod << " does the trick." << std::endl;
443                                 foundone = true;
444                                 break;
445                         }
446                 }
447                 // did we find a module to satisfy the require?
448                 if (!foundone) {
449                         // lyxerr << "No matching module found." << std::endl;
450                         deletePB->setEnabled(false);
451                         return;
452                 }
453         }
454         // lyxerr << "All's well that ends well." << std::endl; 
455         deletePB->setEnabled(true);
456 }
457
458
459 /////////////////////////////////////////////////////////////////////
460 //
461 // PreambleModule
462 //
463 /////////////////////////////////////////////////////////////////////
464
465 PreambleModule::PreambleModule() : current_id_(0)
466 {
467         // This is not a memory leak. The object will be destroyed
468         // with this.
469         (void) new LaTeXHighlighter(preambleTE->document());
470         setFocusProxy(preambleTE);
471         connect(preambleTE, SIGNAL(textChanged()), this, SIGNAL(changed()));
472 }
473
474
475 void PreambleModule::update(BufferParams const & params, BufferId id)
476 {
477         QString preamble = toqstr(params.preamble);
478         // Nothing to do if the params and preamble are unchanged.
479         if (id == current_id_
480                 && preamble == preambleTE->document()->toPlainText())
481                 return;
482
483         QTextCursor cur = preambleTE->textCursor();
484         // Save the coords before switching to the new one.
485         preamble_coords_[current_id_] =
486                 make_pair(cur.position(), preambleTE->verticalScrollBar()->value());
487
488         // Save the params address for further use.
489         current_id_ = id;
490         preambleTE->document()->setPlainText(preamble);
491         Coords::const_iterator it = preamble_coords_.find(current_id_);
492         if (it == preamble_coords_.end())
493                 // First time we open this one.
494                 preamble_coords_[current_id_] = make_pair(0, 0);
495         else {
496                 // Restore saved coords.
497                 QTextCursor cur = preambleTE->textCursor();
498                 cur.setPosition(it->second.first);
499                 preambleTE->setTextCursor(cur);
500                 preambleTE->verticalScrollBar()->setValue(it->second.second);
501         }
502 }
503
504
505 void PreambleModule::apply(BufferParams & params)
506 {
507         params.preamble = fromqstr(preambleTE->document()->toPlainText());
508 }
509
510
511 void PreambleModule::closeEvent(QCloseEvent * e)
512 {
513         // Save the coords before closing.
514         QTextCursor cur = preambleTE->textCursor();
515         preamble_coords_[current_id_] =
516                 make_pair(cur.position(), preambleTE->verticalScrollBar()->value());
517         e->accept();
518 }
519
520
521 /////////////////////////////////////////////////////////////////////
522 //
523 // DocumentDialog
524 //
525 /////////////////////////////////////////////////////////////////////
526
527
528 GuiDocument::GuiDocument(GuiView & lv)
529         : GuiDialog(lv, "document", qt_("Document Settings"))
530 {
531         setupUi(this);
532
533         connect(okPB, SIGNAL(clicked()), this, SLOT(slotOK()));
534         connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
535         connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
536         connect(restorePB, SIGNAL(clicked()), this, SLOT(slotRestore()));
537
538         connect(savePB, SIGNAL(clicked()), this, SLOT(saveDefaultClicked()));
539         connect(defaultPB, SIGNAL(clicked()), this, SLOT(useDefaultsClicked()));
540
541         // Manage the restore, ok, apply, restore and cancel/close buttons
542         bc().setPolicy(ButtonPolicy::NoRepeatedApplyReadOnlyPolicy);
543         bc().setOK(okPB);
544         bc().setApply(applyPB);
545         bc().setCancel(closePB);
546         bc().setRestore(restorePB);
547
548         textLayoutModule = new UiWidget<Ui::TextLayoutUi>;
549         // text layout
550         connect(textLayoutModule->lspacingCO, SIGNAL(activated(int)),
551                 this, SLOT(change_adaptor()));
552         connect(textLayoutModule->lspacingCO, SIGNAL(activated(int)),
553                 this, SLOT(setLSpacing(int)));
554         connect(textLayoutModule->lspacingLE, SIGNAL(textChanged(const QString &)),
555                 this, SLOT(change_adaptor()));
556         connect(textLayoutModule->skipRB, SIGNAL(clicked()),
557                 this, SLOT(change_adaptor()));
558         connect(textLayoutModule->indentRB, SIGNAL(clicked()),
559                 this, SLOT(change_adaptor()));
560         connect(textLayoutModule->skipCO, SIGNAL(activated(int)),
561                 this, SLOT(change_adaptor()));
562         connect(textLayoutModule->skipLE, SIGNAL(textChanged(const QString &)),
563                 this, SLOT(change_adaptor()));
564         connect(textLayoutModule->skipLengthCO, SIGNAL(activated(int)),
565                 this, SLOT(change_adaptor()));
566         connect(textLayoutModule->skipCO, SIGNAL(activated(int)),
567                 this, SLOT(setSkip(int)));
568         connect(textLayoutModule->skipRB, SIGNAL(toggled(bool)),
569                 this, SLOT(enableSkip(bool)));
570         connect(textLayoutModule->twoColumnCB, SIGNAL(clicked()),
571                 this, SLOT(change_adaptor()));
572         connect(textLayoutModule->twoColumnCB, SIGNAL(clicked()),
573                 this, SLOT(setColSep()));
574         connect(textLayoutModule->listingsED, SIGNAL(textChanged()),
575                 this, SLOT(change_adaptor()));
576         connect(textLayoutModule->bypassCB, SIGNAL(clicked()), 
577                 this, SLOT(change_adaptor()));
578         connect(textLayoutModule->bypassCB, SIGNAL(clicked()), 
579                 this, SLOT(setListingsMessage()));
580         connect(textLayoutModule->listingsED, SIGNAL(textChanged()),
581                 this, SLOT(setListingsMessage()));
582         textLayoutModule->listingsTB->setPlainText(
583                 qt_("Input listings parameters on the right. Enter ? for a list of parameters."));
584         textLayoutModule->lspacingLE->setValidator(new QDoubleValidator(
585                 textLayoutModule->lspacingLE));
586         textLayoutModule->skipLE->setValidator(unsignedLengthValidator(
587                 textLayoutModule->skipLE));
588
589         textLayoutModule->skipCO->addItem(qt_("SmallSkip"));
590         textLayoutModule->skipCO->addItem(qt_("MedSkip"));
591         textLayoutModule->skipCO->addItem(qt_("BigSkip"));
592         textLayoutModule->skipCO->addItem(qt_("Length"));
593         // remove the %-items from the unit choice
594         textLayoutModule->skipLengthCO->noPercents();
595         textLayoutModule->lspacingCO->insertItem(
596                 Spacing::Single, qt_("Single"));
597         textLayoutModule->lspacingCO->insertItem(
598                 Spacing::Onehalf, qt_("OneHalf"));
599         textLayoutModule->lspacingCO->insertItem(
600                 Spacing::Double, qt_("Double"));
601         textLayoutModule->lspacingCO->insertItem(
602                 Spacing::Other, qt_("Custom"));
603
604         // initialize the length validator
605         bc().addCheckedLineEdit(textLayoutModule->skipLE);
606
607         // output
608         outputModule = new UiWidget<Ui::OutputUi>;
609
610         connect(outputModule->xetexCB, SIGNAL(clicked()),
611                 this, SLOT(change_adaptor()));
612         connect(outputModule->xetexCB, SIGNAL(toggled(bool)),
613                 this, SLOT(xetexChanged(bool)));
614         connect(outputModule->defaultFormatCO, SIGNAL(activated(int)),
615                 this, SLOT(change_adaptor()));
616
617         // fonts
618         fontModule = new UiWidget<Ui::FontUi>;
619         connect(fontModule->fontsRomanCO, SIGNAL(activated(int)),
620                 this, SLOT(change_adaptor()));
621         connect(fontModule->fontsRomanCO, SIGNAL(activated(int)),
622                 this, SLOT(romanChanged(int)));
623         connect(fontModule->fontsSansCO, SIGNAL(activated(int)),
624                 this, SLOT(change_adaptor()));
625         connect(fontModule->fontsSansCO, SIGNAL(activated(int)),
626                 this, SLOT(sansChanged(int)));
627         connect(fontModule->fontsTypewriterCO, SIGNAL(activated(int)),
628                 this, SLOT(change_adaptor()));
629         connect(fontModule->fontsTypewriterCO, SIGNAL(activated(int)),
630                 this, SLOT(ttChanged(int)));
631         connect(fontModule->fontsDefaultCO, SIGNAL(activated(int)),
632                 this, SLOT(change_adaptor()));
633         connect(fontModule->fontsizeCO, SIGNAL(activated(int)),
634                 this, SLOT(change_adaptor()));
635         connect(fontModule->cjkFontLE, SIGNAL(textChanged(const QString &)),
636                 this, SLOT(change_adaptor()));
637         connect(fontModule->scaleSansSB, SIGNAL(valueChanged(int)),
638                 this, SLOT(change_adaptor()));
639         connect(fontModule->scaleTypewriterSB, SIGNAL(valueChanged(int)),
640                 this, SLOT(change_adaptor()));
641         connect(fontModule->fontScCB, SIGNAL(clicked()),
642                 this, SLOT(change_adaptor()));
643         connect(fontModule->fontOsfCB, SIGNAL(clicked()),
644                 this, SLOT(change_adaptor()));
645
646         updateFontlist();
647
648         fontModule->fontsizeCO->addItem(qt_("Default"));
649         fontModule->fontsizeCO->addItem(qt_("10"));
650         fontModule->fontsizeCO->addItem(qt_("11"));
651         fontModule->fontsizeCO->addItem(qt_("12"));
652
653         for (int n = 0; GuiDocument::fontfamilies_gui[n][0]; ++n)
654                 fontModule->fontsDefaultCO->addItem(
655                         qt_(GuiDocument::fontfamilies_gui[n]));
656
657
658         pageLayoutModule = new UiWidget<Ui::PageLayoutUi>;
659         // page layout
660         connect(pageLayoutModule->papersizeCO, SIGNAL(activated(int)),
661                 this, SLOT(setCustomPapersize(int)));
662         connect(pageLayoutModule->papersizeCO, SIGNAL(activated(int)),
663                 this, SLOT(setCustomPapersize(int)));
664         connect(pageLayoutModule->portraitRB, SIGNAL(clicked()),
665                 this, SLOT(portraitChanged()));
666         connect(pageLayoutModule->papersizeCO, SIGNAL(activated(int)),
667                 this, SLOT(change_adaptor()));
668         connect(pageLayoutModule->paperheightLE, SIGNAL(textChanged(const QString &)),
669                 this, SLOT(change_adaptor()));
670         connect(pageLayoutModule->paperwidthLE, SIGNAL(textChanged(const QString &)),
671                 this, SLOT(change_adaptor()));
672         connect(pageLayoutModule->paperwidthUnitCO, SIGNAL(activated(int)),
673                 this, SLOT(change_adaptor()));
674         connect(pageLayoutModule->paperheightUnitCO, SIGNAL(activated(int)),
675                 this, SLOT(change_adaptor()));
676         connect(pageLayoutModule->portraitRB, SIGNAL(clicked()),
677                 this, SLOT(change_adaptor()));
678         connect(pageLayoutModule->landscapeRB, SIGNAL(clicked()),
679                 this, SLOT(change_adaptor()));
680         connect(pageLayoutModule->facingPagesCB, SIGNAL(clicked()),
681                 this, SLOT(change_adaptor()));
682         connect(pageLayoutModule->pagestyleCO, SIGNAL(activated(int)),
683                 this, SLOT(change_adaptor()));
684         connect(pageLayoutModule->backgroundPB, SIGNAL(clicked()),
685                 this, SLOT(changeBackgroundColor()));
686         connect(pageLayoutModule->delbackgroundTB, SIGNAL(clicked()),
687                 this, SLOT(deleteBackgroundColor()));
688
689         pageLayoutModule->pagestyleCO->addItem(qt_("Default"));
690         pageLayoutModule->pagestyleCO->addItem(qt_("empty"));
691         pageLayoutModule->pagestyleCO->addItem(qt_("plain"));
692         pageLayoutModule->pagestyleCO->addItem(qt_("headings"));
693         pageLayoutModule->pagestyleCO->addItem(qt_("fancy"));
694         bc().addCheckedLineEdit(pageLayoutModule->paperheightLE,
695                 pageLayoutModule->paperheightL);
696         bc().addCheckedLineEdit(pageLayoutModule->paperwidthLE,
697                 pageLayoutModule->paperwidthL);
698
699         // paper
700         QComboBox * cb = pageLayoutModule->papersizeCO;
701         cb->addItem(qt_("Default"));
702         cb->addItem(qt_("Custom"));
703         cb->addItem(qt_("US letter"));
704         cb->addItem(qt_("US legal"));
705         cb->addItem(qt_("US executive"));
706         cb->addItem(qt_("A3"));
707         cb->addItem(qt_("A4"));
708         cb->addItem(qt_("A5"));
709         cb->addItem(qt_("B3"));
710         cb->addItem(qt_("B4"));
711         cb->addItem(qt_("B5"));
712         // remove the %-items from the unit choice
713         pageLayoutModule->paperwidthUnitCO->noPercents();
714         pageLayoutModule->paperheightUnitCO->noPercents();
715         pageLayoutModule->paperheightLE->setValidator(unsignedLengthValidator(
716                 pageLayoutModule->paperheightLE));
717         pageLayoutModule->paperwidthLE->setValidator(unsignedLengthValidator(
718                 pageLayoutModule->paperwidthLE));
719
720
721         marginsModule = new UiWidget<Ui::MarginsUi>;
722         // margins
723         connect(marginsModule->marginCB, SIGNAL(toggled(bool)),
724                 this, SLOT(setCustomMargins(bool)));
725         connect(marginsModule->marginCB, SIGNAL(clicked()),
726                 this, SLOT(change_adaptor()));
727         connect(marginsModule->topLE, SIGNAL(textChanged(QString)),
728                 this, SLOT(change_adaptor()));
729         connect(marginsModule->topUnit, SIGNAL(activated(int)),
730                 this, SLOT(change_adaptor()));
731         connect(marginsModule->bottomLE, SIGNAL(textChanged(QString)),
732                 this, SLOT(change_adaptor()));
733         connect(marginsModule->bottomUnit, SIGNAL(activated(int)),
734                 this, SLOT(change_adaptor()));
735         connect(marginsModule->innerLE, SIGNAL(textChanged(QString)),
736                 this, SLOT(change_adaptor()));
737         connect(marginsModule->innerUnit, SIGNAL(activated(int)),
738                 this, SLOT(change_adaptor()));
739         connect(marginsModule->outerLE, SIGNAL(textChanged(QString)),
740                 this, SLOT(change_adaptor()));
741         connect(marginsModule->outerUnit, SIGNAL(activated(int)),
742                 this, SLOT(change_adaptor()));
743         connect(marginsModule->headheightLE, SIGNAL(textChanged(QString)),
744                 this, SLOT(change_adaptor()));
745         connect(marginsModule->headheightUnit, SIGNAL(activated(int)),
746                 this, SLOT(change_adaptor()));
747         connect(marginsModule->headsepLE, SIGNAL(textChanged(QString)),
748                 this, SLOT(change_adaptor()));
749         connect(marginsModule->headsepUnit, SIGNAL(activated(int)),
750                 this, SLOT(change_adaptor()));
751         connect(marginsModule->footskipLE, SIGNAL(textChanged(QString)),
752                 this, SLOT(change_adaptor()));
753         connect(marginsModule->footskipUnit, SIGNAL(activated(int)),
754                 this, SLOT(change_adaptor()));
755         connect(marginsModule->columnsepLE, SIGNAL(textChanged(QString)),
756                 this, SLOT(change_adaptor()));
757         connect(marginsModule->columnsepUnit, SIGNAL(activated(int)),
758                 this, SLOT(change_adaptor()));
759         marginsModule->topLE->setValidator(unsignedLengthValidator(
760                 marginsModule->topLE));
761         marginsModule->bottomLE->setValidator(unsignedLengthValidator(
762                 marginsModule->bottomLE));
763         marginsModule->innerLE->setValidator(unsignedLengthValidator(
764                 marginsModule->innerLE));
765         marginsModule->outerLE->setValidator(unsignedLengthValidator(
766                 marginsModule->outerLE));
767         marginsModule->headsepLE->setValidator(unsignedLengthValidator(
768                 marginsModule->headsepLE));
769         marginsModule->headheightLE->setValidator(unsignedLengthValidator(
770                 marginsModule->headheightLE));
771         marginsModule->footskipLE->setValidator(unsignedLengthValidator(
772                 marginsModule->footskipLE));
773         marginsModule->columnsepLE->setValidator(unsignedLengthValidator(
774                 marginsModule->columnsepLE));
775
776         bc().addCheckedLineEdit(marginsModule->topLE,
777                 marginsModule->topL);
778         bc().addCheckedLineEdit(marginsModule->bottomLE,
779                 marginsModule->bottomL);
780         bc().addCheckedLineEdit(marginsModule->innerLE,
781                 marginsModule->innerL);
782         bc().addCheckedLineEdit(marginsModule->outerLE,
783                 marginsModule->outerL);
784         bc().addCheckedLineEdit(marginsModule->headsepLE,
785                 marginsModule->headsepL);
786         bc().addCheckedLineEdit(marginsModule->headheightLE,
787                 marginsModule->headheightL);
788         bc().addCheckedLineEdit(marginsModule->footskipLE,
789                 marginsModule->footskipL);
790         bc().addCheckedLineEdit(marginsModule->columnsepLE,
791                 marginsModule->columnsepL);
792
793
794         langModule = new UiWidget<Ui::LanguageUi>;
795         // language & quote
796         connect(langModule->languageCO, SIGNAL(activated(int)),
797                 this, SLOT(change_adaptor()));
798         connect(langModule->defaultencodingRB, SIGNAL(clicked()),
799                 this, SLOT(change_adaptor()));
800         connect(langModule->otherencodingRB, SIGNAL(clicked()),
801                 this, SLOT(change_adaptor()));
802         connect(langModule->encodingCO, SIGNAL(activated(int)),
803                 this, SLOT(change_adaptor()));
804         connect(langModule->quoteStyleCO, SIGNAL(activated(int)),
805                 this, SLOT(change_adaptor()));
806         // language & quotes
807         QAbstractItemModel * language_model = guiApp->languageModel();
808         // FIXME: it would be nice if sorting was enabled/disabled via a checkbox.
809         language_model->sort(0);
810         langModule->languageCO->setModel(language_model);
811
812         // Always put the default encoding in the first position.
813         langModule->encodingCO->addItem(qt_("Language Default (no inputenc)"));
814         QStringList encodinglist;
815         Encodings::const_iterator it = encodings.begin();
816         Encodings::const_iterator const end = encodings.end();
817         for (; it != end; ++it)
818                 encodinglist.append(qt_(it->guiName()));
819         encodinglist.sort();
820         langModule->encodingCO->addItems(encodinglist);
821
822         langModule->quoteStyleCO->addItem(qt_("``text''"));
823         langModule->quoteStyleCO->addItem(qt_("''text''"));
824         langModule->quoteStyleCO->addItem(qt_(",,text``"));
825         langModule->quoteStyleCO->addItem(qt_(",,text''"));
826         langModule->quoteStyleCO->addItem(qt_("<<text>>"));
827         langModule->quoteStyleCO->addItem(qt_(">>text<<"));
828
829
830         numberingModule = new UiWidget<Ui::NumberingUi>;
831         // numbering
832         connect(numberingModule->depthSL, SIGNAL(valueChanged(int)),
833                 this, SLOT(change_adaptor()));
834         connect(numberingModule->tocSL, SIGNAL(valueChanged(int)),
835                 this, SLOT(change_adaptor()));
836         connect(numberingModule->depthSL, SIGNAL(valueChanged(int)),
837                 this, SLOT(updateNumbering()));
838         connect(numberingModule->tocSL, SIGNAL(valueChanged(int)),
839                 this, SLOT(updateNumbering()));
840         numberingModule->tocTW->setColumnCount(3);
841         numberingModule->tocTW->headerItem()->setText(0, qt_("Example"));
842         numberingModule->tocTW->headerItem()->setText(1, qt_("Numbered"));
843         numberingModule->tocTW->headerItem()->setText(2, qt_("Appears in TOC"));
844
845
846         biblioModule = new UiWidget<Ui::BiblioUi>;
847         connect(biblioModule->citeNatbibRB, SIGNAL(toggled(bool)),
848                 biblioModule->citationStyleL, SLOT(setEnabled(bool)));
849         connect(biblioModule->citeNatbibRB, SIGNAL(toggled(bool)),
850                 biblioModule->citeStyleCO, SLOT(setEnabled(bool)));
851         // biblio
852         connect(biblioModule->citeDefaultRB, SIGNAL(clicked()),
853                 this, SLOT(change_adaptor()));
854         connect(biblioModule->citeNatbibRB, SIGNAL(clicked()),
855                 this, SLOT(change_adaptor()));
856         connect(biblioModule->citeStyleCO, SIGNAL(activated(int)),
857                 this, SLOT(change_adaptor()));
858         connect(biblioModule->citeJurabibRB, SIGNAL(clicked()),
859                 this, SLOT(change_adaptor()));
860         connect(biblioModule->bibtopicCB, SIGNAL(clicked()),
861                 this, SLOT(change_adaptor()));
862         connect(biblioModule->bibtexCO, SIGNAL(activated(int)),
863                 this, SLOT(bibtexChanged(int)));
864         connect(biblioModule->bibtexOptionsED, SIGNAL(textChanged(QString)),
865                 this, SLOT(change_adaptor()));
866         // biblio
867         biblioModule->citeStyleCO->addItem(qt_("Author-year"));
868         biblioModule->citeStyleCO->addItem(qt_("Numerical"));
869         biblioModule->citeStyleCO->setCurrentIndex(0);
870         
871         biblioModule->bibtexCO->clear();
872
873         biblioModule->bibtexCO->addItem(qt_("Default"), QString("default"));
874         for (set<string>::const_iterator it = lyxrc.bibtex_alternatives.begin();
875                              it != lyxrc.bibtex_alternatives.end(); ++it) {
876                 QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
877                 biblioModule->bibtexCO->addItem(command, command);
878         }
879
880         // indices
881         indicesModule = new GuiIndices;
882         connect(indicesModule, SIGNAL(changed()),
883                 this, SLOT(change_adaptor()));
884
885
886         mathsModule = new UiWidget<Ui::MathsUi>;
887         connect(mathsModule->amsautoCB, SIGNAL(toggled(bool)),
888                 mathsModule->amsCB, SLOT(setDisabled(bool)));
889         connect(mathsModule->esintautoCB, SIGNAL(toggled(bool)),
890                 mathsModule->esintCB, SLOT(setDisabled(bool)));
891         // maths
892         connect(mathsModule->amsCB, SIGNAL(clicked()),
893                 this, SLOT(change_adaptor()));
894         connect(mathsModule->amsautoCB, SIGNAL(clicked()),
895                 this, SLOT(change_adaptor()));
896         connect(mathsModule->esintCB, SIGNAL(clicked()),
897                 this, SLOT(change_adaptor()));
898         connect(mathsModule->esintautoCB, SIGNAL(clicked()),
899                 this, SLOT(change_adaptor()));
900
901         latexModule = new UiWidget<Ui::LaTeXUi>;
902         // latex class
903         connect(latexModule->optionsLE, SIGNAL(textChanged(QString)),
904                 this, SLOT(change_adaptor()));
905         connect(latexModule->defaultOptionsCB, SIGNAL(clicked()),
906                 this, SLOT(change_adaptor()));
907         connect(latexModule->psdriverCO, SIGNAL(activated(int)),
908                 this, SLOT(change_adaptor()));
909         connect(latexModule->classCO, SIGNAL(activated(int)),
910                 this, SLOT(classChanged()));
911         connect(latexModule->classCO, SIGNAL(activated(int)),
912                 this, SLOT(change_adaptor()));
913         connect(latexModule->layoutPB, SIGNAL(clicked()),
914                 this, SLOT(browseLayout()));
915         connect(latexModule->layoutPB, SIGNAL(clicked()),
916                 this, SLOT(change_adaptor()));
917         connect(latexModule->childDocGB, SIGNAL(clicked()),
918                 this, SLOT(change_adaptor()));
919         connect(latexModule->childDocLE, SIGNAL(textChanged(QString)),
920                 this, SLOT(change_adaptor()));
921         connect(latexModule->childDocPB, SIGNAL(clicked()),
922                 this, SLOT(browseMaster()));
923
924         // postscript drivers
925         for (int n = 0; tex_graphics[n][0]; ++n) {
926                 QString enc = qt_(tex_graphics_gui[n]);
927                 latexModule->psdriverCO->addItem(enc);
928         }
929         // latex classes
930         latexModule->classCO->setModel(&classes_model_);
931         LayoutFileList const & bcl = LayoutFileList::get();
932         vector<LayoutFileIndex> classList = bcl.classList();
933         sort(classList.begin(), classList.end(), less_textclass_avail_desc());
934
935         vector<LayoutFileIndex>::const_iterator cit  = classList.begin();
936         vector<LayoutFileIndex>::const_iterator cen = classList.end();
937         for (int i = 0; cit != cen; ++cit, ++i) {
938                 LayoutFile const & tc = bcl[*cit];
939                 docstring item = (tc.isTeXClassAvailable()) ?
940                         from_utf8(tc.description()) :
941                         bformat(_("Unavailable: %1$s"), from_utf8(tc.description()));
942                 classes_model_.insertRow(i, toqstr(item), *cit);
943         }
944
945         // branches
946         branchesModule = new GuiBranches;
947         connect(branchesModule, SIGNAL(changed()),
948                 this, SLOT(change_adaptor()));
949         connect(branchesModule, SIGNAL(renameBranches(docstring const &, docstring const &)),
950                 this, SLOT(branchesRename(docstring const &, docstring const &)));
951         updateUnknownBranches();
952
953         // preamble
954         preambleModule = new PreambleModule;
955         connect(preambleModule, SIGNAL(changed()),
956                 this, SLOT(change_adaptor()));
957
958         // bullets
959         bulletsModule = new BulletsModule;
960         connect(bulletsModule, SIGNAL(changed()),
961                 this, SLOT(change_adaptor()));
962
963         // Modules
964         modulesModule = new UiWidget<Ui::ModulesUi>;
965
966         selectionManager =
967                 new ModuleSelectionManager(modulesModule->availableLV,
968                         modulesModule->selectedLV,
969                         modulesModule->addPB, modulesModule->deletePB,
970                         modulesModule->upPB, modulesModule->downPB,
971                         availableModel(), selectedModel(), this);
972         connect(selectionManager, SIGNAL(updateHook()),
973                 this, SLOT(updateModuleInfo()));
974         connect(selectionManager, SIGNAL(updateHook()),
975                 this, SLOT(change_adaptor()));
976         connect(selectionManager, SIGNAL(selectionChanged()),
977                 this, SLOT(modulesChanged()));
978
979         // PDF support
980         pdfSupportModule = new UiWidget<Ui::PDFSupportUi>;
981
982         connect(pdfSupportModule->use_hyperrefGB, SIGNAL(toggled(bool)),
983                 this, SLOT(change_adaptor()));
984         connect(pdfSupportModule->titleLE, SIGNAL(textChanged(QString)),
985                 this, SLOT(change_adaptor()));
986         connect(pdfSupportModule->authorLE, SIGNAL(textChanged(QString)),
987                 this, SLOT(change_adaptor()));
988         connect(pdfSupportModule->subjectLE, SIGNAL(textChanged(QString)),
989                 this, SLOT(change_adaptor()));
990         connect(pdfSupportModule->keywordsLE, SIGNAL(textChanged(QString)),
991                 this, SLOT(change_adaptor()));
992         connect(pdfSupportModule->bookmarksGB, SIGNAL(toggled(bool)),
993                 this, SLOT(change_adaptor()));
994         connect(pdfSupportModule->bookmarksnumberedCB, SIGNAL(toggled(bool)),
995                 this, SLOT(change_adaptor()));
996         connect(pdfSupportModule->bookmarksopenGB, SIGNAL(toggled(bool)),
997                 this, SLOT(change_adaptor()));
998         connect(pdfSupportModule->bookmarksopenlevelSB, SIGNAL(valueChanged(int)),
999                 this, SLOT(change_adaptor()));
1000         connect(pdfSupportModule->breaklinksCB, SIGNAL(toggled(bool)),
1001                 this, SLOT(change_adaptor()));
1002         connect(pdfSupportModule->pdfborderCB, SIGNAL(toggled(bool)),
1003                 this, SLOT(change_adaptor()));
1004         connect(pdfSupportModule->colorlinksCB, SIGNAL(toggled(bool)),
1005                 this, SLOT(change_adaptor()));
1006         connect(pdfSupportModule->backrefCO, SIGNAL(activated(int)),
1007                 this, SLOT(change_adaptor()));
1008         connect(pdfSupportModule->pdfusetitleCB, SIGNAL(toggled(bool)),
1009                 this, SLOT(change_adaptor()));
1010         connect(pdfSupportModule->fullscreenCB, SIGNAL(toggled(bool)),
1011                 this, SLOT(change_adaptor()));
1012         connect(pdfSupportModule->optionsLE, SIGNAL(textChanged(QString)),
1013                 this, SLOT(change_adaptor()));
1014
1015         for (int i = 0; backref_opts[i][0]; ++i)
1016                 pdfSupportModule->backrefCO->addItem(qt_(backref_opts_gui[i]));
1017
1018         // float
1019         floatModule = new FloatPlacement;
1020         connect(floatModule, SIGNAL(changed()),
1021                 this, SLOT(change_adaptor()));
1022
1023         docPS->addPanel(latexModule, qt_("Document Class"));
1024         docPS->addPanel(modulesModule, qt_("Modules"));
1025         docPS->addPanel(fontModule, qt_("Fonts"));
1026         docPS->addPanel(textLayoutModule, qt_("Text Layout"));
1027         docPS->addPanel(pageLayoutModule, qt_("Page Layout"));
1028         docPS->addPanel(marginsModule, qt_("Page Margins"));
1029         docPS->addPanel(langModule, qt_("Language"));
1030         docPS->addPanel(numberingModule, qt_("Numbering & TOC"));
1031         docPS->addPanel(biblioModule, qt_("Bibliography"));
1032         docPS->addPanel(indicesModule, qt_("Indexes"));
1033         docPS->addPanel(pdfSupportModule, qt_("PDF Properties"));
1034         docPS->addPanel(mathsModule, qt_("Math Options"));
1035         docPS->addPanel(floatModule, qt_("Float Placement"));
1036         docPS->addPanel(bulletsModule, qt_("Bullets"));
1037         docPS->addPanel(branchesModule, qt_("Branches"));
1038         docPS->addPanel(outputModule, qt_("Output"));
1039         docPS->addPanel(preambleModule, qt_("LaTeX Preamble"));
1040         docPS->setCurrentPanel(qt_("Document Class"));
1041 // FIXME: hack to work around resizing bug in Qt >= 4.2
1042 // bug verified with Qt 4.2.{0-3} (JSpitzm)
1043 #if QT_VERSION >= 0x040200
1044         docPS->updateGeometry();
1045 #endif
1046 }
1047
1048
1049 void GuiDocument::showPreamble()
1050 {
1051         docPS->setCurrentPanel(qt_("LaTeX Preamble"));
1052 }
1053
1054
1055 void GuiDocument::saveDefaultClicked()
1056 {
1057         saveDocDefault();
1058 }
1059
1060
1061 void GuiDocument::useDefaultsClicked()
1062 {
1063         useClassDefaults();
1064 }
1065
1066
1067 void GuiDocument::change_adaptor()
1068 {
1069         changed();
1070 }
1071
1072
1073 QString GuiDocument::validateListingsParameters()
1074 {
1075         // use a cache here to avoid repeated validation
1076         // of the same parameters
1077         static string param_cache;
1078         static QString msg_cache;
1079         
1080         if (textLayoutModule->bypassCB->isChecked())
1081                 return QString();
1082
1083         string params = fromqstr(textLayoutModule->listingsED->toPlainText());
1084         if (params != param_cache) {
1085                 param_cache = params;
1086                 msg_cache = toqstr(InsetListingsParams(params).validate());
1087         }
1088         return msg_cache;
1089 }
1090
1091
1092 void GuiDocument::setListingsMessage()
1093 {
1094         static bool isOK = true;
1095         QString msg = validateListingsParameters();
1096         if (msg.isEmpty()) {
1097                 if (isOK)
1098                         return;
1099                 isOK = true;
1100                 // listingsTB->setTextColor("black");
1101                 textLayoutModule->listingsTB->setPlainText(
1102                         qt_("Input listings parameters on the right. "
1103                 "Enter ? for a list of parameters."));
1104         } else {
1105                 isOK = false;
1106                 // listingsTB->setTextColor("red");
1107                 textLayoutModule->listingsTB->setPlainText(msg);
1108         }
1109 }
1110
1111
1112 void GuiDocument::setLSpacing(int item)
1113 {
1114         textLayoutModule->lspacingLE->setEnabled(item == 3);
1115 }
1116
1117
1118 void GuiDocument::setSkip(int item)
1119 {
1120         bool const enable = (item == 3);
1121         textLayoutModule->skipLE->setEnabled(enable);
1122         textLayoutModule->skipLengthCO->setEnabled(enable);
1123 }
1124
1125
1126 void GuiDocument::enableSkip(bool skip)
1127 {
1128         textLayoutModule->skipCO->setEnabled(skip);
1129         textLayoutModule->skipLE->setEnabled(skip);
1130         textLayoutModule->skipLengthCO->setEnabled(skip);
1131         if (skip)
1132                 setSkip(textLayoutModule->skipCO->currentIndex());
1133 }
1134
1135
1136 void GuiDocument::portraitChanged()
1137 {
1138         setMargins(pageLayoutModule->papersizeCO->currentIndex());
1139 }
1140
1141
1142 void GuiDocument::setMargins(bool custom)
1143 {
1144         bool const extern_geometry =
1145                 documentClass().provides("geometry");
1146         marginsModule->marginCB->setEnabled(!extern_geometry);
1147         if (extern_geometry) {
1148                 marginsModule->marginCB->setChecked(false);
1149                 setCustomMargins(true);
1150                 return;
1151         }
1152         marginsModule->marginCB->setChecked(custom);
1153         setCustomMargins(custom);
1154 }
1155
1156
1157 void GuiDocument::setCustomPapersize(int papersize)
1158 {
1159         bool const custom = (papersize == 1);
1160
1161         pageLayoutModule->paperwidthL->setEnabled(custom);
1162         pageLayoutModule->paperwidthLE->setEnabled(custom);
1163         pageLayoutModule->paperwidthUnitCO->setEnabled(custom);
1164         pageLayoutModule->paperheightL->setEnabled(custom);
1165         pageLayoutModule->paperheightLE->setEnabled(custom);
1166         pageLayoutModule->paperheightLE->setFocus();
1167         pageLayoutModule->paperheightUnitCO->setEnabled(custom);
1168 }
1169
1170
1171 void GuiDocument::setColSep()
1172 {
1173         setCustomMargins(marginsModule->marginCB->checkState() == Qt::Checked);
1174 }
1175
1176
1177 void GuiDocument::setCustomMargins(bool custom)
1178 {
1179         marginsModule->topL->setEnabled(!custom);
1180         marginsModule->topLE->setEnabled(!custom);
1181         marginsModule->topUnit->setEnabled(!custom);
1182
1183         marginsModule->bottomL->setEnabled(!custom);
1184         marginsModule->bottomLE->setEnabled(!custom);
1185         marginsModule->bottomUnit->setEnabled(!custom);
1186
1187         marginsModule->innerL->setEnabled(!custom);
1188         marginsModule->innerLE->setEnabled(!custom);
1189         marginsModule->innerUnit->setEnabled(!custom);
1190
1191         marginsModule->outerL->setEnabled(!custom);
1192         marginsModule->outerLE->setEnabled(!custom);
1193         marginsModule->outerUnit->setEnabled(!custom);
1194
1195         marginsModule->headheightL->setEnabled(!custom);
1196         marginsModule->headheightLE->setEnabled(!custom);
1197         marginsModule->headheightUnit->setEnabled(!custom);
1198
1199         marginsModule->headsepL->setEnabled(!custom);
1200         marginsModule->headsepLE->setEnabled(!custom);
1201         marginsModule->headsepUnit->setEnabled(!custom);
1202
1203         marginsModule->footskipL->setEnabled(!custom);
1204         marginsModule->footskipLE->setEnabled(!custom);
1205         marginsModule->footskipUnit->setEnabled(!custom);
1206
1207         bool const enableColSep = !custom && 
1208                         textLayoutModule->twoColumnCB->checkState() == Qt::Checked;
1209         marginsModule->columnsepL->setEnabled(enableColSep);
1210         marginsModule->columnsepLE->setEnabled(enableColSep);
1211         marginsModule->columnsepUnit->setEnabled(enableColSep);
1212 }
1213
1214 void GuiDocument::changeBackgroundColor()
1215 {
1216         QColor const & newColor = QColorDialog::getColor(
1217                 rgb2qcolor(set_backgroundcolor), asQWidget());
1218         if (!newColor.isValid())
1219                 return;
1220         // set the button color
1221         pageLayoutModule->backgroundPB->setStyleSheet(
1222                 colorButtonStyleSheet(newColor));
1223         // save color
1224         set_backgroundcolor = rgbFromHexName(fromqstr(newColor.name()));
1225         changed();
1226 }
1227
1228
1229 void GuiDocument::deleteBackgroundColor()
1230 {
1231         // set the button color back to white
1232         pageLayoutModule->backgroundPB->setStyleSheet(
1233                 colorButtonStyleSheet(QColor(Qt::white)));
1234         // save white as the set color
1235         set_backgroundcolor = rgbFromHexName("#ffffff");
1236         changed();
1237 }
1238
1239
1240 void GuiDocument::xetexChanged(bool xetex)
1241 {
1242         updateFontlist();
1243         updateDefaultFormat();
1244         langModule->encodingCO->setEnabled(!xetex &&
1245                 !langModule->defaultencodingRB->isChecked());
1246         langModule->defaultencodingRB->setEnabled(!xetex);
1247         langModule->otherencodingRB->setEnabled(!xetex);
1248
1249         fontModule->fontsDefaultCO->setEnabled(!xetex);
1250         fontModule->fontsDefaultLA->setEnabled(!xetex);
1251         fontModule->cjkFontLE->setEnabled(!xetex);
1252         fontModule->cjkFontLA->setEnabled(!xetex);
1253         string font;
1254         if (!xetex)
1255                 font = tex_fonts_sans[fontModule->fontsSansCO->currentIndex()];
1256         bool scaleable = providesScale(font);
1257         fontModule->scaleSansSB->setEnabled(scaleable);
1258         fontModule->scaleSansLA->setEnabled(scaleable);
1259         if (!xetex)
1260                 font = tex_fonts_monospaced[fontModule->fontsTypewriterCO->currentIndex()];
1261         scaleable = providesScale(font);
1262         fontModule->scaleTypewriterSB->setEnabled(scaleable);
1263         fontModule->scaleTypewriterLA->setEnabled(scaleable);
1264         if (!xetex)
1265                 font = tex_fonts_roman[fontModule->fontsRomanCO->currentIndex()];
1266         fontModule->fontScCB->setEnabled(providesSC(font));
1267         fontModule->fontOsfCB->setEnabled(providesOSF(font));
1268 }
1269
1270
1271 void GuiDocument::updateFontsize(string const & items, string const & sel)
1272 {
1273         fontModule->fontsizeCO->clear();
1274         fontModule->fontsizeCO->addItem(qt_("Default"));
1275
1276         for (int n = 0; !token(items,'|',n).empty(); ++n)
1277                 fontModule->fontsizeCO->
1278                         addItem(toqstr(token(items,'|',n)));
1279
1280         for (int n = 0; n < fontModule->fontsizeCO->count(); ++n) {
1281                 if (fromqstr(fontModule->fontsizeCO->itemText(n)) == sel) {
1282                         fontModule->fontsizeCO->setCurrentIndex(n);
1283                         break;
1284                 }
1285         }
1286 }
1287
1288
1289 void GuiDocument::updateFontlist()
1290 {
1291         fontModule->fontsRomanCO->clear();
1292         fontModule->fontsSansCO->clear();
1293         fontModule->fontsTypewriterCO->clear();
1294
1295         // With XeTeX, we have access to all system fonts, but not the LaTeX fonts
1296         if (outputModule->xetexCB->isChecked()) {
1297                 fontModule->fontsRomanCO->addItem(qt_("Default"));
1298                 fontModule->fontsSansCO->addItem(qt_("Default"));
1299                 fontModule->fontsTypewriterCO->addItem(qt_("Default"));
1300         
1301                 QFontDatabase fontdb;
1302                 QStringList families(fontdb.families());
1303                 for (QStringList::Iterator it = families.begin(); it != families.end(); ++it) {
1304                         fontModule->fontsRomanCO->addItem(*it);
1305                         fontModule->fontsSansCO->addItem(*it);
1306                         fontModule->fontsTypewriterCO->addItem(*it);
1307                 }
1308                 return;
1309         }
1310
1311         for (int n = 0; tex_fonts_roman[n][0]; ++n) {
1312                 QString font = qt_(tex_fonts_roman_gui[n]);
1313                 if (!isFontAvailable(tex_fonts_roman[n]))
1314                         font += qt_(" (not installed)");
1315                 fontModule->fontsRomanCO->addItem(font);
1316         }
1317         for (int n = 0; tex_fonts_sans[n][0]; ++n) {
1318                 QString font = qt_(tex_fonts_sans_gui[n]);
1319                 if (!isFontAvailable(tex_fonts_sans[n]))
1320                         font += qt_(" (not installed)");
1321                 fontModule->fontsSansCO->addItem(font);
1322         }
1323         for (int n = 0; tex_fonts_monospaced[n][0]; ++n) {
1324                 QString font = qt_(tex_fonts_monospaced_gui[n]);
1325                 if (!isFontAvailable(tex_fonts_monospaced[n]))
1326                         font += qt_(" (not installed)");
1327                 fontModule->fontsTypewriterCO->addItem(font);
1328         }
1329 }
1330
1331
1332 void GuiDocument::romanChanged(int item)
1333 {
1334         if (outputModule->xetexCB->isChecked())
1335                 return;
1336         string const font = tex_fonts_roman[item];
1337         fontModule->fontScCB->setEnabled(providesSC(font));
1338         fontModule->fontOsfCB->setEnabled(providesOSF(font));
1339 }
1340
1341
1342 void GuiDocument::sansChanged(int item)
1343 {
1344         if (outputModule->xetexCB->isChecked())
1345                 return;
1346         string const font = tex_fonts_sans[item];
1347         bool scaleable = providesScale(font);
1348         fontModule->scaleSansSB->setEnabled(scaleable);
1349         fontModule->scaleSansLA->setEnabled(scaleable);
1350 }
1351
1352
1353 void GuiDocument::ttChanged(int item)
1354 {
1355         if (outputModule->xetexCB->isChecked())
1356                 return;
1357         string const font = tex_fonts_monospaced[item];
1358         bool scaleable = providesScale(font);
1359         fontModule->scaleTypewriterSB->setEnabled(scaleable);
1360         fontModule->scaleTypewriterLA->setEnabled(scaleable);
1361 }
1362
1363
1364 void GuiDocument::updatePagestyle(string const & items, string const & sel)
1365 {
1366         pagestyles.clear();
1367         pageLayoutModule->pagestyleCO->clear();
1368         pageLayoutModule->pagestyleCO->addItem(qt_("Default"));
1369
1370         for (int n = 0; !token(items, '|', n).empty(); ++n) {
1371                 string style = token(items, '|', n);
1372                 QString style_gui = qt_(style);
1373                 pagestyles.push_back(pair<string, QString>(style, style_gui));
1374                 pageLayoutModule->pagestyleCO->addItem(style_gui);
1375         }
1376
1377         if (sel == "default") {
1378                 pageLayoutModule->pagestyleCO->setCurrentIndex(0);
1379                 return;
1380         }
1381
1382         int nn = 0;
1383
1384         for (size_t i = 0; i < pagestyles.size(); ++i)
1385                 if (pagestyles[i].first == sel)
1386                         nn = pageLayoutModule->pagestyleCO->findText(pagestyles[i].second);
1387
1388         if (nn > 0)
1389                 pageLayoutModule->pagestyleCO->setCurrentIndex(nn);
1390 }
1391
1392
1393 void GuiDocument::browseLayout()
1394 {
1395         QString const label1 = qt_("Layouts|#o#O");
1396         QString const dir1 = toqstr(lyxrc.document_path);
1397         QStringList const filter(qt_("LyX Layout (*.layout)"));
1398         QString file = browseRelFile(QString(), bufferFilepath(),
1399                 qt_("Local layout file"), filter, false,
1400                 label1, dir1);
1401
1402         if (!file.endsWith(".layout"))
1403                 return;
1404
1405         FileName layoutFile = support::makeAbsPath(fromqstr(file),
1406                 fromqstr(bufferFilepath()));
1407         
1408         int const ret = Alert::prompt(_("Local layout file"),
1409                 _("The layout file you have selected is a local layout\n"
1410                   "file, not one in the system or user directory. Your\n"
1411                   "document may not work with this layout if you do not\n"
1412                   "keep the layout file in the document directory."),
1413                   1, 1, _("&Set Layout"), _("&Cancel"));
1414         if (ret == 1)
1415                 return;
1416
1417         // load the layout file
1418         LayoutFileList & bcl = LayoutFileList::get();
1419         string classname = layoutFile.onlyFileName();
1420         // this will update an existing layout if that layout has been loaded before.
1421         LayoutFileIndex name = bcl.addLocalLayout(
1422                 classname.substr(0, classname.size() - 7),
1423                 layoutFile.onlyPath().absFilename());
1424
1425         if (name.empty()) {
1426                 Alert::error(_("Error"),
1427                         _("Unable to read local layout file."));                
1428                 return;
1429         }
1430
1431         // do not trigger classChanged if there is no change.
1432         if (latexModule->classCO->currentText() == toqstr(name))
1433                 return;
1434                 
1435         // add to combo box
1436         int idx = latexModule->classCO->findText(toqstr(name));
1437         if (idx == -1) {
1438                 classes_model_.insertRow(0, toqstr(name), name);
1439                 latexModule->classCO->setCurrentIndex(0);
1440         } else
1441                 latexModule->classCO->setCurrentIndex(idx);
1442         
1443         classChanged();
1444 }
1445
1446
1447 void GuiDocument::browseMaster()
1448 {
1449         QString const title = qt_("Select master document");
1450         QString const dir1 = toqstr(lyxrc.document_path);
1451         QString const old = latexModule->childDocLE->text();
1452         QString const docpath = toqstr(support::onlyPath(buffer().absFileName()));
1453         QStringList const filter(qt_("LyX Files (*.lyx)"));
1454         QString file = browseRelFile(old, docpath, title, filter, false,
1455                 qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
1456
1457         latexModule->childDocLE->setText(file);
1458 }
1459
1460
1461 void GuiDocument::classChanged()
1462 {
1463         int idx = latexModule->classCO->currentIndex();
1464         if (idx < 0) 
1465                 return;
1466         string const classname = classes_model_.getIDString(idx);
1467
1468         // check whether the selected modules have changed.
1469         bool modules_changed = false;
1470         unsigned int const srows = selectedModel()->rowCount();
1471         if (srows != bp_.getModules().size())
1472                 modules_changed = true;
1473         else {
1474                 list<string>::const_iterator mit = bp_.getModules().begin();
1475                 list<string>::const_iterator men = bp_.getModules().end();
1476                 for (unsigned int i = 0; i < srows && mit != men; ++i, ++mit)
1477                         if (selectedModel()->getIDString(i) != *mit) {
1478                                 modules_changed = true;
1479                                 break;
1480                         }
1481         }
1482
1483         if (modules_changed || lyxrc.auto_reset_options) {
1484                 if (applyPB->isEnabled()) {
1485                         int const ret = Alert::prompt(_("Unapplied changes"),
1486                                         _("Some changes in the dialog were not yet applied.\n"
1487                                         "If you do not apply now, they will be lost after this action."),
1488                                         1, 1, _("&Apply"), _("&Dismiss"));
1489                         if (ret == 0)
1490                                 applyView();
1491                 }
1492         }
1493
1494         // We load the TextClass as soon as it is selected. This is
1495         // necessary so that other options in the dialog can be updated
1496         // according to the new class. Note, however, that, if you use 
1497         // the scroll wheel when sitting on the combo box, we'll load a 
1498         // lot of TextClass objects very quickly....
1499         if (!bp_.setBaseClass(classname)) {
1500                 Alert::error(_("Error"), _("Unable to set document class."));
1501                 return;
1502         }
1503         if (lyxrc.auto_reset_options)
1504                 bp_.useClassDefaults();
1505
1506         // With the introduction of modules came a distinction between the base 
1507         // class and the document class. The former corresponds to the main layout 
1508         // file; the latter is that plus the modules (or the document-specific layout,
1509         // or  whatever else there could be). Our parameters come from the document 
1510         // class. So when we set the base class, we also need to recreate the document 
1511         // class. Otherwise, we still have the old one.
1512         bp_.makeDocumentClass();
1513         paramsToDialog();
1514 }
1515
1516
1517 void GuiDocument::bibtexChanged(int n)
1518 {
1519         biblioModule->bibtexOptionsED->setEnabled(n != 0);
1520         changed();
1521 }
1522
1523
1524 namespace {
1525         // This is an insanely complicated attempt to make this sort of thing
1526         // work with RTL languages.
1527         docstring formatStrVec(vector<string> const & v, docstring const & s) 
1528         {
1529                 //this mess formats the list as "v[0], v[1], ..., [s] v[n]"
1530                 if (v.size() == 0)
1531                         return docstring();
1532                 if (v.size() == 1) 
1533                         return from_utf8(v[0]);
1534                 if (v.size() == 2) {
1535                         docstring retval = _("%1$s and %2$s");
1536                         retval = subst(retval, _("and"), s);
1537                         return bformat(retval, from_utf8(v[0]), from_utf8(v[1]));
1538                 }
1539                 // The idea here is to format all but the last two items...
1540                 int const vSize = v.size();
1541                 docstring t2 = _("%1$s, %2$s");
1542                 docstring retval = from_utf8(v[0]);
1543                 for (int i = 1; i < vSize - 2; ++i)
1544                         retval = bformat(t2, retval, from_utf8(v[i])); 
1545                 //...and then to  plug them, and the last two, into this schema
1546                 docstring t = _("%1$s, %2$s, and %3$s");
1547                 t = subst(t, _("and"), s);
1548                 return bformat(t, retval, from_utf8(v[vSize - 2]), from_utf8(v[vSize - 1]));
1549         }
1550         
1551         vector<string> idsToNames(vector<string> const & idList)
1552         {
1553                 vector<string> retval;
1554                 vector<string>::const_iterator it  = idList.begin();
1555                 vector<string>::const_iterator end = idList.end();
1556                 for (; it != end; ++it) {
1557                         LyXModule const * const mod = moduleList[*it];
1558                         if (!mod)
1559                                 retval.push_back(*it + " (Unavailable)");
1560                         else
1561                                 retval.push_back(mod->getName());
1562                 }
1563                 return retval;
1564         }
1565 }
1566
1567
1568 void GuiDocument::modulesToParams(BufferParams & bp)
1569 {
1570         // update list of loaded modules
1571         bp.clearLayoutModules();
1572         int const srows = modules_sel_model_.rowCount();
1573         for (int i = 0; i < srows; ++i)
1574                 bp.addLayoutModule(modules_sel_model_.getIDString(i));
1575
1576         // update the list of removed modules
1577         bp.clearRemovedModules();
1578         LayoutModuleList const & reqmods = bp.baseClass()->defaultModules();
1579         list<string>::const_iterator rit = reqmods.begin();
1580         list<string>::const_iterator ren = reqmods.end();
1581
1582         // check each of the default modules
1583         for (; rit != ren; rit++) {
1584                 list<string>::const_iterator mit = bp.getModules().begin();
1585                 list<string>::const_iterator men = bp.getModules().end();
1586                 bool found = false;
1587                 for (; mit != men; mit++) {
1588                         if (*rit == *mit) {
1589                                 found = true;
1590                                 break;
1591                         }
1592                 }
1593                 if (!found) {
1594                         // the module isn't present so must have been removed by the user
1595                         bp.addRemovedModule(*rit);
1596                 }
1597         }
1598 }
1599
1600 void GuiDocument::modulesChanged()
1601 {
1602         modulesToParams(bp_);
1603         bp_.makeDocumentClass();
1604         paramsToDialog();
1605 }
1606
1607
1608 void GuiDocument::updateModuleInfo()
1609 {
1610         selectionManager->update();
1611         
1612         //Module description
1613         bool const focus_on_selected = selectionManager->selectedFocused();
1614         QListView const * const lv = 
1615                         focus_on_selected ? modulesModule->selectedLV : modulesModule->availableLV;
1616         if (lv->selectionModel()->selectedIndexes().isEmpty()) {
1617                 modulesModule->infoML->document()->clear();
1618                 return;
1619         }
1620         QModelIndex const & idx = lv->selectionModel()->currentIndex();
1621         GuiIdListModel const & id_model = 
1622                         focus_on_selected  ? modules_sel_model_ : modules_av_model_;
1623         string const modName = id_model.getIDString(idx.row());
1624         docstring desc = getModuleDescription(modName);
1625
1626         LayoutModuleList const & provmods = bp_.baseClass()->providedModules();
1627         if (std::find(provmods.begin(), provmods.end(), modName) != provmods.end()) {
1628                 if (!desc.empty())
1629                         desc += "\n";
1630                 desc += _("Module provided by document class.");
1631         }
1632
1633         vector<string> pkglist = getPackageList(modName);
1634         docstring pkgdesc = formatStrVec(pkglist, _("and"));
1635         if (!pkgdesc.empty()) {
1636                 if (!desc.empty())
1637                         desc += "\n";
1638                 desc += bformat(_("Package(s) required: %1$s."), pkgdesc);
1639         }
1640
1641         pkglist = getRequiredList(modName);
1642         if (!pkglist.empty()) {
1643                 vector<string> const reqdescs = idsToNames(pkglist);
1644                 pkgdesc = formatStrVec(reqdescs, _("or"));
1645                 if (!desc.empty())
1646                         desc += "\n";
1647                 desc += bformat(_("Module required: %1$s."), pkgdesc);
1648         }
1649
1650         pkglist = getExcludedList(modName);
1651         if (!pkglist.empty()) {
1652                 vector<string> const reqdescs = idsToNames(pkglist);
1653                 pkgdesc = formatStrVec(reqdescs, _( "and"));
1654                 if (!desc.empty())
1655                         desc += "\n";
1656                 desc += bformat(_("Modules excluded: %1$s."), pkgdesc);
1657         }
1658
1659         if (!isModuleAvailable(modName)) {
1660                 if (!desc.empty())
1661                         desc += "\n";
1662                 desc += _("WARNING: Some required packages are unavailable!");
1663         }
1664
1665         modulesModule->infoML->document()->setPlainText(toqstr(desc));
1666 }
1667
1668
1669 void GuiDocument::updateNumbering()
1670 {
1671         DocumentClass const & tclass = documentClass();
1672
1673         numberingModule->tocTW->setUpdatesEnabled(false);
1674         numberingModule->tocTW->clear();
1675
1676         int const depth = numberingModule->depthSL->value();
1677         int const toc = numberingModule->tocSL->value();
1678         QString const no = qt_("No");
1679         QString const yes = qt_("Yes");
1680         QTreeWidgetItem * item = 0;
1681
1682         DocumentClass::const_iterator lit = tclass.begin();
1683         DocumentClass::const_iterator len = tclass.end();
1684         for (; lit != len; ++lit) {
1685                 int const toclevel = lit->toclevel;
1686                 if (toclevel != Layout::NOT_IN_TOC && lit->labeltype == LABEL_COUNTER) {
1687                         item = new QTreeWidgetItem(numberingModule->tocTW);
1688                         item->setText(0, toqstr(translateIfPossible(lit->name())));
1689                         item->setText(1, (toclevel <= depth) ? yes : no);
1690                         item->setText(2, (toclevel <= toc) ? yes : no);
1691                 }
1692         }
1693
1694         numberingModule->tocTW->setUpdatesEnabled(true);
1695         numberingModule->tocTW->update();
1696 }
1697
1698
1699 void GuiDocument::updateDefaultFormat()
1700 {
1701         // make a copy in order to consider unapplied changes
1702         Buffer * tmpbuf = const_cast<Buffer *>(&buffer());
1703         tmpbuf->params().useXetex = outputModule->xetexCB->isChecked();
1704         int idx = latexModule->classCO->currentIndex();
1705         if (idx >= 0) {
1706                 string const classname = classes_model_.getIDString(idx);
1707                 tmpbuf->params().setBaseClass(classname);
1708                 tmpbuf->params().makeDocumentClass();
1709         }
1710         outputModule->defaultFormatCO->blockSignals(true);
1711         outputModule->defaultFormatCO->clear();
1712         outputModule->defaultFormatCO->addItem(qt_("Default"),
1713                                 QVariant(QString("default")));
1714         typedef vector<Format const *> Formats;
1715         Formats formats = tmpbuf->exportableFormats(true);
1716         Formats::const_iterator cit = formats.begin();
1717         Formats::const_iterator end = formats.end();
1718         for (; cit != end; ++cit)
1719                 outputModule->defaultFormatCO->addItem(qt_((*cit)->prettyname()),
1720                                 QVariant(toqstr((*cit)->name())));
1721         outputModule->defaultFormatCO->blockSignals(false);
1722 }
1723
1724
1725 void GuiDocument::applyView()
1726 {
1727         // preamble
1728         preambleModule->apply(bp_);
1729
1730         // biblio
1731         bp_.setCiteEngine(ENGINE_BASIC);
1732
1733         if (biblioModule->citeNatbibRB->isChecked()) {
1734                 bool const use_numerical_citations =
1735                         biblioModule->citeStyleCO->currentIndex();
1736                 if (use_numerical_citations)
1737                         bp_.setCiteEngine(ENGINE_NATBIB_NUMERICAL);
1738                 else
1739                         bp_.setCiteEngine(ENGINE_NATBIB_AUTHORYEAR);
1740
1741         } else if (biblioModule->citeJurabibRB->isChecked())
1742                 bp_.setCiteEngine(ENGINE_JURABIB);
1743
1744         bp_.use_bibtopic =
1745                 biblioModule->bibtopicCB->isChecked();
1746
1747         string const bibtex_command =
1748                 fromqstr(biblioModule->bibtexCO->itemData(
1749                         biblioModule->bibtexCO->currentIndex()).toString());
1750         string const bibtex_options =
1751                 fromqstr(biblioModule->bibtexOptionsED->text());
1752         if (bibtex_command == "default" || bibtex_options.empty())
1753                 bp_.bibtex_command = bibtex_command;
1754         else
1755                 bp_.bibtex_command = bibtex_command + " " + bibtex_options;
1756
1757         // Indices
1758         indicesModule->apply(bp_);
1759
1760         // language & quotes
1761         if (langModule->defaultencodingRB->isChecked()) {
1762                 bp_.inputenc = "auto";
1763         } else {
1764                 int i = langModule->encodingCO->currentIndex();
1765                 if (i == 0)
1766                         bp_.inputenc = "default";
1767                 else {
1768                         QString const enc_gui =
1769                                 langModule->encodingCO->currentText();
1770                         Encodings::const_iterator it = encodings.begin();
1771                         Encodings::const_iterator const end = encodings.end();
1772                         bool found = false;
1773                         for (; it != end; ++it) {
1774                                 if (qt_(it->guiName()) == enc_gui) {
1775                                         bp_.inputenc = it->latexName();
1776                                         found = true;
1777                                         break;
1778                                 }
1779                         }
1780                         if (!found) {
1781                                 // should not happen
1782                                 lyxerr << "GuiDocument::apply: Unknown encoding! Resetting to default" << endl;
1783                                 bp_.inputenc = "default";
1784                         }
1785                 }
1786         }
1787
1788         InsetQuotes::QuoteLanguage lga = InsetQuotes::EnglishQuotes;
1789         switch (langModule->quoteStyleCO->currentIndex()) {
1790         case 0:
1791                 lga = InsetQuotes::EnglishQuotes;
1792                 break;
1793         case 1:
1794                 lga = InsetQuotes::SwedishQuotes;
1795                 break;
1796         case 2:
1797                 lga = InsetQuotes::GermanQuotes;
1798                 break;
1799         case 3:
1800                 lga = InsetQuotes::PolishQuotes;
1801                 break;
1802         case 4:
1803                 lga = InsetQuotes::FrenchQuotes;
1804                 break;
1805         case 5:
1806                 lga = InsetQuotes::DanishQuotes;
1807                 break;
1808         }
1809         bp_.quotes_language = lga;
1810
1811         QString const lang = langModule->languageCO->itemData(
1812                 langModule->languageCO->currentIndex()).toString();
1813         bp_.language = languages.getLanguage(fromqstr(lang));
1814
1815         // numbering
1816         if (bp_.documentClass().hasTocLevels()) {
1817                 bp_.tocdepth = numberingModule->tocSL->value();
1818                 bp_.secnumdepth = numberingModule->depthSL->value();
1819         }
1820
1821         // bullets
1822         bp_.user_defined_bullet(0) = bulletsModule->bullet(0);
1823         bp_.user_defined_bullet(1) = bulletsModule->bullet(1);
1824         bp_.user_defined_bullet(2) = bulletsModule->bullet(2);
1825         bp_.user_defined_bullet(3) = bulletsModule->bullet(3);
1826
1827         // packages
1828         bp_.graphicsDriver =
1829                 tex_graphics[latexModule->psdriverCO->currentIndex()];
1830         
1831         // text layout
1832         int idx = latexModule->classCO->currentIndex();
1833         if (idx >= 0) {
1834                 string const classname = classes_model_.getIDString(idx);
1835                 bp_.setBaseClass(classname);
1836         }
1837
1838         // Modules
1839         modulesToParams(bp_);
1840
1841         if (mathsModule->amsautoCB->isChecked()) {
1842                 bp_.use_amsmath = BufferParams::package_auto;
1843         } else {
1844                 if (mathsModule->amsCB->isChecked())
1845                         bp_.use_amsmath = BufferParams::package_on;
1846                 else
1847                         bp_.use_amsmath = BufferParams::package_off;
1848         }
1849
1850         if (mathsModule->esintautoCB->isChecked())
1851                 bp_.use_esint = BufferParams::package_auto;
1852         else {
1853                 if (mathsModule->esintCB->isChecked())
1854                         bp_.use_esint = BufferParams::package_on;
1855                 else
1856                         bp_.use_esint = BufferParams::package_off;
1857         }
1858
1859         if (pageLayoutModule->pagestyleCO->currentIndex() == 0)
1860                 bp_.pagestyle = "default";
1861         else {
1862                 QString style_gui = pageLayoutModule->pagestyleCO->currentText();
1863                 for (size_t i = 0; i != pagestyles.size(); ++i)
1864                         if (pagestyles[i].second == style_gui)
1865                                 bp_.pagestyle = pagestyles[i].first;
1866         }
1867
1868         switch (textLayoutModule->lspacingCO->currentIndex()) {
1869         case 0:
1870                 bp_.spacing().set(Spacing::Single);
1871                 break;
1872         case 1:
1873                 bp_.spacing().set(Spacing::Onehalf);
1874                 break;
1875         case 2:
1876                 bp_.spacing().set(Spacing::Double);
1877                 break;
1878         case 3:
1879                 bp_.spacing().set(Spacing::Other,
1880                         fromqstr(textLayoutModule->lspacingLE->text()));
1881                 break;
1882         }
1883
1884         if (textLayoutModule->twoColumnCB->isChecked())
1885                 bp_.columns = 2;
1886         else
1887                 bp_.columns = 1;
1888
1889         // text should have passed validation
1890         bp_.listings_params =
1891                 InsetListingsParams(fromqstr(textLayoutModule->listingsED->toPlainText())).params();
1892
1893         if (textLayoutModule->indentRB->isChecked())
1894                 bp_.paragraph_separation = BufferParams::ParagraphIndentSeparation;
1895         else
1896                 bp_.paragraph_separation = BufferParams::ParagraphSkipSeparation;
1897
1898         switch (textLayoutModule->skipCO->currentIndex()) {
1899         case 0:
1900                 bp_.setDefSkip(VSpace(VSpace::SMALLSKIP));
1901                 break;
1902         case 1:
1903                 bp_.setDefSkip(VSpace(VSpace::MEDSKIP));
1904                 break;
1905         case 2:
1906                 bp_.setDefSkip(VSpace(VSpace::BIGSKIP));
1907                 break;
1908         case 3:
1909         {
1910                 VSpace vs = VSpace(
1911                         widgetsToLength(textLayoutModule->skipLE,
1912                                 textLayoutModule->skipLengthCO)
1913                         );
1914                 bp_.setDefSkip(vs);
1915                 break;
1916         }
1917         default:
1918                 // DocumentDefskipCB assures that this never happens
1919                 // so Assert then !!!  - jbl
1920                 bp_.setDefSkip(VSpace(VSpace::MEDSKIP));
1921                 break;
1922         }
1923
1924         bp_.options =
1925                 fromqstr(latexModule->optionsLE->text());
1926
1927         bp_.use_default_options =
1928                 latexModule->defaultOptionsCB->isChecked();
1929
1930         if (latexModule->childDocGB->isChecked())
1931                 bp_.master =
1932                         fromqstr(latexModule->childDocLE->text());
1933         else
1934                 bp_.master = string();
1935
1936         bp_.float_placement = floatModule->get();
1937
1938         // output
1939         bp_.defaultOutputFormat = fromqstr(outputModule->defaultFormatCO->itemData(
1940                 outputModule->defaultFormatCO->currentIndex()).toString());
1941
1942         bool const xetex = outputModule->xetexCB->isChecked();
1943         bp_.useXetex = xetex;
1944
1945         // fonts
1946         if (xetex) {
1947                 if (fontModule->fontsRomanCO->currentIndex() == 0)
1948                         bp_.fontsRoman = "default";
1949                 else
1950                         bp_.fontsRoman =
1951                                 fromqstr(fontModule->fontsRomanCO->currentText());
1952         
1953                 if (fontModule->fontsSansCO->currentIndex() == 0)
1954                         bp_.fontsSans = "default";
1955                 else
1956                         bp_.fontsSans =
1957                                 fromqstr(fontModule->fontsSansCO->currentText());
1958         
1959                 if (fontModule->fontsTypewriterCO->currentIndex() == 0)
1960                         bp_.fontsTypewriter = "default";
1961                 else
1962                         bp_.fontsTypewriter =
1963                                 fromqstr(fontModule->fontsTypewriterCO->currentText());
1964         } else {
1965                 bp_.fontsRoman =
1966                         tex_fonts_roman[fontModule->fontsRomanCO->currentIndex()];
1967         
1968                 bp_.fontsSans =
1969                         tex_fonts_sans[fontModule->fontsSansCO->currentIndex()];
1970         
1971                 bp_.fontsTypewriter =
1972                         tex_fonts_monospaced[fontModule->fontsTypewriterCO->currentIndex()];
1973         }
1974
1975         bp_.fontsCJK =
1976                 fromqstr(fontModule->cjkFontLE->text());
1977
1978         bp_.fontsSansScale = fontModule->scaleSansSB->value();
1979
1980         bp_.fontsTypewriterScale = fontModule->scaleTypewriterSB->value();
1981
1982         bp_.fontsSC = fontModule->fontScCB->isChecked();
1983
1984         bp_.fontsOSF = fontModule->fontOsfCB->isChecked();
1985
1986         if (xetex)
1987                 bp_.fontsDefaultFamily = "default";
1988         else
1989                 bp_.fontsDefaultFamily = GuiDocument::fontfamilies[
1990                         fontModule->fontsDefaultCO->currentIndex()];
1991
1992         if (fontModule->fontsizeCO->currentIndex() == 0)
1993                 bp_.fontsize = "default";
1994         else
1995                 bp_.fontsize =
1996                         fromqstr(fontModule->fontsizeCO->currentText());
1997
1998         // paper
1999         bp_.papersize = PAPER_SIZE(
2000                 pageLayoutModule->papersizeCO->currentIndex());
2001
2002         // custom, A3, B3 and B4 paper sizes need geometry
2003         int psize = pageLayoutModule->papersizeCO->currentIndex();
2004         bool geom_papersize = (psize == 1 || psize == 5 || psize == 8 || psize == 9);
2005
2006         bp_.paperwidth = widgetsToLength(pageLayoutModule->paperwidthLE,
2007                 pageLayoutModule->paperwidthUnitCO);
2008
2009         bp_.paperheight = widgetsToLength(pageLayoutModule->paperheightLE,
2010                 pageLayoutModule->paperheightUnitCO);
2011
2012         if (pageLayoutModule->facingPagesCB->isChecked())
2013                 bp_.sides = TwoSides;
2014         else
2015                 bp_.sides = OneSide;
2016
2017         if (pageLayoutModule->landscapeRB->isChecked())
2018                 bp_.orientation = ORIENTATION_LANDSCAPE;
2019         else
2020                 bp_.orientation = ORIENTATION_PORTRAIT;
2021
2022         bp_.backgroundcolor = set_backgroundcolor;
2023
2024         // margins
2025         bp_.use_geometry = !marginsModule->marginCB->isChecked()
2026                 || geom_papersize;
2027
2028         Ui::MarginsUi const * m = marginsModule;
2029
2030         bp_.leftmargin = widgetsToLength(m->innerLE, m->innerUnit);
2031         bp_.topmargin = widgetsToLength(m->topLE, m->topUnit);
2032         bp_.rightmargin = widgetsToLength(m->outerLE, m->outerUnit);
2033         bp_.bottommargin = widgetsToLength(m->bottomLE, m->bottomUnit);
2034         bp_.headheight = widgetsToLength(m->headheightLE, m->headheightUnit);
2035         bp_.headsep = widgetsToLength(m->headsepLE, m->headsepUnit);
2036         bp_.footskip = widgetsToLength(m->footskipLE, m->footskipUnit);
2037         bp_.columnsep = widgetsToLength(m->columnsepLE, m->columnsepUnit);
2038
2039         branchesModule->apply(bp_);
2040
2041         // PDF support
2042         PDFOptions & pdf = bp_.pdfoptions();
2043         pdf.use_hyperref = pdfSupportModule->use_hyperrefGB->isChecked();
2044         pdf.title = fromqstr(pdfSupportModule->titleLE->text());
2045         pdf.author = fromqstr(pdfSupportModule->authorLE->text());
2046         pdf.subject = fromqstr(pdfSupportModule->subjectLE->text());
2047         pdf.keywords = fromqstr(pdfSupportModule->keywordsLE->text());
2048
2049         pdf.bookmarks = pdfSupportModule->bookmarksGB->isChecked();
2050         pdf.bookmarksnumbered = pdfSupportModule->bookmarksnumberedCB->isChecked();
2051         pdf.bookmarksopen = pdfSupportModule->bookmarksopenGB->isChecked();
2052         pdf.bookmarksopenlevel = pdfSupportModule->bookmarksopenlevelSB->value();
2053
2054         pdf.breaklinks = pdfSupportModule->breaklinksCB->isChecked();
2055         pdf.pdfborder = pdfSupportModule->pdfborderCB->isChecked();
2056         pdf.pdfusetitle = pdfSupportModule->pdfusetitleCB->isChecked();
2057         pdf.colorlinks = pdfSupportModule->colorlinksCB->isChecked();
2058         pdf.backref =
2059                 backref_opts[pdfSupportModule->backrefCO->currentIndex()];
2060         if (pdfSupportModule->fullscreenCB->isChecked())
2061                 pdf.pagemode = pdf.pagemode_fullscreen;
2062         else
2063                 pdf.pagemode.clear();
2064         pdf.quoted_options = pdf.quoted_options_check(
2065                                 fromqstr(pdfSupportModule->optionsLE->text()));
2066 }
2067
2068
2069 void GuiDocument::paramsToDialog()
2070 {
2071         // set the default unit
2072         Length::UNIT const defaultUnit = Length::defaultUnit();
2073
2074         // preamble
2075         preambleModule->update(bp_, id());
2076
2077         // biblio
2078         biblioModule->citeDefaultRB->setChecked(
2079                 bp_.citeEngine() == ENGINE_BASIC);
2080
2081         biblioModule->citeNatbibRB->setChecked(
2082                 bp_.citeEngine() == ENGINE_NATBIB_NUMERICAL ||
2083                 bp_.citeEngine() == ENGINE_NATBIB_AUTHORYEAR);
2084
2085         biblioModule->citeStyleCO->setCurrentIndex(
2086                 bp_.citeEngine() == ENGINE_NATBIB_NUMERICAL);
2087
2088         biblioModule->citeJurabibRB->setChecked(
2089                 bp_.citeEngine() == ENGINE_JURABIB);
2090
2091         biblioModule->bibtopicCB->setChecked(
2092                 bp_.use_bibtopic);
2093
2094         string command;
2095         string options =
2096                 split(bp_.bibtex_command, command, ' ');
2097
2098         int const bpos = biblioModule->bibtexCO->findData(toqstr(command));
2099         if (bpos != -1) {
2100                 biblioModule->bibtexCO->setCurrentIndex(bpos);
2101                 biblioModule->bibtexOptionsED->setText(toqstr(options).trimmed());
2102         } else {
2103                 biblioModule->bibtexCO->setCurrentIndex(0);
2104                 biblioModule->bibtexOptionsED->clear();
2105         }
2106         biblioModule->bibtexOptionsED->setEnabled(
2107                 biblioModule->bibtexCO->currentIndex() != 0);
2108
2109         // indices
2110         indicesModule->update(bp_);
2111
2112         // language & quotes
2113         int const pos = langModule->languageCO->findData(toqstr(
2114                 bp_.language->lang()));
2115         langModule->languageCO->setCurrentIndex(pos);
2116
2117         langModule->quoteStyleCO->setCurrentIndex(
2118                 bp_.quotes_language);
2119
2120         bool default_enc = true;
2121         if (bp_.inputenc != "auto") {
2122                 default_enc = false;
2123                 if (bp_.inputenc == "default") {
2124                         langModule->encodingCO->setCurrentIndex(0);
2125                 } else {
2126                         string enc_gui;
2127                         Encodings::const_iterator it = encodings.begin();
2128                         Encodings::const_iterator const end = encodings.end();
2129                         for (; it != end; ++it) {
2130                                 if (it->latexName() == bp_.inputenc) {
2131                                         enc_gui = it->guiName();
2132                                         break;
2133                                 }
2134                         }
2135                         int const i = langModule->encodingCO->findText(
2136                                         qt_(enc_gui));
2137                         if (i >= 0)
2138                                 langModule->encodingCO->setCurrentIndex(i);
2139                         else
2140                                 // unknown encoding. Set to default.
2141                                 default_enc = true;
2142                 }
2143         }
2144         langModule->defaultencodingRB->setChecked(default_enc);
2145         langModule->otherencodingRB->setChecked(!default_enc);
2146
2147         // numbering
2148         int const min_toclevel = documentClass().min_toclevel();
2149         int const max_toclevel = documentClass().max_toclevel();
2150         if (documentClass().hasTocLevels()) {
2151                 numberingModule->setEnabled(true);
2152                 numberingModule->depthSL->setMinimum(min_toclevel - 1);
2153                 numberingModule->depthSL->setMaximum(max_toclevel);
2154                 numberingModule->depthSL->setValue(bp_.secnumdepth);
2155                 numberingModule->tocSL->setMaximum(min_toclevel - 1);
2156                 numberingModule->tocSL->setMaximum(max_toclevel);
2157                 numberingModule->tocSL->setValue(bp_.tocdepth);
2158                 updateNumbering();
2159         } else {
2160                 numberingModule->setEnabled(false);
2161                 numberingModule->tocTW->clear();
2162         }
2163
2164         // bullets
2165         bulletsModule->setBullet(0, bp_.user_defined_bullet(0));
2166         bulletsModule->setBullet(1, bp_.user_defined_bullet(1));
2167         bulletsModule->setBullet(2, bp_.user_defined_bullet(2));
2168         bulletsModule->setBullet(3, bp_.user_defined_bullet(3));
2169         bulletsModule->init();
2170
2171         // packages
2172         int nitem = findToken(tex_graphics, bp_.graphicsDriver);
2173         if (nitem >= 0)
2174                 latexModule->psdriverCO->setCurrentIndex(nitem);
2175         updateModuleInfo();
2176         
2177         mathsModule->amsCB->setChecked(
2178                 bp_.use_amsmath == BufferParams::package_on);
2179         mathsModule->amsautoCB->setChecked(
2180                 bp_.use_amsmath == BufferParams::package_auto);
2181
2182         mathsModule->esintCB->setChecked(
2183                 bp_.use_esint == BufferParams::package_on);
2184         mathsModule->esintautoCB->setChecked(
2185                 bp_.use_esint == BufferParams::package_auto);
2186
2187         switch (bp_.spacing().getSpace()) {
2188                 case Spacing::Other: nitem = 3; break;
2189                 case Spacing::Double: nitem = 2; break;
2190                 case Spacing::Onehalf: nitem = 1; break;
2191                 case Spacing::Default: case Spacing::Single: nitem = 0; break;
2192         }
2193
2194         // text layout
2195         string const & layoutID = bp_.baseClassID();
2196         setLayoutComboByIDString(layoutID);
2197
2198         updatePagestyle(documentClass().opt_pagestyle(),
2199                                  bp_.pagestyle);
2200
2201         textLayoutModule->lspacingCO->setCurrentIndex(nitem);
2202         if (bp_.spacing().getSpace() == Spacing::Other) {
2203                 textLayoutModule->lspacingLE->setText(
2204                         toqstr(bp_.spacing().getValueAsString()));
2205         }
2206         setLSpacing(nitem);
2207
2208         if (bp_.paragraph_separation == BufferParams::ParagraphIndentSeparation)
2209                 textLayoutModule->indentRB->setChecked(true);
2210         else
2211                 textLayoutModule->skipRB->setChecked(true);
2212
2213         int skip = 0;
2214         switch (bp_.getDefSkip().kind()) {
2215         case VSpace::SMALLSKIP:
2216                 skip = 0;
2217                 break;
2218         case VSpace::MEDSKIP:
2219                 skip = 1;
2220                 break;
2221         case VSpace::BIGSKIP:
2222                 skip = 2;
2223                 break;
2224         case VSpace::LENGTH:
2225         {
2226                 skip = 3;
2227                 string const length = bp_.getDefSkip().asLyXCommand();
2228                 lengthToWidgets(textLayoutModule->skipLE,
2229                         textLayoutModule->skipLengthCO,
2230                         length, defaultUnit);
2231                 break;
2232         }
2233         default:
2234                 skip = 0;
2235                 break;
2236         }
2237         textLayoutModule->skipCO->setCurrentIndex(skip);
2238         setSkip(skip);
2239
2240         textLayoutModule->twoColumnCB->setChecked(
2241                 bp_.columns == 2);
2242
2243         // break listings_params to multiple lines
2244         string lstparams =
2245                 InsetListingsParams(bp_.listings_params).separatedParams();
2246         textLayoutModule->listingsED->setPlainText(toqstr(lstparams));
2247
2248         if (!bp_.options.empty()) {
2249                 latexModule->optionsLE->setText(
2250                         toqstr(bp_.options));
2251         } else {
2252                 latexModule->optionsLE->setText(QString());
2253         }
2254
2255         // latex
2256         latexModule->defaultOptionsCB->setChecked(
2257                         bp_.use_default_options);
2258         updateSelectedModules();
2259         selectionManager->updateProvidedModules(
2260                         bp_.baseClass()->providedModules());
2261         selectionManager->updateExcludedModules(
2262                         bp_.baseClass()->excludedModules());
2263
2264         if (!documentClass().options().empty()) {
2265                 latexModule->defaultOptionsLE->setText(
2266                         toqstr(documentClass().options()));
2267         } else {
2268                 latexModule->defaultOptionsLE->setText(
2269                         toqstr(_("[No options predefined]")));
2270         }
2271
2272         latexModule->defaultOptionsLE->setEnabled(
2273                 bp_.use_default_options
2274                 && !documentClass().options().empty());
2275
2276         latexModule->defaultOptionsCB->setEnabled(
2277                 !documentClass().options().empty());
2278
2279         if (!bp_.master.empty()) {
2280                 latexModule->childDocGB->setChecked(true);
2281                 latexModule->childDocLE->setText(
2282                         toqstr(bp_.master));
2283         } else {
2284                 latexModule->childDocLE->setText(QString());
2285                 latexModule->childDocGB->setChecked(false);
2286         }
2287
2288         floatModule->set(bp_.float_placement);
2289
2290         // Output
2291         // update combobox with formats
2292         updateDefaultFormat();
2293         int index = outputModule->defaultFormatCO->findData(toqstr(
2294                 bp_.defaultOutputFormat));
2295         // set to default if format is not found 
2296         if (index == -1)
2297                 index = 0;
2298         outputModule->defaultFormatCO->setCurrentIndex(index);
2299         outputModule->xetexCB->setEnabled(bp_.baseClass()->outputType() == lyx::LATEX);
2300         outputModule->xetexCB->setChecked(
2301                 bp_.baseClass()->outputType() == lyx::LATEX && bp_.useXetex);
2302
2303         // Fonts
2304         updateFontsize(documentClass().opt_fontsize(),
2305                         bp_.fontsize);
2306
2307         if (bp_.useXetex) {
2308                 for (int i = 0; i < fontModule->fontsRomanCO->count(); ++i) {
2309                         if (fontModule->fontsRomanCO->itemText(i) == toqstr(bp_.fontsRoman)) {
2310                                 fontModule->fontsRomanCO->setCurrentIndex(i);
2311                                 return;
2312                         }
2313                 }
2314                 
2315                 for (int i = 0; i < fontModule->fontsSansCO->count(); ++i) {
2316                         if (fontModule->fontsSansCO->itemText(i) == toqstr(bp_.fontsSans)) {
2317                                 fontModule->fontsSansCO->setCurrentIndex(i);
2318                                 return;
2319                         }
2320                 }
2321                 for (int i = 0; i < fontModule->fontsTypewriterCO->count(); ++i) {
2322                         if (fontModule->fontsTypewriterCO->itemText(i) == 
2323                                 toqstr(bp_.fontsTypewriter)) {
2324                                 fontModule->fontsTypewriterCO->setCurrentIndex(i);
2325                                 return;
2326                         }
2327                 }
2328         } else {
2329                 int n = findToken(tex_fonts_roman, bp_.fontsRoman);
2330                 if (n >= 0) {
2331                         fontModule->fontsRomanCO->setCurrentIndex(n);
2332                         romanChanged(n);
2333                 }
2334         
2335                 n = findToken(tex_fonts_sans, bp_.fontsSans);
2336                 if (n >= 0) {
2337                         fontModule->fontsSansCO->setCurrentIndex(n);
2338                         sansChanged(n);
2339                 }
2340         
2341                 n = findToken(tex_fonts_monospaced, bp_.fontsTypewriter);
2342                 if (n >= 0) {
2343                         fontModule->fontsTypewriterCO->setCurrentIndex(n);
2344                         ttChanged(n);
2345                 }
2346         }
2347
2348         if (!bp_.fontsCJK.empty())
2349                 fontModule->cjkFontLE->setText(
2350                         toqstr(bp_.fontsCJK));
2351         else
2352                 fontModule->cjkFontLE->setText(QString());
2353
2354         fontModule->fontScCB->setChecked(bp_.fontsSC);
2355         fontModule->fontOsfCB->setChecked(bp_.fontsOSF);
2356         fontModule->scaleSansSB->setValue(bp_.fontsSansScale);
2357         fontModule->scaleTypewriterSB->setValue(bp_.fontsTypewriterScale);
2358
2359         int nn = findToken(GuiDocument::fontfamilies, bp_.fontsDefaultFamily);
2360         if (nn >= 0)
2361                 fontModule->fontsDefaultCO->setCurrentIndex(nn);
2362
2363         // paper
2364         bool const extern_geometry =
2365                 documentClass().provides("geometry");
2366         int const psize = bp_.papersize;
2367         pageLayoutModule->papersizeCO->setCurrentIndex(psize);
2368         setCustomPapersize(!extern_geometry && psize);
2369         pageLayoutModule->papersizeCO->setEnabled(!extern_geometry);
2370
2371         bool const landscape =
2372                 bp_.orientation == ORIENTATION_LANDSCAPE;
2373         pageLayoutModule->landscapeRB->setChecked(landscape);
2374         pageLayoutModule->portraitRB->setChecked(!landscape);
2375         pageLayoutModule->landscapeRB->setEnabled(!extern_geometry);
2376         pageLayoutModule->portraitRB->setEnabled(!extern_geometry);
2377
2378         pageLayoutModule->facingPagesCB->setChecked(
2379                 bp_.sides == TwoSides);
2380
2381         pageLayoutModule->backgroundPB->setStyleSheet(
2382                 colorButtonStyleSheet(rgb2qcolor(bp_.backgroundcolor)));
2383         set_backgroundcolor = bp_.backgroundcolor;
2384
2385         lengthToWidgets(pageLayoutModule->paperwidthLE,
2386                 pageLayoutModule->paperwidthUnitCO, bp_.paperwidth, defaultUnit);
2387         lengthToWidgets(pageLayoutModule->paperheightLE,
2388                 pageLayoutModule->paperheightUnitCO, bp_.paperheight, defaultUnit);
2389
2390         // margins
2391         Ui::MarginsUi * m = marginsModule;
2392
2393         setMargins(!bp_.use_geometry);
2394
2395         lengthToWidgets(m->topLE, m->topUnit,
2396                 bp_.topmargin, defaultUnit);
2397
2398         lengthToWidgets(m->bottomLE, m->bottomUnit,
2399                 bp_.bottommargin, defaultUnit);
2400
2401         lengthToWidgets(m->innerLE, m->innerUnit,
2402                 bp_.leftmargin, defaultUnit);
2403
2404         lengthToWidgets(m->outerLE, m->outerUnit,
2405                 bp_.rightmargin, defaultUnit);
2406
2407         lengthToWidgets(m->headheightLE, m->headheightUnit,
2408                 bp_.headheight, defaultUnit);
2409
2410         lengthToWidgets(m->headsepLE, m->headsepUnit,
2411                 bp_.headsep, defaultUnit);
2412
2413         lengthToWidgets(m->footskipLE, m->footskipUnit,
2414                 bp_.footskip, defaultUnit);
2415
2416         lengthToWidgets(m->columnsepLE, m->columnsepUnit,
2417                 bp_.columnsep, defaultUnit);
2418
2419         // branches
2420         updateUnknownBranches();
2421         branchesModule->update(bp_);
2422
2423         // PDF support
2424         PDFOptions const & pdf = bp_.pdfoptions();
2425         pdfSupportModule->use_hyperrefGB->setChecked(pdf.use_hyperref);
2426         pdfSupportModule->titleLE->setText(toqstr(pdf.title));
2427         pdfSupportModule->authorLE->setText(toqstr(pdf.author));
2428         pdfSupportModule->subjectLE->setText(toqstr(pdf.subject));
2429         pdfSupportModule->keywordsLE->setText(toqstr(pdf.keywords));
2430
2431         pdfSupportModule->bookmarksGB->setChecked(pdf.bookmarks);
2432         pdfSupportModule->bookmarksnumberedCB->setChecked(pdf.bookmarksnumbered);
2433         pdfSupportModule->bookmarksopenGB->setChecked(pdf.bookmarksopen);
2434
2435         pdfSupportModule->bookmarksopenlevelSB->setValue(pdf.bookmarksopenlevel);
2436
2437         pdfSupportModule->breaklinksCB->setChecked(pdf.breaklinks);
2438         pdfSupportModule->pdfborderCB->setChecked(pdf.pdfborder);
2439         pdfSupportModule->pdfusetitleCB->setChecked(pdf.pdfusetitle);
2440         pdfSupportModule->colorlinksCB->setChecked(pdf.colorlinks);
2441
2442         nn = findToken(backref_opts, pdf.backref);
2443         if (nn >= 0)
2444                 pdfSupportModule->backrefCO->setCurrentIndex(nn);
2445
2446         pdfSupportModule->fullscreenCB->setChecked
2447                 (pdf.pagemode == pdf.pagemode_fullscreen);
2448
2449         pdfSupportModule->optionsLE->setText(
2450                 toqstr(pdf.quoted_options));
2451
2452         // Make sure that the bc is in the INITIAL state
2453         if (bc().policy().buttonStatus(ButtonPolicy::RESTORE))
2454                 bc().restore();
2455
2456         // clear changed branches cache
2457         changedBranches_.clear();
2458 }
2459
2460
2461 void GuiDocument::saveDocDefault()
2462 {
2463         // we have to apply the params first
2464         applyView();
2465         saveAsDefault();
2466 }
2467
2468
2469 void GuiDocument::updateAvailableModules() 
2470 {
2471         modules_av_model_.clear();
2472         list<modInfoStruct> const & modInfoList = getModuleInfo();
2473         list<modInfoStruct>::const_iterator mit = modInfoList.begin();
2474         list<modInfoStruct>::const_iterator men = modInfoList.end();
2475         for (int i = 0; mit != men; ++mit, ++i)
2476                 modules_av_model_.insertRow(i, mit->name, mit->id, 
2477                                 mit->description);
2478 }
2479
2480
2481 void GuiDocument::updateSelectedModules() 
2482 {
2483         modules_sel_model_.clear();
2484         list<modInfoStruct> const selModList = getSelectedModules();
2485         list<modInfoStruct>::const_iterator mit = selModList.begin();
2486         list<modInfoStruct>::const_iterator men = selModList.end();
2487         for (int i = 0; mit != men; ++mit, ++i)
2488                 modules_sel_model_.insertRow(i, mit->name, mit->id, 
2489                                 mit->description);
2490 }
2491
2492
2493 void GuiDocument::updateContents()
2494 {
2495         // Nothing to do here as the document settings is not cursor dependant.
2496         return;
2497 }
2498
2499
2500 void GuiDocument::useClassDefaults()
2501 {
2502         if (applyPB->isEnabled()) {
2503                 int const ret = Alert::prompt(_("Unapplied changes"),
2504                                 _("Some changes in the dialog were not yet applied.\n"
2505                                   "If you do not apply now, they will be lost after this action."),
2506                                 1, 1, _("&Apply"), _("&Dismiss"));
2507                 if (ret == 0)
2508                         applyView();
2509         }
2510
2511         int idx = latexModule->classCO->currentIndex();
2512         string const classname = classes_model_.getIDString(idx);
2513         if (!bp_.setBaseClass(classname)) {
2514                 Alert::error(_("Error"), _("Unable to set document class."));
2515                 return;
2516         }
2517         bp_.useClassDefaults();
2518         paramsToDialog();
2519 }
2520
2521
2522 void GuiDocument::setLayoutComboByIDString(string const & idString)
2523 {
2524         int idx = classes_model_.findIDString(idString);
2525         if (idx < 0)
2526                 Alert::warning(_("Can't set layout!"), 
2527                         bformat(_("Unable to set layout for ID: %1$s"), from_utf8(idString)));
2528         else 
2529                 latexModule->classCO->setCurrentIndex(idx);
2530 }
2531
2532
2533 bool GuiDocument::isValid()
2534 {
2535         return validateListingsParameters().isEmpty()
2536                 && (textLayoutModule->skipCO->currentIndex() != 3
2537                         || !textLayoutModule->skipLE->text().isEmpty());
2538 }
2539
2540
2541 char const * const GuiDocument::fontfamilies[5] = {
2542         "default", "rmdefault", "sfdefault", "ttdefault", ""
2543 };
2544
2545
2546 char const * GuiDocument::fontfamilies_gui[5] = {
2547         N_("Default"), N_("Roman"), N_("Sans Serif"), N_("Typewriter"), ""
2548 };
2549
2550
2551 bool GuiDocument::initialiseParams(string const &)
2552 {
2553         BufferView const * view = bufferview();
2554         if (!view) {
2555                 bp_ = BufferParams();
2556                 paramsToDialog();
2557                 return true;
2558         }
2559         bp_ = view->buffer().params();
2560         loadModuleInfo();
2561         updateAvailableModules();
2562         //FIXME It'd be nice to make sure here that the selected
2563         //modules are consistent: That required modules are actually
2564         //selected, and that we don't have conflicts. If so, we could
2565         //at least pop up a warning.
2566         paramsToDialog();
2567         return true;
2568 }
2569
2570
2571 void GuiDocument::clearParams()
2572 {
2573         bp_ = BufferParams();
2574 }
2575
2576
2577 BufferId GuiDocument::id() const
2578 {
2579         BufferView const * const view = bufferview();
2580         return view? &view->buffer() : 0;
2581 }
2582
2583
2584 list<GuiDocument::modInfoStruct> const & GuiDocument::getModuleInfo()
2585 {
2586         return moduleNames_;
2587 }
2588
2589
2590 list<GuiDocument::modInfoStruct> const 
2591                 GuiDocument::makeModuleInfo(LayoutModuleList const & mods)
2592 {
2593         LayoutModuleList::const_iterator it =  mods.begin();
2594         LayoutModuleList::const_iterator end = mods.end();
2595         list<modInfoStruct> mInfo;
2596         for (; it != end; ++it) {
2597                 modInfoStruct m;
2598                 m.id = *it;
2599                 LyXModule * mod = moduleList[*it];
2600                 if (mod)
2601                         // FIXME Unicode
2602                         m.name = toqstr(translateIfPossible(from_utf8(mod->getName())));
2603                 else 
2604                         m.name = toqstr(*it) + toqstr(" (") + qt_("Not Found") + toqstr(")");
2605                 mInfo.push_back(m);
2606         }
2607         return mInfo;
2608 }
2609
2610
2611 list<GuiDocument::modInfoStruct> const GuiDocument::getSelectedModules()
2612 {
2613         return makeModuleInfo(params().getModules());
2614 }
2615
2616
2617 list<GuiDocument::modInfoStruct> const GuiDocument::getProvidedModules()
2618 {
2619         return makeModuleInfo(params().baseClass()->providedModules());
2620 }
2621
2622
2623 DocumentClass const & GuiDocument::documentClass() const
2624 {
2625         return bp_.documentClass();
2626 }
2627
2628
2629 static void dispatch_bufferparams(Dialog const & dialog,
2630         BufferParams const & bp, FuncCode lfun)
2631 {
2632         ostringstream ss;
2633         ss << "\\begin_header\n";
2634         bp.writeFile(ss);
2635         ss << "\\end_header\n";
2636         dialog.dispatch(FuncRequest(lfun, ss.str()));
2637 }
2638
2639
2640 void GuiDocument::dispatchParams()
2641 {
2642         // This must come first so that a language change is correctly noticed
2643         setLanguage();
2644
2645         // rename branches in the document
2646         executeBranchRenaming();
2647         // and clear changed branches cache
2648         changedBranches_.clear();
2649
2650         // Apply the BufferParams. Note that this will set the base class
2651         // and then update the buffer's layout.
2652         dispatch_bufferparams(*this, params(), LFUN_BUFFER_PARAMS_APPLY);
2653
2654         if (!params().master.empty()) {
2655                 FileName const master_file = support::makeAbsPath(params().master,
2656                            support::onlyPath(buffer().absFileName()));
2657                 if (isLyXFilename(master_file.absFilename())) {
2658                         Buffer * master = checkAndLoadLyXFile(master_file);
2659                         if (master) {
2660                                 if (master->isChild(const_cast<Buffer *>(&buffer())))
2661                                         const_cast<Buffer &>(buffer()).setParent(master);
2662                                 else
2663                                         Alert::warning(_("Assigned master does not include this file"), 
2664                                                 bformat(_("You must include this file in the document\n"
2665                                                           "'%1$s' in order to use the master document\n"
2666                                                           "feature."), from_utf8(params().master)));
2667                         } else
2668                                 Alert::warning(_("Could not load master"), 
2669                                                 bformat(_("The master document '%1$s'\n"
2670                                                            "could not be loaded."),
2671                                                            from_utf8(params().master)));
2672                 }
2673         }
2674
2675         // Generate the colours requested by each new branch.
2676         BranchList & branchlist = params().branchlist();
2677         if (!branchlist.empty()) {
2678                 BranchList::const_iterator it = branchlist.begin();
2679                 BranchList::const_iterator const end = branchlist.end();
2680                 for (; it != end; ++it) {
2681                         docstring const & current_branch = it->branch();
2682                         Branch const * branch = branchlist.find(current_branch);
2683                         string const x11hexname = X11hexname(branch->color());
2684                         // display the new color
2685                         docstring const str = current_branch + ' ' + from_ascii(x11hexname);
2686                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
2687                 }
2688
2689                 // Open insets of selected branches, close deselected ones
2690                 dispatch(FuncRequest(LFUN_ALL_INSETS_TOGGLE,
2691                         "assign branch"));
2692         }
2693         // Generate the colours requested by indices.
2694         IndicesList & indiceslist = params().indiceslist();
2695         if (!indiceslist.empty()) {
2696                 IndicesList::const_iterator it = indiceslist.begin();
2697                 IndicesList::const_iterator const end = indiceslist.end();
2698                 for (; it != end; ++it) {
2699                         docstring const & current_index = it->index();
2700                         Index const * index = indiceslist.find(current_index);
2701                         string const x11hexname = X11hexname(index->color());
2702                         // display the new color
2703                         docstring const str = current_index + ' ' + from_ascii(x11hexname);
2704                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
2705                 }
2706         }
2707         // FIXME: If we used an LFUN, we would not need those two lines:
2708         BufferView * bv = const_cast<BufferView *>(bufferview());
2709         bv->processUpdateFlags(Update::Force | Update::FitCursor);
2710 }
2711
2712
2713 void GuiDocument::setLanguage() const
2714 {
2715         Language const * const newL = bp_.language;
2716         if (buffer().params().language == newL)
2717                 return;
2718
2719         string const & lang_name = newL->lang();
2720         dispatch(FuncRequest(LFUN_BUFFER_LANGUAGE, lang_name));
2721 }
2722
2723
2724 void GuiDocument::saveAsDefault() const
2725 {
2726         dispatch_bufferparams(*this, params(), LFUN_BUFFER_SAVE_AS_DEFAULT);
2727 }
2728
2729
2730 bool GuiDocument::isFontAvailable(string const & font) const
2731 {
2732         if (font == "default" || font == "cmr"
2733             || font == "cmss" || font == "cmtt")
2734                 // these are standard
2735                 return true;
2736         if (font == "lmodern" || font == "lmss" || font == "lmtt")
2737                 return LaTeXFeatures::isAvailable("lmodern");
2738         if (font == "times" || font == "palatino"
2739                  || font == "helvet" || font == "courier")
2740                 return LaTeXFeatures::isAvailable("psnfss");
2741         if (font == "cmbr" || font == "cmtl")
2742                 return LaTeXFeatures::isAvailable("cmbright");
2743         if (font == "utopia")
2744                 return LaTeXFeatures::isAvailable("utopia")
2745                         || LaTeXFeatures::isAvailable("fourier");
2746         if (font == "beraserif" || font == "berasans"
2747                 || font == "beramono")
2748                 return LaTeXFeatures::isAvailable("bera");
2749         return LaTeXFeatures::isAvailable(font);
2750 }
2751
2752
2753 bool GuiDocument::providesOSF(string const & font) const
2754 {
2755         if (outputModule->xetexCB->isChecked())
2756                 // FIXME: we should check if the fonts really
2757                 // have OSF support. But how?
2758                 return true;
2759         if (font == "cmr")
2760                 return isFontAvailable("eco");
2761         if (font == "palatino")
2762                 return isFontAvailable("mathpazo");
2763         return false;
2764 }
2765
2766
2767 bool GuiDocument::providesSC(string const & font) const
2768 {
2769         if (outputModule->xetexCB->isChecked())
2770                 return false;
2771         if (font == "palatino")
2772                 return isFontAvailable("mathpazo");
2773         if (font == "utopia")
2774                 return isFontAvailable("fourier");
2775         return false;
2776 }
2777
2778
2779 bool GuiDocument::providesScale(string const & font) const
2780 {
2781         if (outputModule->xetexCB->isChecked())
2782                 return true;
2783         return font == "helvet" || font == "luximono"
2784                 || font == "berasans"  || font == "beramono";
2785 }
2786
2787
2788 void GuiDocument::loadModuleInfo()
2789 {
2790         moduleNames_.clear();
2791         LyXModuleList::const_iterator it  = moduleList.begin();
2792         LyXModuleList::const_iterator end = moduleList.end();
2793         for (; it != end; ++it) {
2794                 modInfoStruct m;
2795                 m.id = it->getID();
2796                 // FIXME Unicode
2797                 m.name = toqstr(translateIfPossible(from_utf8(it->getName())));
2798                 // this is supposed to give us the first sentence of the description
2799                 // FIXME Unicode
2800                 QString desc =
2801                         toqstr(translateIfPossible(from_utf8(it->getDescription())));
2802                 int const pos = desc.indexOf(".");
2803                 if (pos > 0)
2804                         desc.truncate(pos + 1);
2805                 m.description = desc;
2806                 moduleNames_.push_back(m);
2807         }
2808 }
2809
2810
2811 void GuiDocument::updateUnknownBranches()
2812 {
2813         list<docstring> used_branches;
2814         buffer().getUsedBranches(used_branches);
2815         list<docstring>::const_iterator it = used_branches.begin();
2816         QStringList unknown_branches;
2817         for (; it != used_branches.end() ; ++it) {
2818                 if (!buffer().params().branchlist().find(*it))
2819                         unknown_branches.append(toqstr(*it));
2820         }
2821         branchesModule->setUnknownBranches(unknown_branches);
2822 }
2823
2824
2825 void GuiDocument::branchesRename(docstring const & oldname, docstring const & newname)
2826 {
2827         map<docstring, docstring>::iterator it = changedBranches_.begin();
2828         for (; it != changedBranches_.end() ; ++it) {
2829                 if (it->second == oldname) {
2830                         // branch has already been renamed
2831                         it->second = newname;
2832                         return;
2833                 }
2834         }
2835         // store new name
2836         changedBranches_[oldname] = newname;
2837 }
2838
2839
2840 void GuiDocument::executeBranchRenaming() const
2841 {
2842         map<docstring, docstring>::const_iterator it = changedBranches_.begin();
2843         for (; it != changedBranches_.end() ; ++it) {
2844                 docstring const arg = '"' + it->first + '"' + " " + '"' + it->second + '"';
2845                 dispatch(FuncRequest(LFUN_BRANCHES_RENAME, arg));
2846         }
2847 }
2848
2849
2850 Dialog * createGuiDocument(GuiView & lv) { return new GuiDocument(lv); }
2851
2852
2853 } // namespace frontend
2854 } // namespace lyx
2855
2856 #include "moc_GuiDocument.cpp"