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