]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiDocument.cpp
*sigh*
[lyx.git] / src / frontends / qt4 / GuiDocument.cpp
1 /**
2  * \file GuiDocument.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Edwin Leuven
7  * \author Richard Heck (modules)
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "GuiDocument.h"
15
16 #include "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         updateUnknownBranches();
950
951         // preamble
952         preambleModule = new PreambleModule;
953         connect(preambleModule, SIGNAL(changed()),
954                 this, SLOT(change_adaptor()));
955
956         // bullets
957         bulletsModule = new BulletsModule;
958         connect(bulletsModule, SIGNAL(changed()),
959                 this, SLOT(change_adaptor()));
960
961         // Modules
962         modulesModule = new UiWidget<Ui::ModulesUi>;
963
964         selectionManager =
965                 new ModuleSelectionManager(modulesModule->availableLV,
966                         modulesModule->selectedLV,
967                         modulesModule->addPB, modulesModule->deletePB,
968                         modulesModule->upPB, modulesModule->downPB,
969                         availableModel(), selectedModel(), this);
970         connect(selectionManager, SIGNAL(updateHook()),
971                 this, SLOT(updateModuleInfo()));
972         connect(selectionManager, SIGNAL(updateHook()),
973                 this, SLOT(change_adaptor()));
974         connect(selectionManager, SIGNAL(selectionChanged()),
975                 this, SLOT(modulesChanged()));
976
977         // PDF support
978         pdfSupportModule = new UiWidget<Ui::PDFSupportUi>;
979
980         connect(pdfSupportModule->use_hyperrefGB, SIGNAL(toggled(bool)),
981                 this, SLOT(change_adaptor()));
982         connect(pdfSupportModule->titleLE, SIGNAL(textChanged(QString)),
983                 this, SLOT(change_adaptor()));
984         connect(pdfSupportModule->authorLE, SIGNAL(textChanged(QString)),
985                 this, SLOT(change_adaptor()));
986         connect(pdfSupportModule->subjectLE, SIGNAL(textChanged(QString)),
987                 this, SLOT(change_adaptor()));
988         connect(pdfSupportModule->keywordsLE, SIGNAL(textChanged(QString)),
989                 this, SLOT(change_adaptor()));
990         connect(pdfSupportModule->bookmarksGB, SIGNAL(toggled(bool)),
991                 this, SLOT(change_adaptor()));
992         connect(pdfSupportModule->bookmarksnumberedCB, SIGNAL(toggled(bool)),
993                 this, SLOT(change_adaptor()));
994         connect(pdfSupportModule->bookmarksopenGB, SIGNAL(toggled(bool)),
995                 this, SLOT(change_adaptor()));
996         connect(pdfSupportModule->bookmarksopenlevelSB, SIGNAL(valueChanged(int)),
997                 this, SLOT(change_adaptor()));
998         connect(pdfSupportModule->breaklinksCB, SIGNAL(toggled(bool)),
999                 this, SLOT(change_adaptor()));
1000         connect(pdfSupportModule->pdfborderCB, SIGNAL(toggled(bool)),
1001                 this, SLOT(change_adaptor()));
1002         connect(pdfSupportModule->colorlinksCB, SIGNAL(toggled(bool)),
1003                 this, SLOT(change_adaptor()));
1004         connect(pdfSupportModule->backrefCO, SIGNAL(activated(int)),
1005                 this, SLOT(change_adaptor()));
1006         connect(pdfSupportModule->pdfusetitleCB, SIGNAL(toggled(bool)),
1007                 this, SLOT(change_adaptor()));
1008         connect(pdfSupportModule->fullscreenCB, SIGNAL(toggled(bool)),
1009                 this, SLOT(change_adaptor()));
1010         connect(pdfSupportModule->optionsLE, SIGNAL(textChanged(QString)),
1011                 this, SLOT(change_adaptor()));
1012
1013         for (int i = 0; backref_opts[i][0]; ++i)
1014                 pdfSupportModule->backrefCO->addItem(qt_(backref_opts_gui[i]));
1015
1016         // float
1017         floatModule = new FloatPlacement;
1018         connect(floatModule, SIGNAL(changed()),
1019                 this, SLOT(change_adaptor()));
1020
1021         docPS->addPanel(latexModule, qt_("Document Class"));
1022         docPS->addPanel(modulesModule, qt_("Modules"));
1023         docPS->addPanel(fontModule, qt_("Fonts"));
1024         docPS->addPanel(textLayoutModule, qt_("Text Layout"));
1025         docPS->addPanel(pageLayoutModule, qt_("Page Layout"));
1026         docPS->addPanel(marginsModule, qt_("Page Margins"));
1027         docPS->addPanel(langModule, qt_("Language"));
1028         docPS->addPanel(numberingModule, qt_("Numbering & TOC"));
1029         docPS->addPanel(biblioModule, qt_("Bibliography"));
1030         docPS->addPanel(indicesModule, qt_("Indexes"));
1031         docPS->addPanel(pdfSupportModule, qt_("PDF Properties"));
1032         docPS->addPanel(mathsModule, qt_("Math Options"));
1033         docPS->addPanel(floatModule, qt_("Float Placement"));
1034         docPS->addPanel(bulletsModule, qt_("Bullets"));
1035         docPS->addPanel(branchesModule, qt_("Branches"));
1036         docPS->addPanel(outputModule, qt_("Output"));
1037         docPS->addPanel(preambleModule, qt_("LaTeX Preamble"));
1038         docPS->setCurrentPanel(qt_("Document Class"));
1039 // FIXME: hack to work around resizing bug in Qt >= 4.2
1040 // bug verified with Qt 4.2.{0-3} (JSpitzm)
1041 #if QT_VERSION >= 0x040200
1042         docPS->updateGeometry();
1043 #endif
1044 }
1045
1046
1047 void GuiDocument::showPreamble()
1048 {
1049         docPS->setCurrentPanel(qt_("LaTeX Preamble"));
1050 }
1051
1052
1053 void GuiDocument::saveDefaultClicked()
1054 {
1055         saveDocDefault();
1056 }
1057
1058
1059 void GuiDocument::useDefaultsClicked()
1060 {
1061         useClassDefaults();
1062 }
1063
1064
1065 void GuiDocument::change_adaptor()
1066 {
1067         changed();
1068 }
1069
1070
1071 QString GuiDocument::validateListingsParameters()
1072 {
1073         // use a cache here to avoid repeated validation
1074         // of the same parameters
1075         static string param_cache;
1076         static QString msg_cache;
1077         
1078         if (textLayoutModule->bypassCB->isChecked())
1079                 return QString();
1080
1081         string params = fromqstr(textLayoutModule->listingsED->toPlainText());
1082         if (params != param_cache) {
1083                 param_cache = params;
1084                 msg_cache = toqstr(InsetListingsParams(params).validate());
1085         }
1086         return msg_cache;
1087 }
1088
1089
1090 void GuiDocument::setListingsMessage()
1091 {
1092         static bool isOK = true;
1093         QString msg = validateListingsParameters();
1094         if (msg.isEmpty()) {
1095                 if (isOK)
1096                         return;
1097                 isOK = true;
1098                 // listingsTB->setTextColor("black");
1099                 textLayoutModule->listingsTB->setPlainText(
1100                         qt_("Input listings parameters on the right. "
1101                 "Enter ? for a list of parameters."));
1102         } else {
1103                 isOK = false;
1104                 // listingsTB->setTextColor("red");
1105                 textLayoutModule->listingsTB->setPlainText(msg);
1106         }
1107 }
1108
1109
1110 void GuiDocument::setLSpacing(int item)
1111 {
1112         textLayoutModule->lspacingLE->setEnabled(item == 3);
1113 }
1114
1115
1116 void GuiDocument::setSkip(int item)
1117 {
1118         bool const enable = (item == 3);
1119         textLayoutModule->skipLE->setEnabled(enable);
1120         textLayoutModule->skipLengthCO->setEnabled(enable);
1121 }
1122
1123
1124 void GuiDocument::enableSkip(bool skip)
1125 {
1126         textLayoutModule->skipCO->setEnabled(skip);
1127         textLayoutModule->skipLE->setEnabled(skip);
1128         textLayoutModule->skipLengthCO->setEnabled(skip);
1129         if (skip)
1130                 setSkip(textLayoutModule->skipCO->currentIndex());
1131 }
1132
1133
1134 void GuiDocument::portraitChanged()
1135 {
1136         setMargins(pageLayoutModule->papersizeCO->currentIndex());
1137 }
1138
1139
1140 void GuiDocument::setMargins(bool custom)
1141 {
1142         bool const extern_geometry =
1143                 documentClass().provides("geometry");
1144         marginsModule->marginCB->setEnabled(!extern_geometry);
1145         if (extern_geometry) {
1146                 marginsModule->marginCB->setChecked(false);
1147                 setCustomMargins(true);
1148                 return;
1149         }
1150         marginsModule->marginCB->setChecked(custom);
1151         setCustomMargins(custom);
1152 }
1153
1154
1155 void GuiDocument::setCustomPapersize(int papersize)
1156 {
1157         bool const custom = (papersize == 1);
1158
1159         pageLayoutModule->paperwidthL->setEnabled(custom);
1160         pageLayoutModule->paperwidthLE->setEnabled(custom);
1161         pageLayoutModule->paperwidthUnitCO->setEnabled(custom);
1162         pageLayoutModule->paperheightL->setEnabled(custom);
1163         pageLayoutModule->paperheightLE->setEnabled(custom);
1164         pageLayoutModule->paperheightLE->setFocus();
1165         pageLayoutModule->paperheightUnitCO->setEnabled(custom);
1166 }
1167
1168
1169 void GuiDocument::setColSep()
1170 {
1171         setCustomMargins(marginsModule->marginCB->checkState() == Qt::Checked);
1172 }
1173
1174
1175 void GuiDocument::setCustomMargins(bool custom)
1176 {
1177         marginsModule->topL->setEnabled(!custom);
1178         marginsModule->topLE->setEnabled(!custom);
1179         marginsModule->topUnit->setEnabled(!custom);
1180
1181         marginsModule->bottomL->setEnabled(!custom);
1182         marginsModule->bottomLE->setEnabled(!custom);
1183         marginsModule->bottomUnit->setEnabled(!custom);
1184
1185         marginsModule->innerL->setEnabled(!custom);
1186         marginsModule->innerLE->setEnabled(!custom);
1187         marginsModule->innerUnit->setEnabled(!custom);
1188
1189         marginsModule->outerL->setEnabled(!custom);
1190         marginsModule->outerLE->setEnabled(!custom);
1191         marginsModule->outerUnit->setEnabled(!custom);
1192
1193         marginsModule->headheightL->setEnabled(!custom);
1194         marginsModule->headheightLE->setEnabled(!custom);
1195         marginsModule->headheightUnit->setEnabled(!custom);
1196
1197         marginsModule->headsepL->setEnabled(!custom);
1198         marginsModule->headsepLE->setEnabled(!custom);
1199         marginsModule->headsepUnit->setEnabled(!custom);
1200
1201         marginsModule->footskipL->setEnabled(!custom);
1202         marginsModule->footskipLE->setEnabled(!custom);
1203         marginsModule->footskipUnit->setEnabled(!custom);
1204
1205         bool const enableColSep = !custom && 
1206                         textLayoutModule->twoColumnCB->checkState() == Qt::Checked;
1207         marginsModule->columnsepL->setEnabled(enableColSep);
1208         marginsModule->columnsepLE->setEnabled(enableColSep);
1209         marginsModule->columnsepUnit->setEnabled(enableColSep);
1210 }
1211
1212 void GuiDocument::changeBackgroundColor()
1213 {
1214         QColor const & newColor = QColorDialog::getColor(
1215                 rgb2qcolor(set_backgroundcolor), asQWidget());
1216         if (!newColor.isValid())
1217                 return;
1218         // set the button color
1219         pageLayoutModule->backgroundPB->setStyleSheet(
1220                 colorButtonStyleSheet(newColor));
1221         // save color
1222         set_backgroundcolor = rgbFromHexName(fromqstr(newColor.name()));
1223         changed();
1224 }
1225
1226
1227 void GuiDocument::deleteBackgroundColor()
1228 {
1229         // set the button color back to white
1230         pageLayoutModule->backgroundPB->setStyleSheet(
1231                 colorButtonStyleSheet(QColor(Qt::white)));
1232         // save white as the set color
1233         set_backgroundcolor = rgbFromHexName("#ffffff");
1234         changed();
1235 }
1236
1237
1238 void GuiDocument::xetexChanged(bool xetex)
1239 {
1240         updateFontlist();
1241         updateDefaultFormat();
1242         langModule->encodingCO->setEnabled(!xetex &&
1243                 !langModule->defaultencodingRB->isChecked());
1244         langModule->defaultencodingRB->setEnabled(!xetex);
1245         langModule->otherencodingRB->setEnabled(!xetex);
1246
1247         fontModule->fontsDefaultCO->setEnabled(!xetex);
1248         fontModule->fontsDefaultLA->setEnabled(!xetex);
1249         fontModule->cjkFontLE->setEnabled(!xetex);
1250         fontModule->cjkFontLA->setEnabled(!xetex);
1251         string font;
1252         if (!xetex)
1253                 font = tex_fonts_sans[fontModule->fontsSansCO->currentIndex()];
1254         bool scaleable = providesScale(font);
1255         fontModule->scaleSansSB->setEnabled(scaleable);
1256         fontModule->scaleSansLA->setEnabled(scaleable);
1257         if (!xetex)
1258                 font = tex_fonts_monospaced[fontModule->fontsTypewriterCO->currentIndex()];
1259         scaleable = providesScale(font);
1260         fontModule->scaleTypewriterSB->setEnabled(scaleable);
1261         fontModule->scaleTypewriterLA->setEnabled(scaleable);
1262         if (!xetex)
1263                 font = tex_fonts_roman[fontModule->fontsRomanCO->currentIndex()];
1264         fontModule->fontScCB->setEnabled(providesSC(font));
1265         fontModule->fontOsfCB->setEnabled(providesOSF(font));
1266 }
1267
1268
1269 void GuiDocument::updateFontsize(string const & items, string const & sel)
1270 {
1271         fontModule->fontsizeCO->clear();
1272         fontModule->fontsizeCO->addItem(qt_("Default"));
1273
1274         for (int n = 0; !token(items,'|',n).empty(); ++n)
1275                 fontModule->fontsizeCO->
1276                         addItem(toqstr(token(items,'|',n)));
1277
1278         for (int n = 0; n < fontModule->fontsizeCO->count(); ++n) {
1279                 if (fromqstr(fontModule->fontsizeCO->itemText(n)) == sel) {
1280                         fontModule->fontsizeCO->setCurrentIndex(n);
1281                         break;
1282                 }
1283         }
1284 }
1285
1286
1287 void GuiDocument::updateFontlist()
1288 {
1289         fontModule->fontsRomanCO->clear();
1290         fontModule->fontsSansCO->clear();
1291         fontModule->fontsTypewriterCO->clear();
1292
1293         // With XeTeX, we have access to all system fonts, but not the LaTeX fonts
1294         if (outputModule->xetexCB->isChecked()) {
1295                 fontModule->fontsRomanCO->addItem(qt_("Default"));
1296                 fontModule->fontsSansCO->addItem(qt_("Default"));
1297                 fontModule->fontsTypewriterCO->addItem(qt_("Default"));
1298         
1299                 QFontDatabase fontdb;
1300                 QStringList families(fontdb.families());
1301                 for (QStringList::Iterator it = families.begin(); it != families.end(); ++it) {
1302                         fontModule->fontsRomanCO->addItem(*it);
1303                         fontModule->fontsSansCO->addItem(*it);
1304                         fontModule->fontsTypewriterCO->addItem(*it);
1305                 }
1306                 return;
1307         }
1308
1309         for (int n = 0; tex_fonts_roman[n][0]; ++n) {
1310                 QString font = qt_(tex_fonts_roman_gui[n]);
1311                 if (!isFontAvailable(tex_fonts_roman[n]))
1312                         font += qt_(" (not installed)");
1313                 fontModule->fontsRomanCO->addItem(font);
1314         }
1315         for (int n = 0; tex_fonts_sans[n][0]; ++n) {
1316                 QString font = qt_(tex_fonts_sans_gui[n]);
1317                 if (!isFontAvailable(tex_fonts_sans[n]))
1318                         font += qt_(" (not installed)");
1319                 fontModule->fontsSansCO->addItem(font);
1320         }
1321         for (int n = 0; tex_fonts_monospaced[n][0]; ++n) {
1322                 QString font = qt_(tex_fonts_monospaced_gui[n]);
1323                 if (!isFontAvailable(tex_fonts_monospaced[n]))
1324                         font += qt_(" (not installed)");
1325                 fontModule->fontsTypewriterCO->addItem(font);
1326         }
1327 }
1328
1329
1330 void GuiDocument::romanChanged(int item)
1331 {
1332         if (outputModule->xetexCB->isChecked())
1333                 return;
1334         string const font = tex_fonts_roman[item];
1335         fontModule->fontScCB->setEnabled(providesSC(font));
1336         fontModule->fontOsfCB->setEnabled(providesOSF(font));
1337 }
1338
1339
1340 void GuiDocument::sansChanged(int item)
1341 {
1342         if (outputModule->xetexCB->isChecked())
1343                 return;
1344         string const font = tex_fonts_sans[item];
1345         bool scaleable = providesScale(font);
1346         fontModule->scaleSansSB->setEnabled(scaleable);
1347         fontModule->scaleSansLA->setEnabled(scaleable);
1348 }
1349
1350
1351 void GuiDocument::ttChanged(int item)
1352 {
1353         if (outputModule->xetexCB->isChecked())
1354                 return;
1355         string const font = tex_fonts_monospaced[item];
1356         bool scaleable = providesScale(font);
1357         fontModule->scaleTypewriterSB->setEnabled(scaleable);
1358         fontModule->scaleTypewriterLA->setEnabled(scaleable);
1359 }
1360
1361
1362 void GuiDocument::updatePagestyle(string const & items, string const & sel)
1363 {
1364         pagestyles.clear();
1365         pageLayoutModule->pagestyleCO->clear();
1366         pageLayoutModule->pagestyleCO->addItem(qt_("Default"));
1367
1368         for (int n = 0; !token(items, '|', n).empty(); ++n) {
1369                 string style = token(items, '|', n);
1370                 QString style_gui = qt_(style);
1371                 pagestyles.push_back(pair<string, QString>(style, style_gui));
1372                 pageLayoutModule->pagestyleCO->addItem(style_gui);
1373         }
1374
1375         if (sel == "default") {
1376                 pageLayoutModule->pagestyleCO->setCurrentIndex(0);
1377                 return;
1378         }
1379
1380         int nn = 0;
1381
1382         for (size_t i = 0; i < pagestyles.size(); ++i)
1383                 if (pagestyles[i].first == sel)
1384                         nn = pageLayoutModule->pagestyleCO->findText(pagestyles[i].second);
1385
1386         if (nn > 0)
1387                 pageLayoutModule->pagestyleCO->setCurrentIndex(nn);
1388 }
1389
1390
1391 void GuiDocument::browseLayout()
1392 {
1393         QString const label1 = qt_("Layouts|#o#O");
1394         QString const dir1 = toqstr(lyxrc.document_path);
1395         QStringList const filter(qt_("LyX Layout (*.layout)"));
1396         QString file = browseRelFile(QString(), bufferFilepath(),
1397                 qt_("Local layout file"), filter, false,
1398                 label1, dir1);
1399
1400         if (!file.endsWith(".layout"))
1401                 return;
1402
1403         FileName layoutFile = support::makeAbsPath(fromqstr(file),
1404                 fromqstr(bufferFilepath()));
1405         
1406         int const ret = Alert::prompt(_("Local layout file"),
1407                 _("The layout file you have selected is a local layout\n"
1408                   "file, not one in the system or user directory. Your\n"
1409                   "document may not work with this layout if you do not\n"
1410                   "keep the layout file in the document directory."),
1411                   1, 1, _("&Set Layout"), _("&Cancel"));
1412         if (ret == 1)
1413                 return;
1414
1415         // load the layout file
1416         LayoutFileList & bcl = LayoutFileList::get();
1417         string classname = layoutFile.onlyFileName();
1418         // this will update an existing layout if that layout has been loaded before.
1419         LayoutFileIndex name = bcl.addLocalLayout(
1420                 classname.substr(0, classname.size() - 7),
1421                 layoutFile.onlyPath().absFilename());
1422
1423         if (name.empty()) {
1424                 Alert::error(_("Error"),
1425                         _("Unable to read local layout file."));                
1426                 return;
1427         }
1428
1429         // do not trigger classChanged if there is no change.
1430         if (latexModule->classCO->currentText() == toqstr(name))
1431                 return;
1432                 
1433         // add to combo box
1434         int idx = latexModule->classCO->findText(toqstr(name));
1435         if (idx == -1) {
1436                 classes_model_.insertRow(0, toqstr(name), name);
1437                 latexModule->classCO->setCurrentIndex(0);
1438         } else
1439                 latexModule->classCO->setCurrentIndex(idx);
1440         
1441         classChanged();
1442 }
1443
1444
1445 void GuiDocument::browseMaster()
1446 {
1447         QString const title = qt_("Select master document");
1448         QString const dir1 = toqstr(lyxrc.document_path);
1449         QString const old = latexModule->childDocLE->text();
1450         QString const docpath = toqstr(support::onlyPath(buffer().absFileName()));
1451         QStringList const filter(qt_("LyX Files (*.lyx)"));
1452         QString file = browseRelFile(old, docpath, title, filter, false,
1453                 qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
1454
1455         latexModule->childDocLE->setText(file);
1456 }
1457
1458
1459 void GuiDocument::classChanged()
1460 {
1461         int idx = latexModule->classCO->currentIndex();
1462         if (idx < 0) 
1463                 return;
1464         string const classname = classes_model_.getIDString(idx);
1465
1466         // check whether the selected modules have changed.
1467         bool modules_changed = false;
1468         unsigned int const srows = selectedModel()->rowCount();
1469         if (srows != bp_.getModules().size())
1470                 modules_changed = true;
1471         else {
1472                 list<string>::const_iterator mit = bp_.getModules().begin();
1473                 list<string>::const_iterator men = bp_.getModules().end();
1474                 for (unsigned int i = 0; i < srows && mit != men; ++i, ++mit)
1475                         if (selectedModel()->getIDString(i) != *mit) {
1476                                 modules_changed = true;
1477                                 break;
1478                         }
1479         }
1480
1481         if (modules_changed || lyxrc.auto_reset_options) {
1482                 if (applyPB->isEnabled()) {
1483                         int const ret = Alert::prompt(_("Unapplied changes"),
1484                                         _("Some changes in the dialog were not yet applied.\n"
1485                                         "If you do not apply now, they will be lost after this action."),
1486                                         1, 1, _("&Apply"), _("&Dismiss"));
1487                         if (ret == 0)
1488                                 applyView();
1489                 }
1490         }
1491
1492         // We load the TextClass as soon as it is selected. This is
1493         // necessary so that other options in the dialog can be updated
1494         // according to the new class. Note, however, that, if you use 
1495         // the scroll wheel when sitting on the combo box, we'll load a 
1496         // lot of TextClass objects very quickly....
1497         if (!bp_.setBaseClass(classname)) {
1498                 Alert::error(_("Error"), _("Unable to set document class."));
1499                 return;
1500         }
1501         if (lyxrc.auto_reset_options)
1502                 bp_.useClassDefaults();
1503
1504         // With the introduction of modules came a distinction between the base 
1505         // class and the document class. The former corresponds to the main layout 
1506         // file; the latter is that plus the modules (or the document-specific layout,
1507         // or  whatever else there could be). Our parameters come from the document 
1508         // class. So when we set the base class, we also need to recreate the document 
1509         // class. Otherwise, we still have the old one.
1510         bp_.makeDocumentClass();
1511         paramsToDialog();
1512 }
1513
1514
1515 void GuiDocument::bibtexChanged(int n)
1516 {
1517         biblioModule->bibtexOptionsED->setEnabled(n != 0);
1518         changed();
1519 }
1520
1521
1522 namespace {
1523         // This is an insanely complicated attempt to make this sort of thing
1524         // work with RTL languages.
1525         docstring formatStrVec(vector<string> const & v, docstring const & s) 
1526         {
1527                 //this mess formats the list as "v[0], v[1], ..., [s] v[n]"
1528                 if (v.size() == 0)
1529                         return docstring();
1530                 if (v.size() == 1) 
1531                         return from_utf8(v[0]);
1532                 if (v.size() == 2) {
1533                         docstring retval = _("%1$s and %2$s");
1534                         retval = subst(retval, _("and"), s);
1535                         return bformat(retval, from_utf8(v[0]), from_utf8(v[1]));
1536                 }
1537                 // The idea here is to format all but the last two items...
1538                 int const vSize = v.size();
1539                 docstring t2 = _("%1$s, %2$s");
1540                 docstring retval = from_utf8(v[0]);
1541                 for (int i = 1; i < vSize - 2; ++i)
1542                         retval = bformat(t2, retval, from_utf8(v[i])); 
1543                 //...and then to  plug them, and the last two, into this schema
1544                 docstring t = _("%1$s, %2$s, and %3$s");
1545                 t = subst(t, _("and"), s);
1546                 return bformat(t, retval, from_utf8(v[vSize - 2]), from_utf8(v[vSize - 1]));
1547         }
1548         
1549         vector<string> idsToNames(vector<string> const & idList)
1550         {
1551                 vector<string> retval;
1552                 vector<string>::const_iterator it  = idList.begin();
1553                 vector<string>::const_iterator end = idList.end();
1554                 for (; it != end; ++it) {
1555                         LyXModule const * const mod = moduleList[*it];
1556                         if (!mod)
1557                                 retval.push_back(*it + " (Unavailable)");
1558                         else
1559                                 retval.push_back(mod->getName());
1560                 }
1561                 return retval;
1562         }
1563 }
1564
1565
1566 void GuiDocument::modulesToParams(BufferParams & bp)
1567 {
1568         // update list of loaded modules
1569         bp.clearLayoutModules();
1570         int const srows = modules_sel_model_.rowCount();
1571         for (int i = 0; i < srows; ++i)
1572                 bp.addLayoutModule(modules_sel_model_.getIDString(i));
1573
1574         // update the list of removed modules
1575         bp.clearRemovedModules();
1576         LayoutModuleList const & reqmods = bp.baseClass()->defaultModules();
1577         list<string>::const_iterator rit = reqmods.begin();
1578         list<string>::const_iterator ren = reqmods.end();
1579
1580         // check each of the default modules
1581         for (; rit != ren; rit++) {
1582                 list<string>::const_iterator mit = bp.getModules().begin();
1583                 list<string>::const_iterator men = bp.getModules().end();
1584                 bool found = false;
1585                 for (; mit != men; mit++) {
1586                         if (*rit == *mit) {
1587                                 found = true;
1588                                 break;
1589                         }
1590                 }
1591                 if (!found) {
1592                         // the module isn't present so must have been removed by the user
1593                         bp.addRemovedModule(*rit);
1594                 }
1595         }
1596 }
1597
1598 void GuiDocument::modulesChanged()
1599 {
1600         modulesToParams(bp_);
1601         bp_.makeDocumentClass();
1602         paramsToDialog();
1603 }
1604
1605
1606 void GuiDocument::updateModuleInfo()
1607 {
1608         selectionManager->update();
1609         
1610         //Module description
1611         bool const focus_on_selected = selectionManager->selectedFocused();
1612         QListView const * const lv = 
1613                         focus_on_selected ? modulesModule->selectedLV : modulesModule->availableLV;
1614         if (lv->selectionModel()->selectedIndexes().isEmpty()) {
1615                 modulesModule->infoML->document()->clear();
1616                 return;
1617         }
1618         QModelIndex const & idx = lv->selectionModel()->currentIndex();
1619         GuiIdListModel const & id_model = 
1620                         focus_on_selected  ? modules_sel_model_ : modules_av_model_;
1621         string const modName = id_model.getIDString(idx.row());
1622         docstring desc = getModuleDescription(modName);
1623
1624         LayoutModuleList const & provmods = bp_.baseClass()->providedModules();
1625         if (std::find(provmods.begin(), provmods.end(), modName) != provmods.end()) {
1626                 if (!desc.empty())
1627                         desc += "\n";
1628                 desc += _("Module provided by document class.");
1629         }
1630
1631         vector<string> pkglist = getPackageList(modName);
1632         docstring pkgdesc = formatStrVec(pkglist, _("and"));
1633         if (!pkgdesc.empty()) {
1634                 if (!desc.empty())
1635                         desc += "\n";
1636                 desc += bformat(_("Package(s) required: %1$s."), pkgdesc);
1637         }
1638
1639         pkglist = getRequiredList(modName);
1640         if (!pkglist.empty()) {
1641                 vector<string> const reqdescs = idsToNames(pkglist);
1642                 pkgdesc = formatStrVec(reqdescs, _("or"));
1643                 if (!desc.empty())
1644                         desc += "\n";
1645                 desc += bformat(_("Module required: %1$s."), pkgdesc);
1646         }
1647
1648         pkglist = getExcludedList(modName);
1649         if (!pkglist.empty()) {
1650                 vector<string> const reqdescs = idsToNames(pkglist);
1651                 pkgdesc = formatStrVec(reqdescs, _( "and"));
1652                 if (!desc.empty())
1653                         desc += "\n";
1654                 desc += bformat(_("Modules excluded: %1$s."), pkgdesc);
1655         }
1656
1657         if (!isModuleAvailable(modName)) {
1658                 if (!desc.empty())
1659                         desc += "\n";
1660                 desc += _("WARNING: Some required packages are unavailable!");
1661         }
1662
1663         modulesModule->infoML->document()->setPlainText(toqstr(desc));
1664 }
1665
1666
1667 void GuiDocument::updateNumbering()
1668 {
1669         DocumentClass const & tclass = documentClass();
1670
1671         numberingModule->tocTW->setUpdatesEnabled(false);
1672         numberingModule->tocTW->clear();
1673
1674         int const depth = numberingModule->depthSL->value();
1675         int const toc = numberingModule->tocSL->value();
1676         QString const no = qt_("No");
1677         QString const yes = qt_("Yes");
1678         QTreeWidgetItem * item = 0;
1679
1680         DocumentClass::const_iterator lit = tclass.begin();
1681         DocumentClass::const_iterator len = tclass.end();
1682         for (; lit != len; ++lit) {
1683                 int const toclevel = lit->toclevel;
1684                 if (toclevel != Layout::NOT_IN_TOC && lit->labeltype == LABEL_COUNTER) {
1685                         item = new QTreeWidgetItem(numberingModule->tocTW);
1686                         item->setText(0, toqstr(translateIfPossible(lit->name())));
1687                         item->setText(1, (toclevel <= depth) ? yes : no);
1688                         item->setText(2, (toclevel <= toc) ? yes : no);
1689                 }
1690         }
1691
1692         numberingModule->tocTW->setUpdatesEnabled(true);
1693         numberingModule->tocTW->update();
1694 }
1695
1696
1697 void GuiDocument::updateDefaultFormat()
1698 {
1699         // make a copy in order to consider unapplied changes
1700         Buffer * tmpbuf = const_cast<Buffer *>(&buffer());
1701         tmpbuf->params().useXetex = outputModule->xetexCB->isChecked();
1702         int idx = latexModule->classCO->currentIndex();
1703         if (idx >= 0) {
1704                 string const classname = classes_model_.getIDString(idx);
1705                 tmpbuf->params().setBaseClass(classname);
1706                 tmpbuf->params().makeDocumentClass();
1707         }
1708         outputModule->defaultFormatCO->blockSignals(true);
1709         outputModule->defaultFormatCO->clear();
1710         outputModule->defaultFormatCO->addItem(qt_("Default"),
1711                                 QVariant(QString("default")));
1712         typedef vector<Format const *> Formats;
1713         Formats formats = tmpbuf->exportableFormats(true);
1714         Formats::const_iterator cit = formats.begin();
1715         Formats::const_iterator end = formats.end();
1716         for (; cit != end; ++cit)
1717                 outputModule->defaultFormatCO->addItem(qt_((*cit)->prettyname()),
1718                                 QVariant(toqstr((*cit)->name())));
1719         outputModule->defaultFormatCO->blockSignals(false);
1720 }
1721
1722
1723 void GuiDocument::applyView()
1724 {
1725         // preamble
1726         preambleModule->apply(bp_);
1727
1728         // biblio
1729         bp_.setCiteEngine(ENGINE_BASIC);
1730
1731         if (biblioModule->citeNatbibRB->isChecked()) {
1732                 bool const use_numerical_citations =
1733                         biblioModule->citeStyleCO->currentIndex();
1734                 if (use_numerical_citations)
1735                         bp_.setCiteEngine(ENGINE_NATBIB_NUMERICAL);
1736                 else
1737                         bp_.setCiteEngine(ENGINE_NATBIB_AUTHORYEAR);
1738
1739         } else if (biblioModule->citeJurabibRB->isChecked())
1740                 bp_.setCiteEngine(ENGINE_JURABIB);
1741
1742         bp_.use_bibtopic =
1743                 biblioModule->bibtopicCB->isChecked();
1744
1745         string const bibtex_command =
1746                 fromqstr(biblioModule->bibtexCO->itemData(
1747                         biblioModule->bibtexCO->currentIndex()).toString());
1748         string const bibtex_options =
1749                 fromqstr(biblioModule->bibtexOptionsED->text());
1750         if (bibtex_command == "default" || bibtex_options.empty())
1751                 bp_.bibtex_command = bibtex_command;
1752         else
1753                 bp_.bibtex_command = bibtex_command + " " + bibtex_options;
1754
1755         // Indices
1756         indicesModule->apply(bp_);
1757
1758         // language & quotes
1759         if (langModule->defaultencodingRB->isChecked()) {
1760                 bp_.inputenc = "auto";
1761         } else {
1762                 int i = langModule->encodingCO->currentIndex();
1763                 if (i == 0)
1764                         bp_.inputenc = "default";
1765                 else {
1766                         QString const enc_gui =
1767                                 langModule->encodingCO->currentText();
1768                         Encodings::const_iterator it = encodings.begin();
1769                         Encodings::const_iterator const end = encodings.end();
1770                         bool found = false;
1771                         for (; it != end; ++it) {
1772                                 if (qt_(it->guiName()) == enc_gui) {
1773                                         bp_.inputenc = it->latexName();
1774                                         found = true;
1775                                         break;
1776                                 }
1777                         }
1778                         if (!found) {
1779                                 // should not happen
1780                                 lyxerr << "GuiDocument::apply: Unknown encoding! Resetting to default" << endl;
1781                                 bp_.inputenc = "default";
1782                         }
1783                 }
1784         }
1785
1786         InsetQuotes::QuoteLanguage lga = InsetQuotes::EnglishQuotes;
1787         switch (langModule->quoteStyleCO->currentIndex()) {
1788         case 0:
1789                 lga = InsetQuotes::EnglishQuotes;
1790                 break;
1791         case 1:
1792                 lga = InsetQuotes::SwedishQuotes;
1793                 break;
1794         case 2:
1795                 lga = InsetQuotes::GermanQuotes;
1796                 break;
1797         case 3:
1798                 lga = InsetQuotes::PolishQuotes;
1799                 break;
1800         case 4:
1801                 lga = InsetQuotes::FrenchQuotes;
1802                 break;
1803         case 5:
1804                 lga = InsetQuotes::DanishQuotes;
1805                 break;
1806         }
1807         bp_.quotes_language = lga;
1808
1809         QString const lang = langModule->languageCO->itemData(
1810                 langModule->languageCO->currentIndex()).toString();
1811         bp_.language = languages.getLanguage(fromqstr(lang));
1812
1813         // numbering
1814         if (bp_.documentClass().hasTocLevels()) {
1815                 bp_.tocdepth = numberingModule->tocSL->value();
1816                 bp_.secnumdepth = numberingModule->depthSL->value();
1817         }
1818
1819         // bullets
1820         bp_.user_defined_bullet(0) = bulletsModule->bullet(0);
1821         bp_.user_defined_bullet(1) = bulletsModule->bullet(1);
1822         bp_.user_defined_bullet(2) = bulletsModule->bullet(2);
1823         bp_.user_defined_bullet(3) = bulletsModule->bullet(3);
1824
1825         // packages
1826         bp_.graphicsDriver =
1827                 tex_graphics[latexModule->psdriverCO->currentIndex()];
1828         
1829         // text layout
1830         int idx = latexModule->classCO->currentIndex();
1831         if (idx >= 0) {
1832                 string const classname = classes_model_.getIDString(idx);
1833                 bp_.setBaseClass(classname);
1834         }
1835
1836         // Modules
1837         modulesToParams(bp_);
1838
1839         if (mathsModule->amsautoCB->isChecked()) {
1840                 bp_.use_amsmath = BufferParams::package_auto;
1841         } else {
1842                 if (mathsModule->amsCB->isChecked())
1843                         bp_.use_amsmath = BufferParams::package_on;
1844                 else
1845                         bp_.use_amsmath = BufferParams::package_off;
1846         }
1847
1848         if (mathsModule->esintautoCB->isChecked())
1849                 bp_.use_esint = BufferParams::package_auto;
1850         else {
1851                 if (mathsModule->esintCB->isChecked())
1852                         bp_.use_esint = BufferParams::package_on;
1853                 else
1854                         bp_.use_esint = BufferParams::package_off;
1855         }
1856
1857         if (pageLayoutModule->pagestyleCO->currentIndex() == 0)
1858                 bp_.pagestyle = "default";
1859         else {
1860                 QString style_gui = pageLayoutModule->pagestyleCO->currentText();
1861                 for (size_t i = 0; i != pagestyles.size(); ++i)
1862                         if (pagestyles[i].second == style_gui)
1863                                 bp_.pagestyle = pagestyles[i].first;
1864         }
1865
1866         switch (textLayoutModule->lspacingCO->currentIndex()) {
1867         case 0:
1868                 bp_.spacing().set(Spacing::Single);
1869                 break;
1870         case 1:
1871                 bp_.spacing().set(Spacing::Onehalf);
1872                 break;
1873         case 2:
1874                 bp_.spacing().set(Spacing::Double);
1875                 break;
1876         case 3:
1877                 bp_.spacing().set(Spacing::Other,
1878                         fromqstr(textLayoutModule->lspacingLE->text()));
1879                 break;
1880         }
1881
1882         if (textLayoutModule->twoColumnCB->isChecked())
1883                 bp_.columns = 2;
1884         else
1885                 bp_.columns = 1;
1886
1887         // text should have passed validation
1888         bp_.listings_params =
1889                 InsetListingsParams(fromqstr(textLayoutModule->listingsED->toPlainText())).params();
1890
1891         if (textLayoutModule->indentRB->isChecked())
1892                 bp_.paragraph_separation = BufferParams::ParagraphIndentSeparation;
1893         else
1894                 bp_.paragraph_separation = BufferParams::ParagraphSkipSeparation;
1895
1896         switch (textLayoutModule->skipCO->currentIndex()) {
1897         case 0:
1898                 bp_.setDefSkip(VSpace(VSpace::SMALLSKIP));
1899                 break;
1900         case 1:
1901                 bp_.setDefSkip(VSpace(VSpace::MEDSKIP));
1902                 break;
1903         case 2:
1904                 bp_.setDefSkip(VSpace(VSpace::BIGSKIP));
1905                 break;
1906         case 3:
1907         {
1908                 VSpace vs = VSpace(
1909                         widgetsToLength(textLayoutModule->skipLE,
1910                                 textLayoutModule->skipLengthCO)
1911                         );
1912                 bp_.setDefSkip(vs);
1913                 break;
1914         }
1915         default:
1916                 // DocumentDefskipCB assures that this never happens
1917                 // so Assert then !!!  - jbl
1918                 bp_.setDefSkip(VSpace(VSpace::MEDSKIP));
1919                 break;
1920         }
1921
1922         bp_.options =
1923                 fromqstr(latexModule->optionsLE->text());
1924
1925         bp_.use_default_options =
1926                 latexModule->defaultOptionsCB->isChecked();
1927
1928         if (latexModule->childDocGB->isChecked())
1929                 bp_.master =
1930                         fromqstr(latexModule->childDocLE->text());
1931         else
1932                 bp_.master = string();
1933
1934         bp_.float_placement = floatModule->get();
1935
1936         // output
1937         bp_.defaultOutputFormat = fromqstr(outputModule->defaultFormatCO->itemData(
1938                 outputModule->defaultFormatCO->currentIndex()).toString());
1939
1940         bool const xetex = outputModule->xetexCB->isChecked();
1941         bp_.useXetex = xetex;
1942
1943         // fonts
1944         if (xetex) {
1945                 if (fontModule->fontsRomanCO->currentIndex() == 0)
1946                         bp_.fontsRoman = "default";
1947                 else
1948                         bp_.fontsRoman =
1949                                 fromqstr(fontModule->fontsRomanCO->currentText());
1950         
1951                 if (fontModule->fontsSansCO->currentIndex() == 0)
1952                         bp_.fontsSans = "default";
1953                 else
1954                         bp_.fontsSans =
1955                                 fromqstr(fontModule->fontsSansCO->currentText());
1956         
1957                 if (fontModule->fontsTypewriterCO->currentIndex() == 0)
1958                         bp_.fontsTypewriter = "default";
1959                 else
1960                         bp_.fontsTypewriter =
1961                                 fromqstr(fontModule->fontsTypewriterCO->currentText());
1962         } else {
1963                 bp_.fontsRoman =
1964                         tex_fonts_roman[fontModule->fontsRomanCO->currentIndex()];
1965         
1966                 bp_.fontsSans =
1967                         tex_fonts_sans[fontModule->fontsSansCO->currentIndex()];
1968         
1969                 bp_.fontsTypewriter =
1970                         tex_fonts_monospaced[fontModule->fontsTypewriterCO->currentIndex()];
1971         }
1972
1973         bp_.fontsCJK =
1974                 fromqstr(fontModule->cjkFontLE->text());
1975
1976         bp_.fontsSansScale = fontModule->scaleSansSB->value();
1977
1978         bp_.fontsTypewriterScale = fontModule->scaleTypewriterSB->value();
1979
1980         bp_.fontsSC = fontModule->fontScCB->isChecked();
1981
1982         bp_.fontsOSF = fontModule->fontOsfCB->isChecked();
1983
1984         if (xetex)
1985                 bp_.fontsDefaultFamily = "default";
1986         else
1987                 bp_.fontsDefaultFamily = GuiDocument::fontfamilies[
1988                         fontModule->fontsDefaultCO->currentIndex()];
1989
1990         if (fontModule->fontsizeCO->currentIndex() == 0)
1991                 bp_.fontsize = "default";
1992         else
1993                 bp_.fontsize =
1994                         fromqstr(fontModule->fontsizeCO->currentText());
1995
1996         // paper
1997         bp_.papersize = PAPER_SIZE(
1998                 pageLayoutModule->papersizeCO->currentIndex());
1999
2000         // custom, A3, B3 and B4 paper sizes need geometry
2001         int psize = pageLayoutModule->papersizeCO->currentIndex();
2002         bool geom_papersize = (psize == 1 || psize == 5 || psize == 8 || psize == 9);
2003
2004         bp_.paperwidth = widgetsToLength(pageLayoutModule->paperwidthLE,
2005                 pageLayoutModule->paperwidthUnitCO);
2006
2007         bp_.paperheight = widgetsToLength(pageLayoutModule->paperheightLE,
2008                 pageLayoutModule->paperheightUnitCO);
2009
2010         if (pageLayoutModule->facingPagesCB->isChecked())
2011                 bp_.sides = TwoSides;
2012         else
2013                 bp_.sides = OneSide;
2014
2015         if (pageLayoutModule->landscapeRB->isChecked())
2016                 bp_.orientation = ORIENTATION_LANDSCAPE;
2017         else
2018                 bp_.orientation = ORIENTATION_PORTRAIT;
2019
2020         bp_.backgroundcolor = set_backgroundcolor;
2021
2022         // margins
2023         bp_.use_geometry = !marginsModule->marginCB->isChecked()
2024                 || geom_papersize;
2025
2026         Ui::MarginsUi const * m = marginsModule;
2027
2028         bp_.leftmargin = widgetsToLength(m->innerLE, m->innerUnit);
2029         bp_.topmargin = widgetsToLength(m->topLE, m->topUnit);
2030         bp_.rightmargin = widgetsToLength(m->outerLE, m->outerUnit);
2031         bp_.bottommargin = widgetsToLength(m->bottomLE, m->bottomUnit);
2032         bp_.headheight = widgetsToLength(m->headheightLE, m->headheightUnit);
2033         bp_.headsep = widgetsToLength(m->headsepLE, m->headsepUnit);
2034         bp_.footskip = widgetsToLength(m->footskipLE, m->footskipUnit);
2035         bp_.columnsep = widgetsToLength(m->columnsepLE, m->columnsepUnit);
2036
2037         branchesModule->apply(bp_);
2038
2039         // PDF support
2040         PDFOptions & pdf = bp_.pdfoptions();
2041         pdf.use_hyperref = pdfSupportModule->use_hyperrefGB->isChecked();
2042         pdf.title = fromqstr(pdfSupportModule->titleLE->text());
2043         pdf.author = fromqstr(pdfSupportModule->authorLE->text());
2044         pdf.subject = fromqstr(pdfSupportModule->subjectLE->text());
2045         pdf.keywords = fromqstr(pdfSupportModule->keywordsLE->text());
2046
2047         pdf.bookmarks = pdfSupportModule->bookmarksGB->isChecked();
2048         pdf.bookmarksnumbered = pdfSupportModule->bookmarksnumberedCB->isChecked();
2049         pdf.bookmarksopen = pdfSupportModule->bookmarksopenGB->isChecked();
2050         pdf.bookmarksopenlevel = pdfSupportModule->bookmarksopenlevelSB->value();
2051
2052         pdf.breaklinks = pdfSupportModule->breaklinksCB->isChecked();
2053         pdf.pdfborder = pdfSupportModule->pdfborderCB->isChecked();
2054         pdf.pdfusetitle = pdfSupportModule->pdfusetitleCB->isChecked();
2055         pdf.colorlinks = pdfSupportModule->colorlinksCB->isChecked();
2056         pdf.backref =
2057                 backref_opts[pdfSupportModule->backrefCO->currentIndex()];
2058         if (pdfSupportModule->fullscreenCB->isChecked())
2059                 pdf.pagemode = pdf.pagemode_fullscreen;
2060         else
2061                 pdf.pagemode.clear();
2062         pdf.quoted_options = pdf.quoted_options_check(
2063                                 fromqstr(pdfSupportModule->optionsLE->text()));
2064 }
2065
2066
2067 void GuiDocument::paramsToDialog()
2068 {
2069         // set the default unit
2070         Length::UNIT const defaultUnit = Length::defaultUnit();
2071
2072         // preamble
2073         preambleModule->update(bp_, id());
2074
2075         // biblio
2076         biblioModule->citeDefaultRB->setChecked(
2077                 bp_.citeEngine() == ENGINE_BASIC);
2078
2079         biblioModule->citeNatbibRB->setChecked(
2080                 bp_.citeEngine() == ENGINE_NATBIB_NUMERICAL ||
2081                 bp_.citeEngine() == ENGINE_NATBIB_AUTHORYEAR);
2082
2083         biblioModule->citeStyleCO->setCurrentIndex(
2084                 bp_.citeEngine() == ENGINE_NATBIB_NUMERICAL);
2085
2086         biblioModule->citeJurabibRB->setChecked(
2087                 bp_.citeEngine() == ENGINE_JURABIB);
2088
2089         biblioModule->bibtopicCB->setChecked(
2090                 bp_.use_bibtopic);
2091
2092         string command;
2093         string options =
2094                 split(bp_.bibtex_command, command, ' ');
2095
2096         int const bpos = biblioModule->bibtexCO->findData(toqstr(command));
2097         if (bpos != -1) {
2098                 biblioModule->bibtexCO->setCurrentIndex(bpos);
2099                 biblioModule->bibtexOptionsED->setText(toqstr(options).trimmed());
2100         } else {
2101                 biblioModule->bibtexCO->setCurrentIndex(0);
2102                 biblioModule->bibtexOptionsED->clear();
2103         }
2104         biblioModule->bibtexOptionsED->setEnabled(
2105                 biblioModule->bibtexCO->currentIndex() != 0);
2106
2107         // indices
2108         indicesModule->update(bp_);
2109
2110         // language & quotes
2111         int const pos = langModule->languageCO->findData(toqstr(
2112                 bp_.language->lang()));
2113         langModule->languageCO->setCurrentIndex(pos);
2114
2115         langModule->quoteStyleCO->setCurrentIndex(
2116                 bp_.quotes_language);
2117
2118         bool default_enc = true;
2119         if (bp_.inputenc != "auto") {
2120                 default_enc = false;
2121                 if (bp_.inputenc == "default") {
2122                         langModule->encodingCO->setCurrentIndex(0);
2123                 } else {
2124                         string enc_gui;
2125                         Encodings::const_iterator it = encodings.begin();
2126                         Encodings::const_iterator const end = encodings.end();
2127                         for (; it != end; ++it) {
2128                                 if (it->latexName() == bp_.inputenc) {
2129                                         enc_gui = it->guiName();
2130                                         break;
2131                                 }
2132                         }
2133                         int const i = langModule->encodingCO->findText(
2134                                         qt_(enc_gui));
2135                         if (i >= 0)
2136                                 langModule->encodingCO->setCurrentIndex(i);
2137                         else
2138                                 // unknown encoding. Set to default.
2139                                 default_enc = true;
2140                 }
2141         }
2142         langModule->defaultencodingRB->setChecked(default_enc);
2143         langModule->otherencodingRB->setChecked(!default_enc);
2144
2145         // numbering
2146         int const min_toclevel = documentClass().min_toclevel();
2147         int const max_toclevel = documentClass().max_toclevel();
2148         if (documentClass().hasTocLevels()) {
2149                 numberingModule->setEnabled(true);
2150                 numberingModule->depthSL->setMinimum(min_toclevel - 1);
2151                 numberingModule->depthSL->setMaximum(max_toclevel);
2152                 numberingModule->depthSL->setValue(bp_.secnumdepth);
2153                 numberingModule->tocSL->setMaximum(min_toclevel - 1);
2154                 numberingModule->tocSL->setMaximum(max_toclevel);
2155                 numberingModule->tocSL->setValue(bp_.tocdepth);
2156                 updateNumbering();
2157         } else {
2158                 numberingModule->setEnabled(false);
2159                 numberingModule->tocTW->clear();
2160         }
2161
2162         // bullets
2163         bulletsModule->setBullet(0, bp_.user_defined_bullet(0));
2164         bulletsModule->setBullet(1, bp_.user_defined_bullet(1));
2165         bulletsModule->setBullet(2, bp_.user_defined_bullet(2));
2166         bulletsModule->setBullet(3, bp_.user_defined_bullet(3));
2167         bulletsModule->init();
2168
2169         // packages
2170         int nitem = findToken(tex_graphics, bp_.graphicsDriver);
2171         if (nitem >= 0)
2172                 latexModule->psdriverCO->setCurrentIndex(nitem);
2173         updateModuleInfo();
2174         
2175         mathsModule->amsCB->setChecked(
2176                 bp_.use_amsmath == BufferParams::package_on);
2177         mathsModule->amsautoCB->setChecked(
2178                 bp_.use_amsmath == BufferParams::package_auto);
2179
2180         mathsModule->esintCB->setChecked(
2181                 bp_.use_esint == BufferParams::package_on);
2182         mathsModule->esintautoCB->setChecked(
2183                 bp_.use_esint == BufferParams::package_auto);
2184
2185         switch (bp_.spacing().getSpace()) {
2186                 case Spacing::Other: nitem = 3; break;
2187                 case Spacing::Double: nitem = 2; break;
2188                 case Spacing::Onehalf: nitem = 1; break;
2189                 case Spacing::Default: case Spacing::Single: nitem = 0; break;
2190         }
2191
2192         // text layout
2193         string const & layoutID = bp_.baseClassID();
2194         setLayoutComboByIDString(layoutID);
2195
2196         updatePagestyle(documentClass().opt_pagestyle(),
2197                                  bp_.pagestyle);
2198
2199         textLayoutModule->lspacingCO->setCurrentIndex(nitem);
2200         if (bp_.spacing().getSpace() == Spacing::Other) {
2201                 textLayoutModule->lspacingLE->setText(
2202                         toqstr(bp_.spacing().getValueAsString()));
2203         }
2204         setLSpacing(nitem);
2205
2206         if (bp_.paragraph_separation == BufferParams::ParagraphIndentSeparation)
2207                 textLayoutModule->indentRB->setChecked(true);
2208         else
2209                 textLayoutModule->skipRB->setChecked(true);
2210
2211         int skip = 0;
2212         switch (bp_.getDefSkip().kind()) {
2213         case VSpace::SMALLSKIP:
2214                 skip = 0;
2215                 break;
2216         case VSpace::MEDSKIP:
2217                 skip = 1;
2218                 break;
2219         case VSpace::BIGSKIP:
2220                 skip = 2;
2221                 break;
2222         case VSpace::LENGTH:
2223         {
2224                 skip = 3;
2225                 string const length = bp_.getDefSkip().asLyXCommand();
2226                 lengthToWidgets(textLayoutModule->skipLE,
2227                         textLayoutModule->skipLengthCO,
2228                         length, defaultUnit);
2229                 break;
2230         }
2231         default:
2232                 skip = 0;
2233                 break;
2234         }
2235         textLayoutModule->skipCO->setCurrentIndex(skip);
2236         setSkip(skip);
2237
2238         textLayoutModule->twoColumnCB->setChecked(
2239                 bp_.columns == 2);
2240
2241         // break listings_params to multiple lines
2242         string lstparams =
2243                 InsetListingsParams(bp_.listings_params).separatedParams();
2244         textLayoutModule->listingsED->setPlainText(toqstr(lstparams));
2245
2246         if (!bp_.options.empty()) {
2247                 latexModule->optionsLE->setText(
2248                         toqstr(bp_.options));
2249         } else {
2250                 latexModule->optionsLE->setText(QString());
2251         }
2252
2253         // latex
2254         latexModule->defaultOptionsCB->setChecked(
2255                         bp_.use_default_options);
2256         updateSelectedModules();
2257         selectionManager->updateProvidedModules(
2258                         bp_.baseClass()->providedModules());
2259         selectionManager->updateExcludedModules(
2260                         bp_.baseClass()->excludedModules());
2261
2262         if (!documentClass().options().empty()) {
2263                 latexModule->defaultOptionsLE->setText(
2264                         toqstr(documentClass().options()));
2265         } else {
2266                 latexModule->defaultOptionsLE->setText(
2267                         toqstr(_("[No options predefined]")));
2268         }
2269
2270         latexModule->defaultOptionsLE->setEnabled(
2271                 bp_.use_default_options
2272                 && !documentClass().options().empty());
2273
2274         latexModule->defaultOptionsCB->setEnabled(
2275                 !documentClass().options().empty());
2276
2277         if (!bp_.master.empty()) {
2278                 latexModule->childDocGB->setChecked(true);
2279                 latexModule->childDocLE->setText(
2280                         toqstr(bp_.master));
2281         } else {
2282                 latexModule->childDocLE->setText(QString());
2283                 latexModule->childDocGB->setChecked(false);
2284         }
2285
2286         floatModule->set(bp_.float_placement);
2287
2288         // Output
2289         // update combobox with formats
2290         updateDefaultFormat();
2291         int index = outputModule->defaultFormatCO->findData(toqstr(
2292                 bp_.defaultOutputFormat));
2293         // set to default if format is not found 
2294         if (index == -1)
2295                 index = 0;
2296         outputModule->defaultFormatCO->setCurrentIndex(index);
2297         outputModule->xetexCB->setEnabled(bp_.baseClass()->outputType() == lyx::LATEX);
2298         outputModule->xetexCB->setChecked(
2299                 bp_.baseClass()->outputType() == lyx::LATEX && bp_.useXetex);
2300
2301         // Fonts
2302         updateFontsize(documentClass().opt_fontsize(),
2303                         bp_.fontsize);
2304
2305         if (bp_.useXetex) {
2306                 for (int i = 0; i < fontModule->fontsRomanCO->count(); ++i) {
2307                         if (fontModule->fontsRomanCO->itemText(i) == toqstr(bp_.fontsRoman)) {
2308                                 fontModule->fontsRomanCO->setCurrentIndex(i);
2309                                 return;
2310                         }
2311                 }
2312                 
2313                 for (int i = 0; i < fontModule->fontsSansCO->count(); ++i) {
2314                         if (fontModule->fontsSansCO->itemText(i) == toqstr(bp_.fontsSans)) {
2315                                 fontModule->fontsSansCO->setCurrentIndex(i);
2316                                 return;
2317                         }
2318                 }
2319                 for (int i = 0; i < fontModule->fontsTypewriterCO->count(); ++i) {
2320                         if (fontModule->fontsTypewriterCO->itemText(i) == 
2321                                 toqstr(bp_.fontsTypewriter)) {
2322                                 fontModule->fontsTypewriterCO->setCurrentIndex(i);
2323                                 return;
2324                         }
2325                 }
2326         } else {
2327                 int n = findToken(tex_fonts_roman, bp_.fontsRoman);
2328                 if (n >= 0) {
2329                         fontModule->fontsRomanCO->setCurrentIndex(n);
2330                         romanChanged(n);
2331                 }
2332         
2333                 n = findToken(tex_fonts_sans, bp_.fontsSans);
2334                 if (n >= 0) {
2335                         fontModule->fontsSansCO->setCurrentIndex(n);
2336                         sansChanged(n);
2337                 }
2338         
2339                 n = findToken(tex_fonts_monospaced, bp_.fontsTypewriter);
2340                 if (n >= 0) {
2341                         fontModule->fontsTypewriterCO->setCurrentIndex(n);
2342                         ttChanged(n);
2343                 }
2344         }
2345
2346         if (!bp_.fontsCJK.empty())
2347                 fontModule->cjkFontLE->setText(
2348                         toqstr(bp_.fontsCJK));
2349         else
2350                 fontModule->cjkFontLE->setText(QString());
2351
2352         fontModule->fontScCB->setChecked(bp_.fontsSC);
2353         fontModule->fontOsfCB->setChecked(bp_.fontsOSF);
2354         fontModule->scaleSansSB->setValue(bp_.fontsSansScale);
2355         fontModule->scaleTypewriterSB->setValue(bp_.fontsTypewriterScale);
2356
2357         int nn = findToken(GuiDocument::fontfamilies, bp_.fontsDefaultFamily);
2358         if (nn >= 0)
2359                 fontModule->fontsDefaultCO->setCurrentIndex(nn);
2360
2361         // paper
2362         bool const extern_geometry =
2363                 documentClass().provides("geometry");
2364         int const psize = bp_.papersize;
2365         pageLayoutModule->papersizeCO->setCurrentIndex(psize);
2366         setCustomPapersize(!extern_geometry && psize);
2367         pageLayoutModule->papersizeCO->setEnabled(!extern_geometry);
2368
2369         bool const landscape =
2370                 bp_.orientation == ORIENTATION_LANDSCAPE;
2371         pageLayoutModule->landscapeRB->setChecked(landscape);
2372         pageLayoutModule->portraitRB->setChecked(!landscape);
2373         pageLayoutModule->landscapeRB->setEnabled(!extern_geometry);
2374         pageLayoutModule->portraitRB->setEnabled(!extern_geometry);
2375
2376         pageLayoutModule->facingPagesCB->setChecked(
2377                 bp_.sides == TwoSides);
2378
2379         pageLayoutModule->backgroundPB->setStyleSheet(
2380                 colorButtonStyleSheet(rgb2qcolor(bp_.backgroundcolor)));
2381         set_backgroundcolor = bp_.backgroundcolor;
2382
2383         lengthToWidgets(pageLayoutModule->paperwidthLE,
2384                 pageLayoutModule->paperwidthUnitCO, bp_.paperwidth, defaultUnit);
2385         lengthToWidgets(pageLayoutModule->paperheightLE,
2386                 pageLayoutModule->paperheightUnitCO, bp_.paperheight, defaultUnit);
2387
2388         // margins
2389         Ui::MarginsUi * m = marginsModule;
2390
2391         setMargins(!bp_.use_geometry);
2392
2393         lengthToWidgets(m->topLE, m->topUnit,
2394                 bp_.topmargin, defaultUnit);
2395
2396         lengthToWidgets(m->bottomLE, m->bottomUnit,
2397                 bp_.bottommargin, defaultUnit);
2398
2399         lengthToWidgets(m->innerLE, m->innerUnit,
2400                 bp_.leftmargin, defaultUnit);
2401
2402         lengthToWidgets(m->outerLE, m->outerUnit,
2403                 bp_.rightmargin, defaultUnit);
2404
2405         lengthToWidgets(m->headheightLE, m->headheightUnit,
2406                 bp_.headheight, defaultUnit);
2407
2408         lengthToWidgets(m->headsepLE, m->headsepUnit,
2409                 bp_.headsep, defaultUnit);
2410
2411         lengthToWidgets(m->footskipLE, m->footskipUnit,
2412                 bp_.footskip, defaultUnit);
2413
2414         lengthToWidgets(m->columnsepLE, m->columnsepUnit,
2415                 bp_.columnsep, defaultUnit);
2416
2417         // branches
2418         updateUnknownBranches();
2419         branchesModule->update(bp_);
2420
2421         // PDF support
2422         PDFOptions const & pdf = bp_.pdfoptions();
2423         pdfSupportModule->use_hyperrefGB->setChecked(pdf.use_hyperref);
2424         pdfSupportModule->titleLE->setText(toqstr(pdf.title));
2425         pdfSupportModule->authorLE->setText(toqstr(pdf.author));
2426         pdfSupportModule->subjectLE->setText(toqstr(pdf.subject));
2427         pdfSupportModule->keywordsLE->setText(toqstr(pdf.keywords));
2428
2429         pdfSupportModule->bookmarksGB->setChecked(pdf.bookmarks);
2430         pdfSupportModule->bookmarksnumberedCB->setChecked(pdf.bookmarksnumbered);
2431         pdfSupportModule->bookmarksopenGB->setChecked(pdf.bookmarksopen);
2432
2433         pdfSupportModule->bookmarksopenlevelSB->setValue(pdf.bookmarksopenlevel);
2434
2435         pdfSupportModule->breaklinksCB->setChecked(pdf.breaklinks);
2436         pdfSupportModule->pdfborderCB->setChecked(pdf.pdfborder);
2437         pdfSupportModule->pdfusetitleCB->setChecked(pdf.pdfusetitle);
2438         pdfSupportModule->colorlinksCB->setChecked(pdf.colorlinks);
2439
2440         nn = findToken(backref_opts, pdf.backref);
2441         if (nn >= 0)
2442                 pdfSupportModule->backrefCO->setCurrentIndex(nn);
2443
2444         pdfSupportModule->fullscreenCB->setChecked
2445                 (pdf.pagemode == pdf.pagemode_fullscreen);
2446
2447         pdfSupportModule->optionsLE->setText(
2448                 toqstr(pdf.quoted_options));
2449
2450         // Make sure that the bc is in the INITIAL state
2451         if (bc().policy().buttonStatus(ButtonPolicy::RESTORE))
2452                 bc().restore();
2453 }
2454
2455
2456 void GuiDocument::saveDocDefault()
2457 {
2458         // we have to apply the params first
2459         applyView();
2460         saveAsDefault();
2461 }
2462
2463
2464 void GuiDocument::updateAvailableModules() 
2465 {
2466         modules_av_model_.clear();
2467         list<modInfoStruct> const & modInfoList = getModuleInfo();
2468         list<modInfoStruct>::const_iterator mit = modInfoList.begin();
2469         list<modInfoStruct>::const_iterator men = modInfoList.end();
2470         for (int i = 0; mit != men; ++mit, ++i)
2471                 modules_av_model_.insertRow(i, mit->name, mit->id, 
2472                                 mit->description);
2473 }
2474
2475
2476 void GuiDocument::updateSelectedModules() 
2477 {
2478         modules_sel_model_.clear();
2479         list<modInfoStruct> const selModList = getSelectedModules();
2480         list<modInfoStruct>::const_iterator mit = selModList.begin();
2481         list<modInfoStruct>::const_iterator men = selModList.end();
2482         for (int i = 0; mit != men; ++mit, ++i)
2483                 modules_sel_model_.insertRow(i, mit->name, mit->id, 
2484                                 mit->description);
2485 }
2486
2487
2488 void GuiDocument::updateContents()
2489 {
2490         // Nothing to do here as the document settings is not cursor dependant.
2491         return;
2492 }
2493
2494
2495 void GuiDocument::useClassDefaults()
2496 {
2497         if (applyPB->isEnabled()) {
2498                 int const ret = Alert::prompt(_("Unapplied changes"),
2499                                 _("Some changes in the dialog were not yet applied.\n"
2500                                   "If you do not apply now, they will be lost after this action."),
2501                                 1, 1, _("&Apply"), _("&Dismiss"));
2502                 if (ret == 0)
2503                         applyView();
2504         }
2505
2506         int idx = latexModule->classCO->currentIndex();
2507         string const classname = classes_model_.getIDString(idx);
2508         if (!bp_.setBaseClass(classname)) {
2509                 Alert::error(_("Error"), _("Unable to set document class."));
2510                 return;
2511         }
2512         bp_.useClassDefaults();
2513         paramsToDialog();
2514 }
2515
2516
2517 void GuiDocument::setLayoutComboByIDString(string const & idString)
2518 {
2519         int idx = classes_model_.findIDString(idString);
2520         if (idx < 0)
2521                 Alert::warning(_("Can't set layout!"), 
2522                         bformat(_("Unable to set layout for ID: %1$s"), from_utf8(idString)));
2523         else 
2524                 latexModule->classCO->setCurrentIndex(idx);
2525 }
2526
2527
2528 bool GuiDocument::isValid()
2529 {
2530         return validateListingsParameters().isEmpty()
2531                 && (textLayoutModule->skipCO->currentIndex() != 3
2532                         || !textLayoutModule->skipLE->text().isEmpty());
2533 }
2534
2535
2536 char const * const GuiDocument::fontfamilies[5] = {
2537         "default", "rmdefault", "sfdefault", "ttdefault", ""
2538 };
2539
2540
2541 char const * GuiDocument::fontfamilies_gui[5] = {
2542         N_("Default"), N_("Roman"), N_("Sans Serif"), N_("Typewriter"), ""
2543 };
2544
2545
2546 bool GuiDocument::initialiseParams(string const &)
2547 {
2548         BufferView const * view = bufferview();
2549         if (!view) {
2550                 bp_ = BufferParams();
2551                 paramsToDialog();
2552                 return true;
2553         }
2554         bp_ = view->buffer().params();
2555         loadModuleInfo();
2556         updateAvailableModules();
2557         //FIXME It'd be nice to make sure here that the selected
2558         //modules are consistent: That required modules are actually
2559         //selected, and that we don't have conflicts. If so, we could
2560         //at least pop up a warning.
2561         paramsToDialog();
2562         return true;
2563 }
2564
2565
2566 void GuiDocument::clearParams()
2567 {
2568         bp_ = BufferParams();
2569 }
2570
2571
2572 BufferId GuiDocument::id() const
2573 {
2574         BufferView const * const view = bufferview();
2575         return view? &view->buffer() : 0;
2576 }
2577
2578
2579 list<GuiDocument::modInfoStruct> const & GuiDocument::getModuleInfo()
2580 {
2581         return moduleNames_;
2582 }
2583
2584
2585 list<GuiDocument::modInfoStruct> const 
2586                 GuiDocument::makeModuleInfo(LayoutModuleList const & mods)
2587 {
2588         LayoutModuleList::const_iterator it =  mods.begin();
2589         LayoutModuleList::const_iterator end = mods.end();
2590         list<modInfoStruct> mInfo;
2591         for (; it != end; ++it) {
2592                 modInfoStruct m;
2593                 m.id = *it;
2594                 LyXModule * mod = moduleList[*it];
2595                 if (mod)
2596                         // FIXME Unicode
2597                         m.name = toqstr(translateIfPossible(from_utf8(mod->getName())));
2598                 else 
2599                         m.name = toqstr(*it) + toqstr(" (") + qt_("Not Found") + toqstr(")");
2600                 mInfo.push_back(m);
2601         }
2602         return mInfo;
2603 }
2604
2605
2606 list<GuiDocument::modInfoStruct> const GuiDocument::getSelectedModules()
2607 {
2608         return makeModuleInfo(params().getModules());
2609 }
2610
2611
2612 list<GuiDocument::modInfoStruct> const GuiDocument::getProvidedModules()
2613 {
2614         return makeModuleInfo(params().baseClass()->providedModules());
2615 }
2616
2617
2618 DocumentClass const & GuiDocument::documentClass() const
2619 {
2620         return bp_.documentClass();
2621 }
2622
2623
2624 static void dispatch_bufferparams(Dialog const & dialog,
2625         BufferParams const & bp, FuncCode lfun)
2626 {
2627         ostringstream ss;
2628         ss << "\\begin_header\n";
2629         bp.writeFile(ss);
2630         ss << "\\end_header\n";
2631         dialog.dispatch(FuncRequest(lfun, ss.str()));
2632 }
2633
2634
2635 void GuiDocument::dispatchParams()
2636 {
2637         // This must come first so that a language change is correctly noticed
2638         setLanguage();
2639
2640         // Apply the BufferParams. Note that this will set the base class
2641         // and then update the buffer's layout.
2642         dispatch_bufferparams(*this, params(), LFUN_BUFFER_PARAMS_APPLY);
2643
2644         if (!params().master.empty()) {
2645                 FileName const master_file = support::makeAbsPath(params().master,
2646                            support::onlyPath(buffer().absFileName()));
2647                 if (isLyXFilename(master_file.absFilename())) {
2648                         Buffer * master = checkAndLoadLyXFile(master_file);
2649                         if (master) {
2650                                 if (master->isChild(const_cast<Buffer *>(&buffer())))
2651                                         const_cast<Buffer &>(buffer()).setParent(master);
2652                                 else
2653                                         Alert::warning(_("Assigned master does not include this file"), 
2654                                                 bformat(_("You must include this file in the document\n"
2655                                                           "'%1$s' in order to use the master document\n"
2656                                                           "feature."), from_utf8(params().master)));
2657                         } else
2658                                 Alert::warning(_("Could not load master"), 
2659                                                 bformat(_("The master document '%1$s'\n"
2660                                                            "could not be loaded."),
2661                                                            from_utf8(params().master)));
2662                 }
2663         }
2664
2665         // Generate the colours requested by each new branch.
2666         BranchList & branchlist = params().branchlist();
2667         if (!branchlist.empty()) {
2668                 BranchList::const_iterator it = branchlist.begin();
2669                 BranchList::const_iterator const end = branchlist.end();
2670                 for (; it != end; ++it) {
2671                         docstring const & current_branch = it->branch();
2672                         Branch const * branch = branchlist.find(current_branch);
2673                         string const x11hexname = X11hexname(branch->color());
2674                         // display the new color
2675                         docstring const str = current_branch + ' ' + from_ascii(x11hexname);
2676                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
2677                 }
2678
2679                 // Open insets of selected branches, close deselected ones
2680                 dispatch(FuncRequest(LFUN_ALL_INSETS_TOGGLE,
2681                         "assign branch"));
2682         }
2683         // Generate the colours requested by indices.
2684         IndicesList & indiceslist = params().indiceslist();
2685         if (!indiceslist.empty()) {
2686                 IndicesList::const_iterator it = indiceslist.begin();
2687                 IndicesList::const_iterator const end = indiceslist.end();
2688                 for (; it != end; ++it) {
2689                         docstring const & current_index = it->index();
2690                         Index const * index = indiceslist.find(current_index);
2691                         string const x11hexname = X11hexname(index->color());
2692                         // display the new color
2693                         docstring const str = current_index + ' ' + from_ascii(x11hexname);
2694                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
2695                 }
2696         }
2697         // FIXME: If we used an LFUN, we would not need those two lines:
2698         BufferView * bv = const_cast<BufferView *>(bufferview());
2699         bv->processUpdateFlags(Update::Force | Update::FitCursor);
2700 }
2701
2702
2703 void GuiDocument::setLanguage() const
2704 {
2705         Language const * const newL = bp_.language;
2706         if (buffer().params().language == newL)
2707                 return;
2708
2709         string const & lang_name = newL->lang();
2710         dispatch(FuncRequest(LFUN_BUFFER_LANGUAGE, lang_name));
2711 }
2712
2713
2714 void GuiDocument::saveAsDefault() const
2715 {
2716         dispatch_bufferparams(*this, params(), LFUN_BUFFER_SAVE_AS_DEFAULT);
2717 }
2718
2719
2720 bool GuiDocument::isFontAvailable(string const & font) const
2721 {
2722         if (font == "default" || font == "cmr"
2723             || font == "cmss" || font == "cmtt")
2724                 // these are standard
2725                 return true;
2726         if (font == "lmodern" || font == "lmss" || font == "lmtt")
2727                 return LaTeXFeatures::isAvailable("lmodern");
2728         if (font == "times" || font == "palatino"
2729                  || font == "helvet" || font == "courier")
2730                 return LaTeXFeatures::isAvailable("psnfss");
2731         if (font == "cmbr" || font == "cmtl")
2732                 return LaTeXFeatures::isAvailable("cmbright");
2733         if (font == "utopia")
2734                 return LaTeXFeatures::isAvailable("utopia")
2735                         || LaTeXFeatures::isAvailable("fourier");
2736         if (font == "beraserif" || font == "berasans"
2737                 || font == "beramono")
2738                 return LaTeXFeatures::isAvailable("bera");
2739         return LaTeXFeatures::isAvailable(font);
2740 }
2741
2742
2743 bool GuiDocument::providesOSF(string const & font) const
2744 {
2745         if (outputModule->xetexCB->isChecked())
2746                 // FIXME: we should check if the fonts really
2747                 // have OSF support. But how?
2748                 return true;
2749         if (font == "cmr")
2750                 return isFontAvailable("eco");
2751         if (font == "palatino")
2752                 return isFontAvailable("mathpazo");
2753         return false;
2754 }
2755
2756
2757 bool GuiDocument::providesSC(string const & font) const
2758 {
2759         if (outputModule->xetexCB->isChecked())
2760                 return false;
2761         if (font == "palatino")
2762                 return isFontAvailable("mathpazo");
2763         if (font == "utopia")
2764                 return isFontAvailable("fourier");
2765         return false;
2766 }
2767
2768
2769 bool GuiDocument::providesScale(string const & font) const
2770 {
2771         if (outputModule->xetexCB->isChecked())
2772                 return true;
2773         return font == "helvet" || font == "luximono"
2774                 || font == "berasans"  || font == "beramono";
2775 }
2776
2777
2778 void GuiDocument::loadModuleInfo()
2779 {
2780         moduleNames_.clear();
2781         LyXModuleList::const_iterator it  = moduleList.begin();
2782         LyXModuleList::const_iterator end = moduleList.end();
2783         for (; it != end; ++it) {
2784                 modInfoStruct m;
2785                 m.id = it->getID();
2786                 // FIXME Unicode
2787                 m.name = toqstr(translateIfPossible(from_utf8(it->getName())));
2788                 // this is supposed to give us the first sentence of the description
2789                 // FIXME Unicode
2790                 QString desc =
2791                         toqstr(translateIfPossible(from_utf8(it->getDescription())));
2792                 int const pos = desc.indexOf(".");
2793                 if (pos > 0)
2794                         desc.truncate(pos + 1);
2795                 m.description = desc;
2796                 moduleNames_.push_back(m);
2797         }
2798 }
2799
2800
2801 void GuiDocument::updateUnknownBranches()
2802 {
2803         list<docstring> used_branches;
2804         buffer().getUsedBranches(used_branches);
2805         list<docstring>::const_iterator it = used_branches.begin();
2806         QStringList unknown_branches;
2807         for (; it != used_branches.end() ; ++it) {
2808                 if (!buffer().params().branchlist().find(*it))
2809                         unknown_branches.append(toqstr(*it));
2810         }
2811         branchesModule->setUnknownBranches(unknown_branches);
2812 }
2813
2814
2815 Dialog * createGuiDocument(GuiView & lv) { return new GuiDocument(lv); }
2816
2817
2818 } // namespace frontend
2819 } // namespace lyx
2820
2821 #include "moc_GuiDocument.cpp"