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