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