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