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