]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiDocument.cpp
493ac1a2726bfef556e9d1f637d4ab995a45df8e
[lyx.git] / src / frontends / qt4 / GuiDocument.cpp
1 /**
2  * \file GuiDocument.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Edwin Leuven
7  * \author Richard Heck (modules)
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "GuiDocument.h"
15
16 #include "GuiApplication.h"
17 #include "GuiBranches.h"
18 #include "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         marginsModule->marginCB->setChecked(custom);
1101         setCustomMargins(custom);
1102 }
1103
1104
1105 void GuiDocument::setCustomPapersize(int papersize)
1106 {
1107         bool const custom = (papersize == 1);
1108
1109         pageLayoutModule->paperwidthL->setEnabled(custom);
1110         pageLayoutModule->paperwidthLE->setEnabled(custom);
1111         pageLayoutModule->paperwidthUnitCO->setEnabled(custom);
1112         pageLayoutModule->paperheightL->setEnabled(custom);
1113         pageLayoutModule->paperheightLE->setEnabled(custom);
1114         pageLayoutModule->paperheightLE->setFocus();
1115         pageLayoutModule->paperheightUnitCO->setEnabled(custom);
1116 }
1117
1118
1119 void GuiDocument::setColSep()
1120 {
1121         setCustomMargins(marginsModule->marginCB->checkState() == Qt::Checked);
1122 }
1123
1124
1125 void GuiDocument::setCustomMargins(bool custom)
1126 {
1127         marginsModule->topL->setEnabled(!custom);
1128         marginsModule->topLE->setEnabled(!custom);
1129         marginsModule->topUnit->setEnabled(!custom);
1130
1131         marginsModule->bottomL->setEnabled(!custom);
1132         marginsModule->bottomLE->setEnabled(!custom);
1133         marginsModule->bottomUnit->setEnabled(!custom);
1134
1135         marginsModule->innerL->setEnabled(!custom);
1136         marginsModule->innerLE->setEnabled(!custom);
1137         marginsModule->innerUnit->setEnabled(!custom);
1138
1139         marginsModule->outerL->setEnabled(!custom);
1140         marginsModule->outerLE->setEnabled(!custom);
1141         marginsModule->outerUnit->setEnabled(!custom);
1142
1143         marginsModule->headheightL->setEnabled(!custom);
1144         marginsModule->headheightLE->setEnabled(!custom);
1145         marginsModule->headheightUnit->setEnabled(!custom);
1146
1147         marginsModule->headsepL->setEnabled(!custom);
1148         marginsModule->headsepLE->setEnabled(!custom);
1149         marginsModule->headsepUnit->setEnabled(!custom);
1150
1151         marginsModule->footskipL->setEnabled(!custom);
1152         marginsModule->footskipLE->setEnabled(!custom);
1153         marginsModule->footskipUnit->setEnabled(!custom);
1154
1155         bool const enableColSep = !custom && 
1156                         textLayoutModule->twoColumnCB->checkState() == Qt::Checked;
1157         marginsModule->columnsepL->setEnabled(enableColSep);
1158         marginsModule->columnsepLE->setEnabled(enableColSep);
1159         marginsModule->columnsepUnit->setEnabled(enableColSep);
1160 }
1161
1162
1163 void GuiDocument::updateFontsize(string const & items, string const & sel)
1164 {
1165         fontModule->fontsizeCO->clear();
1166         fontModule->fontsizeCO->addItem(qt_("Default"));
1167
1168         for (int n = 0; !token(items,'|',n).empty(); ++n)
1169                 fontModule->fontsizeCO->
1170                         addItem(toqstr(token(items,'|',n)));
1171
1172         for (int n = 0; n < fontModule->fontsizeCO->count(); ++n) {
1173                 if (fromqstr(fontModule->fontsizeCO->itemText(n)) == sel) {
1174                         fontModule->fontsizeCO->setCurrentIndex(n);
1175                         break;
1176                 }
1177         }
1178 }
1179
1180
1181 void GuiDocument::romanChanged(int item)
1182 {
1183         string const font = tex_fonts_roman[item];
1184         fontModule->fontScCB->setEnabled(providesSC(font));
1185         fontModule->fontOsfCB->setEnabled(providesOSF(font));
1186 }
1187
1188
1189 void GuiDocument::sansChanged(int item)
1190 {
1191         string const font = tex_fonts_sans[item];
1192         bool scaleable = providesScale(font);
1193         fontModule->scaleSansSB->setEnabled(scaleable);
1194         fontModule->scaleSansLA->setEnabled(scaleable);
1195 }
1196
1197
1198 void GuiDocument::ttChanged(int item)
1199 {
1200         string const font = tex_fonts_monospaced[item];
1201         bool scaleable = providesScale(font);
1202         fontModule->scaleTypewriterSB->setEnabled(scaleable);
1203         fontModule->scaleTypewriterLA->setEnabled(scaleable);
1204 }
1205
1206
1207 void GuiDocument::updatePagestyle(string const & items, string const & sel)
1208 {
1209         pagestyles.clear();
1210         pageLayoutModule->pagestyleCO->clear();
1211         pageLayoutModule->pagestyleCO->addItem(qt_("Default"));
1212
1213         for (int n = 0; !token(items, '|', n).empty(); ++n) {
1214                 string style = token(items, '|', n);
1215                 QString style_gui = qt_(style);
1216                 pagestyles.push_back(pair<string, QString>(style, style_gui));
1217                 pageLayoutModule->pagestyleCO->addItem(style_gui);
1218         }
1219
1220         if (sel == "default") {
1221                 pageLayoutModule->pagestyleCO->setCurrentIndex(0);
1222                 return;
1223         }
1224
1225         int nn = 0;
1226
1227         for (size_t i = 0; i < pagestyles.size(); ++i)
1228                 if (pagestyles[i].first == sel)
1229                         nn = pageLayoutModule->pagestyleCO->findText(pagestyles[i].second);
1230
1231         if (nn > 0)
1232                 pageLayoutModule->pagestyleCO->setCurrentIndex(nn);
1233 }
1234
1235
1236 void GuiDocument::browseLayout()
1237 {
1238         QString const label1 = qt_("Layouts|#o#O");
1239         QString const dir1 = toqstr(lyxrc.document_path);
1240         QStringList const filter(qt_("LyX Layout (*.layout)"));
1241         QString file = browseRelFile(QString(), bufferFilepath(),
1242                 qt_("Local layout file"), filter, false,
1243                 label1, dir1);
1244
1245         if (!file.endsWith(".layout"))
1246                 return;
1247
1248         FileName layoutFile = support::makeAbsPath(fromqstr(file),
1249                 fromqstr(bufferFilepath()));
1250         
1251         int const ret = Alert::prompt(_("Local layout file"),
1252                 _("The layout file you have selected is a local layout\n"
1253                   "file, not one in the system or user directory. Your\n"
1254                   "document may not work with this layout if you do not\n"
1255                   "keep the layout file in the document directory."),
1256                   1, 1, _("&Set Layout"), _("&Cancel"));
1257         if (ret == 1)
1258                 return;
1259
1260         // load the layout file
1261         LayoutFileList & bcl = LayoutFileList::get();
1262         string classname = layoutFile.onlyFileName();
1263         // this will update an existing layout if that layout has been loaded before.
1264         LayoutFileIndex name = bcl.addLocalLayout(
1265                 classname.substr(0, classname.size() - 7),
1266                 layoutFile.onlyPath().absFilename());
1267
1268         if (name.empty()) {
1269                 Alert::error(_("Error"),
1270                         _("Unable to read local layout file."));                
1271                 return;
1272         }
1273
1274         // do not trigger classChanged if there is no change.
1275         if (latexModule->classCO->currentText() == toqstr(name))
1276                 return;
1277                 
1278         // add to combo box
1279         int idx = latexModule->classCO->findText(toqstr(name));
1280         if (idx == -1) {
1281                 classes_model_.insertRow(0, toqstr(name), name);
1282                 latexModule->classCO->setCurrentIndex(0);
1283         } else
1284                 latexModule->classCO->setCurrentIndex(idx);
1285         
1286         classChanged();
1287 }
1288
1289
1290 void GuiDocument::browseMaster()
1291 {
1292         QString const title = qt_("Select master document");
1293         QString const dir1 = toqstr(lyxrc.document_path);
1294         QString const old = latexModule->childDocLE->text();
1295         QString const docpath = toqstr(support::onlyPath(buffer().absFileName()));
1296         QStringList const filter(qt_("LyX Files (*.lyx)"));
1297         QString file = browseRelFile(old, docpath, title, filter, false,
1298                 qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
1299
1300         latexModule->childDocLE->setText(file);
1301 }
1302
1303
1304 void GuiDocument::classChanged()
1305 {
1306         int idx = latexModule->classCO->currentIndex();
1307         if (idx < 0) 
1308                 return;
1309         string const classname = classes_model_.getIDString(idx);
1310
1311         // check whether the selected modules have changed.
1312         bool modules_changed = false;
1313         unsigned int const srows = selectedModel()->rowCount();
1314         if (srows != bp_.getModules().size())
1315                 modules_changed = true;
1316         else {
1317                 list<string>::const_iterator mit = bp_.getModules().begin();
1318                 list<string>::const_iterator men = bp_.getModules().end();
1319                 for (unsigned int i = 0; i < srows && mit != men; ++i, ++mit)
1320                         if (selectedModel()->getIDString(i) != *mit) {
1321                                 modules_changed = true;
1322                                 break;
1323                         }
1324         }
1325
1326         if (modules_changed || lyxrc.auto_reset_options) {
1327                 if (applyPB->isEnabled()) {
1328                         int const ret = Alert::prompt(_("Unapplied changes"),
1329                                         _("Some changes in the dialog were not yet applied.\n"
1330                                         "If you do not apply now, they will be lost after this action."),
1331                                         1, 1, _("&Apply"), _("&Dismiss"));
1332                         if (ret == 0)
1333                                 applyView();
1334                 }
1335         }
1336
1337         // We load the TextClass as soon as it is selected. This is
1338         // necessary so that other options in the dialog can be updated
1339         // according to the new class. Note, however, that, if you use 
1340         // the scroll wheel when sitting on the combo box, we'll load a 
1341         // lot of TextClass objects very quickly....
1342         if (!bp_.setBaseClass(classname)) {
1343                 Alert::error(_("Error"), _("Unable to set document class."));
1344                 return;
1345         }
1346         if (lyxrc.auto_reset_options)
1347                 bp_.useClassDefaults();
1348
1349         // With the introduction of modules came a distinction between the base 
1350         // class and the document class. The former corresponds to the main layout 
1351         // file; the latter is that plus the modules (or the document-specific layout,
1352         // or  whatever else there could be). Our parameters come from the document 
1353         // class. So when we set the base class, we also need to recreate the document 
1354         // class. Otherwise, we still have the old one.
1355         bp_.makeDocumentClass();
1356         paramsToDialog();
1357 }
1358
1359
1360 namespace {
1361         // This is an insanely complicated attempt to make this sort of thing
1362         // work with RTL languages.
1363         docstring formatStrVec(vector<string> const & v, docstring const & s) 
1364         {
1365                 //this mess formats the list as "v[0], v[1], ..., [s] v[n]"
1366                 if (v.size() == 0)
1367                         return docstring();
1368                 if (v.size() == 1) 
1369                         return from_utf8(v[0]);
1370                 if (v.size() == 2) {
1371                         docstring retval = _("%1$s and %2$s");
1372                         retval = subst(retval, _("and"), s);
1373                         return bformat(retval, from_utf8(v[0]), from_utf8(v[1]));
1374                 }
1375                 // The idea here is to format all but the last two items...
1376                 int const vSize = v.size();
1377                 docstring t2 = _("%1$s, %2$s");
1378                 docstring retval = from_utf8(v[0]);
1379                 for (int i = 1; i < vSize - 2; ++i)
1380                         retval = bformat(t2, retval, from_utf8(v[i])); 
1381                 //...and then to  plug them, and the last two, into this schema
1382                 docstring t = _("%1$s, %2$s, and %3$s");
1383                 t = subst(t, _("and"), s);
1384                 return bformat(t, retval, from_utf8(v[vSize - 2]), from_utf8(v[vSize - 1]));
1385         }
1386         
1387         vector<string> idsToNames(vector<string> const & idList)
1388         {
1389                 vector<string> retval;
1390                 vector<string>::const_iterator it  = idList.begin();
1391                 vector<string>::const_iterator end = idList.end();
1392                 for (; it != end; ++it) {
1393                         LyXModule const * const mod = moduleList[*it];
1394                         if (!mod)
1395                                 retval.push_back(*it + " (Unavailable)");
1396                         else
1397                                 retval.push_back(mod->getName());
1398                 }
1399                 return retval;
1400         }
1401 }
1402
1403
1404 void GuiDocument::modulesToParams(BufferParams & bp)
1405 {
1406         // update list of loaded modules
1407         bp.clearLayoutModules();
1408         int const srows = modules_sel_model_.rowCount();
1409         for (int i = 0; i < srows; ++i)
1410                 bp.addLayoutModule(modules_sel_model_.getIDString(i));
1411
1412         // update the list of removed modules
1413         bp.clearRemovedModules();
1414         LayoutModuleList const & reqmods = bp.baseClass()->defaultModules();
1415         list<string>::const_iterator rit = reqmods.begin();
1416         list<string>::const_iterator ren = reqmods.end();
1417
1418         // check each of the default modules
1419         for (; rit != ren; rit++) {
1420                 list<string>::const_iterator mit = bp.getModules().begin();
1421                 list<string>::const_iterator men = bp.getModules().end();
1422                 bool found = false;
1423                 for (; mit != men; mit++) {
1424                         if (*rit == *mit) {
1425                                 found = true;
1426                                 break;
1427                         }
1428                 }
1429                 if (!found) {
1430                         // the module isn't present so must have been removed by the user
1431                         bp.addRemovedModule(*rit);
1432                 }
1433         }
1434 }
1435
1436 void GuiDocument::modulesChanged()
1437 {
1438         modulesToParams(bp_);
1439         bp_.makeDocumentClass();
1440         paramsToDialog();
1441 }
1442
1443
1444 void GuiDocument::updateModuleInfo()
1445 {
1446         selectionManager->update();
1447         
1448         //Module description
1449         bool const focus_on_selected = selectionManager->selectedFocused();
1450         QListView const * const lv = 
1451                         focus_on_selected ? modulesModule->selectedLV : modulesModule->availableLV;
1452         if (lv->selectionModel()->selectedIndexes().isEmpty()) {
1453                 modulesModule->infoML->document()->clear();
1454                 return;
1455         }
1456         QModelIndex const & idx = lv->selectionModel()->currentIndex();
1457         GuiIdListModel const & id_model = 
1458                         focus_on_selected  ? modules_sel_model_ : modules_av_model_;
1459         string const modName = id_model.getIDString(idx.row());
1460         docstring desc = getModuleDescription(modName);
1461
1462         LayoutModuleList const & provmods = bp_.baseClass()->providedModules();
1463         if (std::find(provmods.begin(), provmods.end(), modName) != provmods.end()) {
1464                 if (!desc.empty())
1465                         desc += "\n";
1466                 desc += _("Module provided by document class.");
1467         }
1468
1469         vector<string> pkglist = getPackageList(modName);
1470         docstring pkgdesc = formatStrVec(pkglist, _("and"));
1471         if (!pkgdesc.empty()) {
1472                 if (!desc.empty())
1473                         desc += "\n";
1474                 desc += bformat(_("Package(s) required: %1$s."), pkgdesc);
1475         }
1476
1477         pkglist = getRequiredList(modName);
1478         if (!pkglist.empty()) {
1479                 vector<string> const reqdescs = idsToNames(pkglist);
1480                 pkgdesc = formatStrVec(reqdescs, _("or"));
1481                 if (!desc.empty())
1482                         desc += "\n";
1483                 desc += bformat(_("Module required: %1$s."), pkgdesc);
1484         }
1485
1486         pkglist = getExcludedList(modName);
1487         if (!pkglist.empty()) {
1488                 vector<string> const reqdescs = idsToNames(pkglist);
1489                 pkgdesc = formatStrVec(reqdescs, _( "and"));
1490                 if (!desc.empty())
1491                         desc += "\n";
1492                 desc += bformat(_("Modules excluded: %1$s."), pkgdesc);
1493         }
1494
1495         if (!isModuleAvailable(modName)) {
1496                 if (!desc.empty())
1497                         desc += "\n";
1498                 desc += _("WARNING: Some required packages are unavailable!");
1499         }
1500
1501         modulesModule->infoML->document()->setPlainText(toqstr(desc));
1502 }
1503
1504
1505 void GuiDocument::updateNumbering()
1506 {
1507         DocumentClass const & tclass = documentClass();
1508
1509         numberingModule->tocTW->setUpdatesEnabled(false);
1510         numberingModule->tocTW->clear();
1511
1512         int const depth = numberingModule->depthSL->value();
1513         int const toc = numberingModule->tocSL->value();
1514         QString const no = qt_("No");
1515         QString const yes = qt_("Yes");
1516         QTreeWidgetItem * item = 0;
1517
1518         DocumentClass::const_iterator lit = tclass.begin();
1519         DocumentClass::const_iterator len = tclass.end();
1520         for (; lit != len; ++lit) {
1521                 int const toclevel = lit->toclevel;
1522                 if (toclevel != Layout::NOT_IN_TOC && lit->labeltype == LABEL_COUNTER) {
1523                         item = new QTreeWidgetItem(numberingModule->tocTW);
1524                         item->setText(0, toqstr(translateIfPossible(lit->name())));
1525                         item->setText(1, (toclevel <= depth) ? yes : no);
1526                         item->setText(2, (toclevel <= toc) ? yes : no);
1527                 }
1528         }
1529
1530         numberingModule->tocTW->setUpdatesEnabled(true);
1531         numberingModule->tocTW->update();
1532 }
1533
1534
1535 void GuiDocument::applyView()
1536 {
1537         // preamble
1538         preambleModule->apply(bp_);
1539
1540         // biblio
1541         bp_.setCiteEngine(ENGINE_BASIC);
1542
1543         if (biblioModule->citeNatbibRB->isChecked()) {
1544                 bool const use_numerical_citations =
1545                         biblioModule->citeStyleCO->currentIndex();
1546                 if (use_numerical_citations)
1547                         bp_.setCiteEngine(ENGINE_NATBIB_NUMERICAL);
1548                 else
1549                         bp_.setCiteEngine(ENGINE_NATBIB_AUTHORYEAR);
1550
1551         } else if (biblioModule->citeJurabibRB->isChecked())
1552                 bp_.setCiteEngine(ENGINE_JURABIB);
1553
1554         bp_.use_bibtopic =
1555                 biblioModule->bibtopicCB->isChecked();
1556
1557         // language & quotes
1558         if (langModule->defaultencodingRB->isChecked()) {
1559                 bp_.inputenc = "auto";
1560         } else {
1561                 int i = langModule->encodingCO->currentIndex();
1562                 if (i == 0)
1563                         bp_.inputenc = "default";
1564                 else {
1565                         QString const enc_gui =
1566                                 langModule->encodingCO->currentText();
1567                         Encodings::const_iterator it = encodings.begin();
1568                         Encodings::const_iterator const end = encodings.end();
1569                         bool found = false;
1570                         for (; it != end; ++it) {
1571                                 if (qt_(it->guiName()) == enc_gui) {
1572                                         bp_.inputenc = it->latexName();
1573                                         found = true;
1574                                         break;
1575                                 }
1576                         }
1577                         if (!found) {
1578                                 // should not happen
1579                                 lyxerr << "GuiDocument::apply: Unknown encoding! Resetting to default" << endl;
1580                                 bp_.inputenc = "default";
1581                         }
1582                 }
1583         }
1584
1585         InsetQuotes::QuoteLanguage lga = InsetQuotes::EnglishQuotes;
1586         switch (langModule->quoteStyleCO->currentIndex()) {
1587         case 0:
1588                 lga = InsetQuotes::EnglishQuotes;
1589                 break;
1590         case 1:
1591                 lga = InsetQuotes::SwedishQuotes;
1592                 break;
1593         case 2:
1594                 lga = InsetQuotes::GermanQuotes;
1595                 break;
1596         case 3:
1597                 lga = InsetQuotes::PolishQuotes;
1598                 break;
1599         case 4:
1600                 lga = InsetQuotes::FrenchQuotes;
1601                 break;
1602         case 5:
1603                 lga = InsetQuotes::DanishQuotes;
1604                 break;
1605         }
1606         bp_.quotes_language = lga;
1607
1608         QString const lang = langModule->languageCO->itemData(
1609                 langModule->languageCO->currentIndex()).toString();
1610         bp_.language = lyx::languages.getLanguage(fromqstr(lang));
1611
1612         // numbering
1613         if (bp_.documentClass().hasTocLevels()) {
1614                 bp_.tocdepth = numberingModule->tocSL->value();
1615                 bp_.secnumdepth = numberingModule->depthSL->value();
1616         }
1617
1618         // bullets
1619         bp_.user_defined_bullet(0) = bulletsModule->bullet(0);
1620         bp_.user_defined_bullet(1) = bulletsModule->bullet(1);
1621         bp_.user_defined_bullet(2) = bulletsModule->bullet(2);
1622         bp_.user_defined_bullet(3) = bulletsModule->bullet(3);
1623
1624         // packages
1625         bp_.graphicsDriver =
1626                 tex_graphics[latexModule->psdriverCO->currentIndex()];
1627         
1628         // text layout
1629         int idx = latexModule->classCO->currentIndex();
1630         if (idx >= 0) {
1631                 string const classname = classes_model_.getIDString(idx);
1632                 bp_.setBaseClass(classname);
1633         }
1634
1635         // Modules
1636         modulesToParams(bp_);
1637
1638         if (mathsModule->amsautoCB->isChecked()) {
1639                 bp_.use_amsmath = BufferParams::package_auto;
1640         } else {
1641                 if (mathsModule->amsCB->isChecked())
1642                         bp_.use_amsmath = BufferParams::package_on;
1643                 else
1644                         bp_.use_amsmath = BufferParams::package_off;
1645         }
1646
1647         if (mathsModule->esintautoCB->isChecked())
1648                 bp_.use_esint = BufferParams::package_auto;
1649         else {
1650                 if (mathsModule->esintCB->isChecked())
1651                         bp_.use_esint = BufferParams::package_on;
1652                 else
1653                         bp_.use_esint = BufferParams::package_off;
1654         }
1655
1656         if (pageLayoutModule->pagestyleCO->currentIndex() == 0)
1657                 bp_.pagestyle = "default";
1658         else {
1659                 QString style_gui = pageLayoutModule->pagestyleCO->currentText();
1660                 for (size_t i = 0; i != pagestyles.size(); ++i)
1661                         if (pagestyles[i].second == style_gui)
1662                                 bp_.pagestyle = pagestyles[i].first;
1663         }
1664
1665         switch (textLayoutModule->lspacingCO->currentIndex()) {
1666         case 0:
1667                 bp_.spacing().set(Spacing::Single);
1668                 break;
1669         case 1:
1670                 bp_.spacing().set(Spacing::Onehalf);
1671                 break;
1672         case 2:
1673                 bp_.spacing().set(Spacing::Double);
1674                 break;
1675         case 3:
1676                 bp_.spacing().set(Spacing::Other,
1677                         fromqstr(textLayoutModule->lspacingLE->text()));
1678                 break;
1679         }
1680
1681         if (textLayoutModule->twoColumnCB->isChecked())
1682                 bp_.columns = 2;
1683         else
1684                 bp_.columns = 1;
1685
1686         // text should have passed validation
1687         bp_.listings_params =
1688                 InsetListingsParams(fromqstr(textLayoutModule->listingsED->toPlainText())).params();
1689
1690         if (textLayoutModule->indentRB->isChecked())
1691                 bp_.paragraph_separation = BufferParams::ParagraphIndentSeparation;
1692         else
1693                 bp_.paragraph_separation = BufferParams::ParagraphSkipSeparation;
1694
1695         switch (textLayoutModule->skipCO->currentIndex()) {
1696         case 0:
1697                 bp_.setDefSkip(VSpace(VSpace::SMALLSKIP));
1698                 break;
1699         case 1:
1700                 bp_.setDefSkip(VSpace(VSpace::MEDSKIP));
1701                 break;
1702         case 2:
1703                 bp_.setDefSkip(VSpace(VSpace::BIGSKIP));
1704                 break;
1705         case 3:
1706         {
1707                 VSpace vs = VSpace(
1708                         widgetsToLength(textLayoutModule->skipLE,
1709                                 textLayoutModule->skipLengthCO)
1710                         );
1711                 bp_.setDefSkip(vs);
1712                 break;
1713         }
1714         default:
1715                 // DocumentDefskipCB assures that this never happens
1716                 // so Assert then !!!  - jbl
1717                 bp_.setDefSkip(VSpace(VSpace::MEDSKIP));
1718                 break;
1719         }
1720
1721         bp_.options =
1722                 fromqstr(latexModule->optionsLE->text());
1723
1724         bp_.use_default_options =
1725                 latexModule->defaultOptionsCB->isChecked();
1726
1727         if (latexModule->childDocGB->isChecked())
1728                 bp_.master =
1729                         fromqstr(latexModule->childDocLE->text());
1730         else
1731                 bp_.master = string();
1732
1733         bp_.float_placement = floatModule->get();
1734
1735         // fonts
1736         bp_.fontsRoman =
1737                 tex_fonts_roman[fontModule->fontsRomanCO->currentIndex()];
1738
1739         bp_.fontsSans =
1740                 tex_fonts_sans[fontModule->fontsSansCO->currentIndex()];
1741
1742         bp_.fontsTypewriter =
1743                 tex_fonts_monospaced[fontModule->fontsTypewriterCO->currentIndex()];
1744
1745         bp_.fontsCJK =
1746                 fromqstr(fontModule->cjkFontLE->text());
1747
1748         bp_.fontsSansScale = fontModule->scaleSansSB->value();
1749
1750         bp_.fontsTypewriterScale = fontModule->scaleTypewriterSB->value();
1751
1752         bp_.fontsSC = fontModule->fontScCB->isChecked();
1753
1754         bp_.fontsOSF = fontModule->fontOsfCB->isChecked();
1755
1756         bp_.fontsDefaultFamily = GuiDocument::fontfamilies[
1757                 fontModule->fontsDefaultCO->currentIndex()];
1758
1759         if (fontModule->fontsizeCO->currentIndex() == 0)
1760                 bp_.fontsize = "default";
1761         else
1762                 bp_.fontsize =
1763                         fromqstr(fontModule->fontsizeCO->currentText());
1764
1765         // paper
1766         bp_.papersize = PAPER_SIZE(
1767                 pageLayoutModule->papersizeCO->currentIndex());
1768
1769         // custom, A3, B3 and B4 paper sizes need geometry
1770         int psize = pageLayoutModule->papersizeCO->currentIndex();
1771         bool geom_papersize = (psize == 1 || psize == 5 || psize == 8 || psize == 9);
1772
1773         bp_.paperwidth = widgetsToLength(pageLayoutModule->paperwidthLE,
1774                 pageLayoutModule->paperwidthUnitCO);
1775
1776         bp_.paperheight = widgetsToLength(pageLayoutModule->paperheightLE,
1777                 pageLayoutModule->paperheightUnitCO);
1778
1779         if (pageLayoutModule->facingPagesCB->isChecked())
1780                 bp_.sides = TwoSides;
1781         else
1782                 bp_.sides = OneSide;
1783
1784         if (pageLayoutModule->landscapeRB->isChecked())
1785                 bp_.orientation = ORIENTATION_LANDSCAPE;
1786         else
1787                 bp_.orientation = ORIENTATION_PORTRAIT;
1788
1789         // margins
1790         bp_.use_geometry = !marginsModule->marginCB->isChecked()
1791                 || geom_papersize;
1792
1793         Ui::MarginsUi const * m = marginsModule;
1794
1795         bp_.leftmargin = widgetsToLength(m->innerLE, m->innerUnit);
1796         bp_.topmargin = widgetsToLength(m->topLE, m->topUnit);
1797         bp_.rightmargin = widgetsToLength(m->outerLE, m->outerUnit);
1798         bp_.bottommargin = widgetsToLength(m->bottomLE, m->bottomUnit);
1799         bp_.headheight = widgetsToLength(m->headheightLE, m->headheightUnit);
1800         bp_.headsep = widgetsToLength(m->headsepLE, m->headsepUnit);
1801         bp_.footskip = widgetsToLength(m->footskipLE, m->footskipUnit);
1802         bp_.columnsep = widgetsToLength(m->columnsepLE, m->columnsepUnit);
1803
1804         branchesModule->apply(bp_);
1805
1806         // PDF support
1807         PDFOptions & pdf = bp_.pdfoptions();
1808         pdf.use_hyperref = pdfSupportModule->use_hyperrefGB->isChecked();
1809         pdf.title = fromqstr(pdfSupportModule->titleLE->text());
1810         pdf.author = fromqstr(pdfSupportModule->authorLE->text());
1811         pdf.subject = fromqstr(pdfSupportModule->subjectLE->text());
1812         pdf.keywords = fromqstr(pdfSupportModule->keywordsLE->text());
1813
1814         pdf.bookmarks = pdfSupportModule->bookmarksGB->isChecked();
1815         pdf.bookmarksnumbered = pdfSupportModule->bookmarksnumberedCB->isChecked();
1816         pdf.bookmarksopen = pdfSupportModule->bookmarksopenGB->isChecked();
1817         pdf.bookmarksopenlevel = pdfSupportModule->bookmarksopenlevelSB->value();
1818
1819         pdf.breaklinks = pdfSupportModule->breaklinksCB->isChecked();
1820         pdf.pdfborder = pdfSupportModule->pdfborderCB->isChecked();
1821         pdf.pdfusetitle = pdfSupportModule->pdfusetitleCB->isChecked();
1822         pdf.colorlinks = pdfSupportModule->colorlinksCB->isChecked();
1823         pdf.backref =
1824                 backref_opts[pdfSupportModule->backrefCO->currentIndex()];
1825         if (pdfSupportModule->fullscreenCB->isChecked())
1826                 pdf.pagemode = pdf.pagemode_fullscreen;
1827         else
1828                 pdf.pagemode.clear();
1829         pdf.quoted_options = pdf.quoted_options_check(
1830                                 fromqstr(pdfSupportModule->optionsLE->text()));
1831 }
1832
1833
1834 void GuiDocument::paramsToDialog()
1835 {
1836         // set the default unit
1837         Length::UNIT const defaultUnit = Length::defaultUnit();
1838
1839         // preamble
1840         preambleModule->update(bp_, id());
1841
1842         // biblio
1843         biblioModule->citeDefaultRB->setChecked(
1844                 bp_.citeEngine() == ENGINE_BASIC);
1845
1846         biblioModule->citeNatbibRB->setChecked(
1847                 bp_.citeEngine() == ENGINE_NATBIB_NUMERICAL ||
1848                 bp_.citeEngine() == ENGINE_NATBIB_AUTHORYEAR);
1849
1850         biblioModule->citeStyleCO->setCurrentIndex(
1851                 bp_.citeEngine() == ENGINE_NATBIB_NUMERICAL);
1852
1853         biblioModule->citeJurabibRB->setChecked(
1854                 bp_.citeEngine() == ENGINE_JURABIB);
1855
1856         biblioModule->bibtopicCB->setChecked(
1857                 bp_.use_bibtopic);
1858
1859         // language & quotes
1860         int const pos = langModule->languageCO->findData(toqstr(
1861                 bp_.language->lang()));
1862         langModule->languageCO->setCurrentIndex(pos);
1863
1864         langModule->quoteStyleCO->setCurrentIndex(
1865                 bp_.quotes_language);
1866
1867         bool default_enc = true;
1868         if (bp_.inputenc != "auto") {
1869                 default_enc = false;
1870                 if (bp_.inputenc == "default") {
1871                         langModule->encodingCO->setCurrentIndex(0);
1872                 } else {
1873                         string enc_gui;
1874                         Encodings::const_iterator it = encodings.begin();
1875                         Encodings::const_iterator const end = encodings.end();
1876                         for (; it != end; ++it) {
1877                                 if (it->latexName() == bp_.inputenc) {
1878                                         enc_gui = it->guiName();
1879                                         break;
1880                                 }
1881                         }
1882                         int const i = langModule->encodingCO->findText(
1883                                         qt_(enc_gui));
1884                         if (i >= 0)
1885                                 langModule->encodingCO->setCurrentIndex(i);
1886                         else
1887                                 // unknown encoding. Set to default.
1888                                 default_enc = true;
1889                 }
1890         }
1891         langModule->defaultencodingRB->setChecked(default_enc);
1892         langModule->otherencodingRB->setChecked(!default_enc);
1893
1894         // numbering
1895         int const min_toclevel = documentClass().min_toclevel();
1896         int const max_toclevel = documentClass().max_toclevel();
1897         if (documentClass().hasTocLevels()) {
1898                 numberingModule->setEnabled(true);
1899                 numberingModule->depthSL->setMinimum(min_toclevel - 1);
1900                 numberingModule->depthSL->setMaximum(max_toclevel);
1901                 numberingModule->depthSL->setValue(bp_.secnumdepth);
1902                 numberingModule->tocSL->setMaximum(min_toclevel - 1);
1903                 numberingModule->tocSL->setMaximum(max_toclevel);
1904                 numberingModule->tocSL->setValue(bp_.tocdepth);
1905                 updateNumbering();
1906         } else {
1907                 numberingModule->setEnabled(false);
1908                 numberingModule->tocTW->clear();
1909         }
1910
1911         // bullets
1912         bulletsModule->setBullet(0, bp_.user_defined_bullet(0));
1913         bulletsModule->setBullet(1, bp_.user_defined_bullet(1));
1914         bulletsModule->setBullet(2, bp_.user_defined_bullet(2));
1915         bulletsModule->setBullet(3, bp_.user_defined_bullet(3));
1916         bulletsModule->init();
1917
1918         // packages
1919         int nitem = findToken(tex_graphics, bp_.graphicsDriver);
1920         if (nitem >= 0)
1921                 latexModule->psdriverCO->setCurrentIndex(nitem);
1922         updateModuleInfo();
1923         
1924         mathsModule->amsCB->setChecked(
1925                 bp_.use_amsmath == BufferParams::package_on);
1926         mathsModule->amsautoCB->setChecked(
1927                 bp_.use_amsmath == BufferParams::package_auto);
1928
1929         mathsModule->esintCB->setChecked(
1930                 bp_.use_esint == BufferParams::package_on);
1931         mathsModule->esintautoCB->setChecked(
1932                 bp_.use_esint == BufferParams::package_auto);
1933
1934         switch (bp_.spacing().getSpace()) {
1935                 case Spacing::Other: nitem = 3; break;
1936                 case Spacing::Double: nitem = 2; break;
1937                 case Spacing::Onehalf: nitem = 1; break;
1938                 case Spacing::Default: case Spacing::Single: nitem = 0; break;
1939         }
1940
1941         // text layout
1942         string const & layoutID = bp_.baseClassID();
1943         setLayoutComboByIDString(layoutID);
1944
1945         updatePagestyle(documentClass().opt_pagestyle(),
1946                                  bp_.pagestyle);
1947
1948         textLayoutModule->lspacingCO->setCurrentIndex(nitem);
1949         if (bp_.spacing().getSpace() == Spacing::Other) {
1950                 textLayoutModule->lspacingLE->setText(
1951                         toqstr(bp_.spacing().getValueAsString()));
1952         }
1953         setLSpacing(nitem);
1954
1955         if (bp_.paragraph_separation == BufferParams::ParagraphIndentSeparation)
1956                 textLayoutModule->indentRB->setChecked(true);
1957         else
1958                 textLayoutModule->skipRB->setChecked(true);
1959
1960         int skip = 0;
1961         switch (bp_.getDefSkip().kind()) {
1962         case VSpace::SMALLSKIP:
1963                 skip = 0;
1964                 break;
1965         case VSpace::MEDSKIP:
1966                 skip = 1;
1967                 break;
1968         case VSpace::BIGSKIP:
1969                 skip = 2;
1970                 break;
1971         case VSpace::LENGTH:
1972         {
1973                 skip = 3;
1974                 string const length = bp_.getDefSkip().asLyXCommand();
1975                 lengthToWidgets(textLayoutModule->skipLE,
1976                         textLayoutModule->skipLengthCO,
1977                         length, defaultUnit);
1978                 break;
1979         }
1980         default:
1981                 skip = 0;
1982                 break;
1983         }
1984         textLayoutModule->skipCO->setCurrentIndex(skip);
1985         setSkip(skip);
1986
1987         textLayoutModule->twoColumnCB->setChecked(
1988                 bp_.columns == 2);
1989
1990         // break listings_params to multiple lines
1991         string lstparams =
1992                 InsetListingsParams(bp_.listings_params).separatedParams();
1993         textLayoutModule->listingsED->setPlainText(toqstr(lstparams));
1994
1995         if (!bp_.options.empty()) {
1996                 latexModule->optionsLE->setText(
1997                         toqstr(bp_.options));
1998         } else {
1999                 latexModule->optionsLE->setText(QString());
2000         }
2001
2002         // latex
2003         latexModule->defaultOptionsCB->setChecked(
2004                         bp_.use_default_options);
2005         updateSelectedModules();
2006         selectionManager->updateProvidedModules(
2007                         bp_.baseClass()->providedModules());
2008         selectionManager->updateExcludedModules(
2009                         bp_.baseClass()->excludedModules());
2010
2011         if (!documentClass().options().empty()) {
2012                 latexModule->defaultOptionsLE->setText(
2013                         toqstr(documentClass().options()));
2014         } else {
2015                 latexModule->defaultOptionsLE->setText(
2016                         toqstr(_("[No options predefined]")));
2017         }
2018
2019         latexModule->defaultOptionsLE->setEnabled(
2020                 bp_.use_default_options
2021                 && !documentClass().options().empty());
2022
2023         latexModule->defaultOptionsCB->setEnabled(
2024                 !documentClass().options().empty());
2025
2026         if (!bp_.master.empty()) {
2027                 latexModule->childDocGB->setChecked(true);
2028                 latexModule->childDocLE->setText(
2029                         toqstr(bp_.master));
2030         } else {
2031                 latexModule->childDocLE->setText(QString());
2032                 latexModule->childDocGB->setChecked(false);
2033         }
2034
2035         floatModule->set(bp_.float_placement);
2036
2037         // Fonts
2038         updateFontsize(documentClass().opt_fontsize(),
2039                         bp_.fontsize);
2040
2041         int n = findToken(tex_fonts_roman, bp_.fontsRoman);
2042         if (n >= 0) {
2043                 fontModule->fontsRomanCO->setCurrentIndex(n);
2044                 romanChanged(n);
2045         }
2046
2047         n = findToken(tex_fonts_sans, bp_.fontsSans);
2048         if (n >= 0)     {
2049                 fontModule->fontsSansCO->setCurrentIndex(n);
2050                 sansChanged(n);
2051         }
2052
2053         n = findToken(tex_fonts_monospaced, bp_.fontsTypewriter);
2054         if (n >= 0) {
2055                 fontModule->fontsTypewriterCO->setCurrentIndex(n);
2056                 ttChanged(n);
2057         }
2058
2059         if (!bp_.fontsCJK.empty())
2060                 fontModule->cjkFontLE->setText(
2061                         toqstr(bp_.fontsCJK));
2062         else
2063                 fontModule->cjkFontLE->setText(QString());
2064
2065         fontModule->fontScCB->setChecked(bp_.fontsSC);
2066         fontModule->fontOsfCB->setChecked(bp_.fontsOSF);
2067         fontModule->scaleSansSB->setValue(bp_.fontsSansScale);
2068         fontModule->scaleTypewriterSB->setValue(bp_.fontsTypewriterScale);
2069         n = findToken(GuiDocument::fontfamilies, bp_.fontsDefaultFamily);
2070         if (n >= 0)
2071                 fontModule->fontsDefaultCO->setCurrentIndex(n);
2072
2073         // paper
2074         int const psize = bp_.papersize;
2075         pageLayoutModule->papersizeCO->setCurrentIndex(psize);
2076         setCustomPapersize(psize);
2077
2078         bool const landscape =
2079                 bp_.orientation == ORIENTATION_LANDSCAPE;
2080         pageLayoutModule->landscapeRB->setChecked(landscape);
2081         pageLayoutModule->portraitRB->setChecked(!landscape);
2082
2083         pageLayoutModule->facingPagesCB->setChecked(
2084                 bp_.sides == TwoSides);
2085
2086
2087         lengthToWidgets(pageLayoutModule->paperwidthLE,
2088                 pageLayoutModule->paperwidthUnitCO, bp_.paperwidth, defaultUnit);
2089
2090         lengthToWidgets(pageLayoutModule->paperheightLE,
2091                 pageLayoutModule->paperheightUnitCO, bp_.paperheight, defaultUnit);
2092
2093         // margins
2094         Ui::MarginsUi * m = marginsModule;
2095
2096         setMargins(!bp_.use_geometry);
2097
2098         lengthToWidgets(m->topLE, m->topUnit,
2099                 bp_.topmargin, defaultUnit);
2100
2101         lengthToWidgets(m->bottomLE, m->bottomUnit,
2102                 bp_.bottommargin, defaultUnit);
2103
2104         lengthToWidgets(m->innerLE, m->innerUnit,
2105                 bp_.leftmargin, defaultUnit);
2106
2107         lengthToWidgets(m->outerLE, m->outerUnit,
2108                 bp_.rightmargin, defaultUnit);
2109
2110         lengthToWidgets(m->headheightLE, m->headheightUnit,
2111                 bp_.headheight, defaultUnit);
2112
2113         lengthToWidgets(m->headsepLE, m->headsepUnit,
2114                 bp_.headsep, defaultUnit);
2115
2116         lengthToWidgets(m->footskipLE, m->footskipUnit,
2117                 bp_.footskip, defaultUnit);
2118
2119         lengthToWidgets(m->columnsepLE, m->columnsepUnit,
2120                 bp_.columnsep, defaultUnit);
2121
2122         branchesModule->update(bp_);
2123
2124         // PDF support
2125         PDFOptions const & pdf = bp_.pdfoptions();
2126         pdfSupportModule->use_hyperrefGB->setChecked(pdf.use_hyperref);
2127         pdfSupportModule->titleLE->setText(toqstr(pdf.title));
2128         pdfSupportModule->authorLE->setText(toqstr(pdf.author));
2129         pdfSupportModule->subjectLE->setText(toqstr(pdf.subject));
2130         pdfSupportModule->keywordsLE->setText(toqstr(pdf.keywords));
2131
2132         pdfSupportModule->bookmarksGB->setChecked(pdf.bookmarks);
2133         pdfSupportModule->bookmarksnumberedCB->setChecked(pdf.bookmarksnumbered);
2134         pdfSupportModule->bookmarksopenGB->setChecked(pdf.bookmarksopen);
2135
2136         pdfSupportModule->bookmarksopenlevelSB->setValue(pdf.bookmarksopenlevel);
2137
2138         pdfSupportModule->breaklinksCB->setChecked(pdf.breaklinks);
2139         pdfSupportModule->pdfborderCB->setChecked(pdf.pdfborder);
2140         pdfSupportModule->pdfusetitleCB->setChecked(pdf.pdfusetitle);
2141         pdfSupportModule->colorlinksCB->setChecked(pdf.colorlinks);
2142
2143         n = findToken(backref_opts, pdf.backref);
2144         if (n >= 0)
2145                 pdfSupportModule->backrefCO->setCurrentIndex(n);
2146
2147         pdfSupportModule->fullscreenCB->setChecked
2148                 (pdf.pagemode == pdf.pagemode_fullscreen);
2149
2150         pdfSupportModule->optionsLE->setText(
2151                 toqstr(pdf.quoted_options));
2152
2153         // Make sure that the bc is in the INITIAL state
2154         if (bc().policy().buttonStatus(ButtonPolicy::RESTORE))
2155                 bc().restore();
2156 }
2157
2158
2159 void GuiDocument::saveDocDefault()
2160 {
2161         // we have to apply the params first
2162         applyView();
2163         saveAsDefault();
2164 }
2165
2166
2167 void GuiDocument::updateAvailableModules() 
2168 {
2169         modules_av_model_.clear();
2170         list<modInfoStruct> const & modInfoList = getModuleInfo();
2171         list<modInfoStruct>::const_iterator mit = modInfoList.begin();
2172         list<modInfoStruct>::const_iterator men = modInfoList.end();
2173         for (int i = 0; mit != men; ++mit, ++i)
2174                 modules_av_model_.insertRow(i, mit->name, mit->id, 
2175                                 mit->description);
2176 }
2177
2178
2179 void GuiDocument::updateSelectedModules() 
2180 {
2181         modules_sel_model_.clear();
2182         list<modInfoStruct> const selModList = getSelectedModules();
2183         list<modInfoStruct>::const_iterator mit = selModList.begin();
2184         list<modInfoStruct>::const_iterator men = selModList.end();
2185         for (int i = 0; mit != men; ++mit, ++i)
2186                 modules_sel_model_.insertRow(i, mit->name, mit->id, 
2187                                 mit->description);
2188 }
2189
2190
2191 void GuiDocument::updateContents()
2192 {
2193         // Nothing to do here as the document settings is not cursor dependant.
2194         return;
2195 }
2196
2197
2198 void GuiDocument::useClassDefaults()
2199 {
2200         if (applyPB->isEnabled()) {
2201                 int const ret = Alert::prompt(_("Unapplied changes"),
2202                                 _("Some changes in the dialog were not yet applied.\n"
2203                                   "If you do not apply now, they will be lost after this action."),
2204                                 1, 1, _("&Apply"), _("&Dismiss"));
2205                 if (ret == 0)
2206                         applyView();
2207         }
2208
2209         int idx = latexModule->classCO->currentIndex();
2210         string const classname = classes_model_.getIDString(idx);
2211         if (!bp_.setBaseClass(classname)) {
2212                 Alert::error(_("Error"), _("Unable to set document class."));
2213                 return;
2214         }
2215         bp_.useClassDefaults();
2216         paramsToDialog();
2217 }
2218
2219
2220 void GuiDocument::setLayoutComboByIDString(string const & idString)
2221 {
2222         int idx = classes_model_.findIDString(idString);
2223         if (idx < 0)
2224                 Alert::warning(_("Can't set layout!"), 
2225                         bformat(_("Unable to set layout for ID: %1$s"), from_utf8(idString)));
2226         else 
2227                 latexModule->classCO->setCurrentIndex(idx);
2228 }
2229
2230
2231 bool GuiDocument::isValid()
2232 {
2233         return validateListingsParameters().isEmpty()
2234                 && (textLayoutModule->skipCO->currentIndex() != 3
2235                         || !textLayoutModule->skipLE->text().isEmpty());
2236 }
2237
2238
2239 char const * const GuiDocument::fontfamilies[5] = {
2240         "default", "rmdefault", "sfdefault", "ttdefault", ""
2241 };
2242
2243
2244 char const * GuiDocument::fontfamilies_gui[5] = {
2245         N_("Default"), N_("Roman"), N_("Sans Serif"), N_("Typewriter"), ""
2246 };
2247
2248
2249 bool GuiDocument::initialiseParams(string const &)
2250 {
2251         BufferView const * view = bufferview();
2252         if (!view) {
2253                 bp_ = BufferParams();
2254                 paramsToDialog();
2255                 return true;
2256         }
2257         bp_ = view->buffer().params();
2258         loadModuleInfo();
2259         updateAvailableModules();
2260         //FIXME It'd be nice to make sure here that the selected
2261         //modules are consistent: That required modules are actually
2262         //selected, and that we don't have conflicts. If so, we could
2263         //at least pop up a warning.
2264         paramsToDialog();
2265         return true;
2266 }
2267
2268
2269 void GuiDocument::clearParams()
2270 {
2271         bp_ = BufferParams();
2272 }
2273
2274
2275 BufferId GuiDocument::id() const
2276 {
2277         BufferView const * const view = bufferview();
2278         return view? &view->buffer() : 0;
2279 }
2280
2281
2282 list<GuiDocument::modInfoStruct> const & GuiDocument::getModuleInfo()
2283 {
2284         return moduleNames_;
2285 }
2286
2287
2288 list<GuiDocument::modInfoStruct> const 
2289                 GuiDocument::makeModuleInfo(LayoutModuleList const & mods)
2290 {
2291         LayoutModuleList::const_iterator it =  mods.begin();
2292         LayoutModuleList::const_iterator end = mods.end();
2293         list<modInfoStruct> mInfo;
2294         for (; it != end; ++it) {
2295                 modInfoStruct m;
2296                 m.id = *it;
2297                 LyXModule * mod = moduleList[*it];
2298                 if (mod)
2299                         // FIXME Unicode
2300                         m.name = toqstr(translateIfPossible(from_utf8(mod->getName())));
2301                 else 
2302                         m.name = toqstr(*it) + toqstr(" (") + qt_("Not Found") + toqstr(")");
2303                 mInfo.push_back(m);
2304         }
2305         return mInfo;
2306 }
2307
2308
2309 list<GuiDocument::modInfoStruct> const GuiDocument::getSelectedModules()
2310 {
2311         return makeModuleInfo(params().getModules());
2312 }
2313
2314
2315 list<GuiDocument::modInfoStruct> const GuiDocument::getProvidedModules()
2316 {
2317         return makeModuleInfo(params().baseClass()->providedModules());
2318 }
2319
2320
2321 DocumentClass const & GuiDocument::documentClass() const
2322 {
2323         return bp_.documentClass();
2324 }
2325
2326
2327 static void dispatch_bufferparams(Dialog const & dialog,
2328         BufferParams const & bp, FuncCode lfun)
2329 {
2330         ostringstream ss;
2331         ss << "\\begin_header\n";
2332         bp.writeFile(ss);
2333         ss << "\\end_header\n";
2334         dialog.dispatch(FuncRequest(lfun, ss.str()));
2335 }
2336
2337
2338 void GuiDocument::dispatchParams()
2339 {
2340         // This must come first so that a language change is correctly noticed
2341         setLanguage();
2342
2343         // Apply the BufferParams. Note that this will set the base class
2344         // and then update the buffer's layout.
2345         dispatch_bufferparams(*this, params(), LFUN_BUFFER_PARAMS_APPLY);
2346
2347         if (!params().master.empty()) {
2348                 FileName const master_file = support::makeAbsPath(params().master,
2349                            support::onlyPath(buffer().absFileName()));
2350                 if (isLyXFilename(master_file.absFilename())) {
2351                         Buffer * master = checkAndLoadLyXFile(master_file);
2352                         if (master) {
2353                                 if (master->isChild(const_cast<Buffer *>(&buffer())))
2354                                         const_cast<Buffer &>(buffer()).setParent(master);
2355                                 else
2356                                         Alert::warning(_("Assigned master does not include this file"), 
2357                                                 bformat(_("You must include this file in the document\n"
2358                                                           "'%1$s' in order to use the master document\n"
2359                                                           "feature."), from_utf8(params().master)));
2360                         } else
2361                                 Alert::warning(_("Could not load master"), 
2362                                                 bformat(_("The master document '%1$s'\n"
2363                                                            "could not be loaded."),
2364                                                            from_utf8(params().master)));
2365                 }
2366         }
2367
2368         // Generate the colours requested by each new branch.
2369         BranchList & branchlist = params().branchlist();
2370         if (!branchlist.empty()) {
2371                 BranchList::const_iterator it = branchlist.begin();
2372                 BranchList::const_iterator const end = branchlist.end();
2373                 for (; it != end; ++it) {
2374                         docstring const & current_branch = it->branch();
2375                         Branch const * branch = branchlist.find(current_branch);
2376                         string const x11hexname = X11hexname(branch->color());
2377                         // display the new color
2378                         docstring const str = current_branch + ' ' + from_ascii(x11hexname);
2379                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
2380                 }
2381
2382                 // Open insets of selected branches, close deselected ones
2383                 dispatch(FuncRequest(LFUN_ALL_INSETS_TOGGLE,
2384                         "assign branch"));
2385         }
2386         // FIXME: If we used an LFUN, we would not need those two lines:
2387         BufferView * bv = const_cast<BufferView *>(bufferview());
2388         bv->processUpdateFlags(Update::Force | Update::FitCursor);
2389 }
2390
2391
2392 void GuiDocument::setLanguage() const
2393 {
2394         Language const * const newL = bp_.language;
2395         if (buffer().params().language == newL)
2396                 return;
2397
2398         string const & lang_name = newL->lang();
2399         dispatch(FuncRequest(LFUN_BUFFER_LANGUAGE, lang_name));
2400 }
2401
2402
2403 void GuiDocument::saveAsDefault() const
2404 {
2405         dispatch_bufferparams(*this, params(), LFUN_BUFFER_SAVE_AS_DEFAULT);
2406 }
2407
2408
2409 bool GuiDocument::isFontAvailable(string const & font) const
2410 {
2411         if (font == "default" || font == "cmr"
2412             || font == "cmss" || font == "cmtt")
2413                 // these are standard
2414                 return true;
2415         if (font == "lmodern" || font == "lmss" || font == "lmtt")
2416                 return LaTeXFeatures::isAvailable("lmodern");
2417         if (font == "times" || font == "palatino"
2418                  || font == "helvet" || font == "courier")
2419                 return LaTeXFeatures::isAvailable("psnfss");
2420         if (font == "cmbr" || font == "cmtl")
2421                 return LaTeXFeatures::isAvailable("cmbright");
2422         if (font == "utopia")
2423                 return LaTeXFeatures::isAvailable("utopia")
2424                         || LaTeXFeatures::isAvailable("fourier");
2425         if (font == "beraserif" || font == "berasans"
2426                 || font == "beramono")
2427                 return LaTeXFeatures::isAvailable("bera");
2428         return LaTeXFeatures::isAvailable(font);
2429 }
2430
2431
2432 bool GuiDocument::providesOSF(string const & font) const
2433 {
2434         if (font == "cmr")
2435                 return isFontAvailable("eco");
2436         if (font == "palatino")
2437                 return isFontAvailable("mathpazo");
2438         return false;
2439 }
2440
2441
2442 bool GuiDocument::providesSC(string const & font) const
2443 {
2444         if (font == "palatino")
2445                 return isFontAvailable("mathpazo");
2446         if (font == "utopia")
2447                 return isFontAvailable("fourier");
2448         return false;
2449 }
2450
2451
2452 bool GuiDocument::providesScale(string const & font) const
2453 {
2454         return font == "helvet" || font == "luximono"
2455                 || font == "berasans"  || font == "beramono";
2456 }
2457
2458
2459 void GuiDocument::loadModuleInfo()
2460 {
2461         moduleNames_.clear();
2462         LyXModuleList::const_iterator it  = moduleList.begin();
2463         LyXModuleList::const_iterator end = moduleList.end();
2464         for (; it != end; ++it) {
2465                 modInfoStruct m;
2466                 m.id = it->getID();
2467                 // FIXME Unicode
2468                 m.name = toqstr(translateIfPossible(from_utf8(it->getName())));
2469                 // this is supposed to give us the first sentence of the description
2470                 // FIXME Unicode
2471                 QString desc =
2472                         toqstr(translateIfPossible(from_utf8(it->getDescription())));
2473                 int const pos = desc.indexOf(".");
2474                 if (pos > 0)
2475                         desc.truncate(pos + 1);
2476                 m.description = desc;
2477                 moduleNames_.push_back(m);
2478         }
2479 }
2480
2481
2482 Dialog * createGuiDocument(GuiView & lv) { return new GuiDocument(lv); }
2483
2484
2485 } // namespace frontend
2486 } // namespace lyx
2487
2488 #include "moc_GuiDocument.cpp"