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