]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiDocument.cpp
This part of QTreeView is newer.
[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 = theModuleList[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 = theModuleList[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 = theModuleList[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 = theModuleList[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 const * const mod = theModuleList[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                 QTreeView * 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         connect(latexModule->suppressDateCB, SIGNAL(clicked()),
936                 this, SLOT(change_adaptor()));
937
938         // postscript drivers
939         for (int n = 0; tex_graphics[n][0]; ++n) {
940                 QString enc = qt_(tex_graphics_gui[n]);
941                 latexModule->psdriverCO->addItem(enc);
942         }
943         // latex classes
944         latexModule->classCO->setModel(&classes_model_);
945         LayoutFileList const & bcl = LayoutFileList::get();
946         vector<LayoutFileIndex> classList = bcl.classList();
947         sort(classList.begin(), classList.end(), less_textclass_avail_desc());
948
949         vector<LayoutFileIndex>::const_iterator cit  = classList.begin();
950         vector<LayoutFileIndex>::const_iterator cen = classList.end();
951         for (int i = 0; cit != cen; ++cit, ++i) {
952                 LayoutFile const & tc = bcl[*cit];
953                 docstring item = (tc.isTeXClassAvailable()) ?
954                         from_utf8(tc.description()) :
955                         bformat(_("Unavailable: %1$s"), from_utf8(tc.description()));
956                 classes_model_.insertRow(i, toqstr(item), *cit);
957         }
958
959         // branches
960         branchesModule = new GuiBranches;
961         connect(branchesModule, SIGNAL(changed()),
962                 this, SLOT(change_adaptor()));
963         connect(branchesModule, SIGNAL(renameBranches(docstring const &, docstring const &)),
964                 this, SLOT(branchesRename(docstring const &, docstring const &)));
965         updateUnknownBranches();
966
967         // preamble
968         preambleModule = new PreambleModule;
969         connect(preambleModule, SIGNAL(changed()),
970                 this, SLOT(change_adaptor()));
971
972         // bullets
973         bulletsModule = new BulletsModule;
974         connect(bulletsModule, SIGNAL(changed()),
975                 this, SLOT(change_adaptor()));
976
977         // Modules
978         modulesModule = new UiWidget<Ui::ModulesUi>;
979
980 #if (QT_VERSION >= 0x040400)
981         modulesModule->availableLV->setHeaderHidden(true);
982 #endif
983         selectionManager =
984                 new ModuleSelectionManager(modulesModule->availableLV,
985                         modulesModule->selectedLV,
986                         modulesModule->addPB, modulesModule->deletePB,
987                         modulesModule->upPB, modulesModule->downPB,
988                         availableModel(), selectedModel(), this);
989         connect(selectionManager, SIGNAL(updateHook()),
990                 this, SLOT(updateModuleInfo()));
991         connect(selectionManager, SIGNAL(updateHook()),
992                 this, SLOT(change_adaptor()));
993         connect(selectionManager, SIGNAL(selectionChanged()),
994                 this, SLOT(modulesChanged()));
995
996         // PDF support
997         pdfSupportModule = new UiWidget<Ui::PDFSupportUi>;
998
999         connect(pdfSupportModule->use_hyperrefGB, SIGNAL(toggled(bool)),
1000                 this, SLOT(change_adaptor()));
1001         connect(pdfSupportModule->titleLE, SIGNAL(textChanged(QString)),
1002                 this, SLOT(change_adaptor()));
1003         connect(pdfSupportModule->authorLE, SIGNAL(textChanged(QString)),
1004                 this, SLOT(change_adaptor()));
1005         connect(pdfSupportModule->subjectLE, SIGNAL(textChanged(QString)),
1006                 this, SLOT(change_adaptor()));
1007         connect(pdfSupportModule->keywordsLE, SIGNAL(textChanged(QString)),
1008                 this, SLOT(change_adaptor()));
1009         connect(pdfSupportModule->bookmarksGB, SIGNAL(toggled(bool)),
1010                 this, SLOT(change_adaptor()));
1011         connect(pdfSupportModule->bookmarksnumberedCB, SIGNAL(toggled(bool)),
1012                 this, SLOT(change_adaptor()));
1013         connect(pdfSupportModule->bookmarksopenGB, SIGNAL(toggled(bool)),
1014                 this, SLOT(change_adaptor()));
1015         connect(pdfSupportModule->bookmarksopenlevelSB, SIGNAL(valueChanged(int)),
1016                 this, SLOT(change_adaptor()));
1017         connect(pdfSupportModule->breaklinksCB, SIGNAL(toggled(bool)),
1018                 this, SLOT(change_adaptor()));
1019         connect(pdfSupportModule->pdfborderCB, SIGNAL(toggled(bool)),
1020                 this, SLOT(change_adaptor()));
1021         connect(pdfSupportModule->colorlinksCB, SIGNAL(toggled(bool)),
1022                 this, SLOT(change_adaptor()));
1023         connect(pdfSupportModule->backrefCO, SIGNAL(activated(int)),
1024                 this, SLOT(change_adaptor()));
1025         connect(pdfSupportModule->pdfusetitleCB, SIGNAL(toggled(bool)),
1026                 this, SLOT(change_adaptor()));
1027         connect(pdfSupportModule->fullscreenCB, SIGNAL(toggled(bool)),
1028                 this, SLOT(change_adaptor()));
1029         connect(pdfSupportModule->optionsLE, SIGNAL(textChanged(QString)),
1030                 this, SLOT(change_adaptor()));
1031
1032         for (int i = 0; backref_opts[i][0]; ++i)
1033                 pdfSupportModule->backrefCO->addItem(qt_(backref_opts_gui[i]));
1034
1035         // float
1036         floatModule = new FloatPlacement;
1037         connect(floatModule, SIGNAL(changed()),
1038                 this, SLOT(change_adaptor()));
1039
1040         // listings
1041         listingsModule = new UiWidget<Ui::ListingsSettingsUi>;
1042         connect(listingsModule->listingsED, SIGNAL(textChanged()),
1043                 this, SLOT(change_adaptor()));
1044         connect(listingsModule->bypassCB, SIGNAL(clicked()), 
1045                 this, SLOT(change_adaptor()));
1046         connect(listingsModule->bypassCB, SIGNAL(clicked()), 
1047                 this, SLOT(setListingsMessage()));
1048         connect(listingsModule->listingsED, SIGNAL(textChanged()),
1049                 this, SLOT(setListingsMessage()));
1050         listingsModule->listingsTB->setPlainText(
1051                 qt_("Input listings parameters below. Enter ? for a list of parameters."));
1052
1053         docPS->addPanel(latexModule, qt_("Document Class"));
1054         docPS->addPanel(modulesModule, qt_("Modules"));
1055         docPS->addPanel(fontModule, qt_("Fonts"));
1056         docPS->addPanel(textLayoutModule, qt_("Text Layout"));
1057         docPS->addPanel(pageLayoutModule, qt_("Page Layout"));
1058         docPS->addPanel(marginsModule, qt_("Page Margins"));
1059         docPS->addPanel(langModule, qt_("Language"));
1060         docPS->addPanel(numberingModule, qt_("Numbering & TOC"));
1061         docPS->addPanel(biblioModule, qt_("Bibliography"));
1062         docPS->addPanel(indicesModule, qt_("Indexes"));
1063         docPS->addPanel(pdfSupportModule, qt_("PDF Properties"));
1064         docPS->addPanel(mathsModule, qt_("Math Options"));
1065         docPS->addPanel(floatModule, qt_("Float Placement"));
1066         docPS->addPanel(listingsModule, qt_("Listings"));
1067         docPS->addPanel(bulletsModule, qt_("Bullets"));
1068         docPS->addPanel(branchesModule, qt_("Branches"));
1069         docPS->addPanel(outputModule, qt_("Output"));
1070         docPS->addPanel(preambleModule, qt_("LaTeX Preamble"));
1071         docPS->setCurrentPanel(qt_("Document Class"));
1072 // FIXME: hack to work around resizing bug in Qt >= 4.2
1073 // bug verified with Qt 4.2.{0-3} (JSpitzm)
1074 #if QT_VERSION >= 0x040200
1075         docPS->updateGeometry();
1076 #endif
1077 }
1078
1079
1080 void GuiDocument::showPreamble()
1081 {
1082         docPS->setCurrentPanel(qt_("LaTeX Preamble"));
1083 }
1084
1085
1086 void GuiDocument::saveDefaultClicked()
1087 {
1088         saveDocDefault();
1089 }
1090
1091
1092 void GuiDocument::useDefaultsClicked()
1093 {
1094         useClassDefaults();
1095 }
1096
1097
1098 void GuiDocument::change_adaptor()
1099 {
1100         changed();
1101 }
1102
1103
1104 QString GuiDocument::validateListingsParameters()
1105 {
1106         // use a cache here to avoid repeated validation
1107         // of the same parameters
1108         static string param_cache;
1109         static QString msg_cache;
1110         
1111         if (listingsModule->bypassCB->isChecked())
1112                 return QString();
1113
1114         string params = fromqstr(listingsModule->listingsED->toPlainText());
1115         if (params != param_cache) {
1116                 param_cache = params;
1117                 msg_cache = toqstr(InsetListingsParams(params).validate());
1118         }
1119         return msg_cache;
1120 }
1121
1122
1123 void GuiDocument::setListingsMessage()
1124 {
1125         static bool isOK = true;
1126         QString msg = validateListingsParameters();
1127         if (msg.isEmpty()) {
1128                 if (isOK)
1129                         return;
1130                 isOK = true;
1131                 // listingsTB->setTextColor("black");
1132                 listingsModule->listingsTB->setPlainText(
1133                         qt_("Input listings parameters below. "
1134                 "Enter ? for a list of parameters."));
1135         } else {
1136                 isOK = false;
1137                 // listingsTB->setTextColor("red");
1138                 listingsModule->listingsTB->setPlainText(msg);
1139         }
1140 }
1141
1142
1143 void GuiDocument::setLSpacing(int item)
1144 {
1145         textLayoutModule->lspacingLE->setEnabled(item == 3);
1146 }
1147
1148
1149 void GuiDocument::setIndent(int item)
1150 {
1151         bool const enable = (item == 1);
1152         textLayoutModule->indentLE->setEnabled(enable);
1153         textLayoutModule->indentLengthCO->setEnabled(enable);
1154         textLayoutModule->skipLE->setEnabled(false);
1155         textLayoutModule->skipLengthCO->setEnabled(false);
1156         isValid();
1157 }
1158
1159
1160 void GuiDocument::enableIndent(bool indent)
1161 {
1162         textLayoutModule->skipLE->setEnabled(!indent);
1163         textLayoutModule->skipLengthCO->setEnabled(!indent);
1164         if (indent)
1165                 setIndent(textLayoutModule->indentCO->currentIndex());
1166 }
1167
1168
1169 void GuiDocument::setSkip(int item)
1170 {
1171         bool const enable = (item == 3);
1172         textLayoutModule->skipLE->setEnabled(enable);
1173         textLayoutModule->skipLengthCO->setEnabled(enable);
1174         isValid();
1175 }
1176
1177
1178 void GuiDocument::enableSkip(bool skip)
1179 {
1180         textLayoutModule->indentLE->setEnabled(!skip);
1181         textLayoutModule->indentLengthCO->setEnabled(!skip);
1182         if (skip)
1183                 setSkip(textLayoutModule->skipCO->currentIndex());
1184 }
1185
1186
1187 void GuiDocument::portraitChanged()
1188 {
1189         setMargins(pageLayoutModule->papersizeCO->currentIndex());
1190 }
1191
1192
1193 void GuiDocument::setMargins(bool custom)
1194 {
1195         bool const extern_geometry =
1196                 documentClass().provides("geometry");
1197         marginsModule->marginCB->setEnabled(!extern_geometry);
1198         if (extern_geometry) {
1199                 marginsModule->marginCB->setChecked(false);
1200                 setCustomMargins(true);
1201                 return;
1202         }
1203         marginsModule->marginCB->setChecked(custom);
1204         setCustomMargins(custom);
1205 }
1206
1207
1208 void GuiDocument::papersizeChanged(int paper_size)
1209 {
1210         setCustomPapersize(paper_size == 1);
1211 }
1212
1213
1214 void GuiDocument::setCustomPapersize(bool custom)
1215 {
1216         pageLayoutModule->paperwidthL->setEnabled(custom);
1217         pageLayoutModule->paperwidthLE->setEnabled(custom);
1218         pageLayoutModule->paperwidthUnitCO->setEnabled(custom);
1219         pageLayoutModule->paperheightL->setEnabled(custom);
1220         pageLayoutModule->paperheightLE->setEnabled(custom);
1221         pageLayoutModule->paperheightLE->setFocus();
1222         pageLayoutModule->paperheightUnitCO->setEnabled(custom);
1223 }
1224
1225
1226 void GuiDocument::setColSep()
1227 {
1228         setCustomMargins(marginsModule->marginCB->checkState() == Qt::Checked);
1229 }
1230
1231
1232 void GuiDocument::setCustomMargins(bool custom)
1233 {
1234         marginsModule->topL->setEnabled(!custom);
1235         marginsModule->topLE->setEnabled(!custom);
1236         marginsModule->topUnit->setEnabled(!custom);
1237
1238         marginsModule->bottomL->setEnabled(!custom);
1239         marginsModule->bottomLE->setEnabled(!custom);
1240         marginsModule->bottomUnit->setEnabled(!custom);
1241
1242         marginsModule->innerL->setEnabled(!custom);
1243         marginsModule->innerLE->setEnabled(!custom);
1244         marginsModule->innerUnit->setEnabled(!custom);
1245
1246         marginsModule->outerL->setEnabled(!custom);
1247         marginsModule->outerLE->setEnabled(!custom);
1248         marginsModule->outerUnit->setEnabled(!custom);
1249
1250         marginsModule->headheightL->setEnabled(!custom);
1251         marginsModule->headheightLE->setEnabled(!custom);
1252         marginsModule->headheightUnit->setEnabled(!custom);
1253
1254         marginsModule->headsepL->setEnabled(!custom);
1255         marginsModule->headsepLE->setEnabled(!custom);
1256         marginsModule->headsepUnit->setEnabled(!custom);
1257
1258         marginsModule->footskipL->setEnabled(!custom);
1259         marginsModule->footskipLE->setEnabled(!custom);
1260         marginsModule->footskipUnit->setEnabled(!custom);
1261
1262         bool const enableColSep = !custom && 
1263                         textLayoutModule->twoColumnCB->checkState() == Qt::Checked;
1264         marginsModule->columnsepL->setEnabled(enableColSep);
1265         marginsModule->columnsepLE->setEnabled(enableColSep);
1266         marginsModule->columnsepUnit->setEnabled(enableColSep);
1267 }
1268
1269 void GuiDocument::changeBackgroundColor()
1270 {
1271         QColor const & newColor = QColorDialog::getColor(
1272                 rgb2qcolor(set_backgroundcolor), asQWidget());
1273         if (!newColor.isValid())
1274                 return;
1275         // set the button color
1276         pageLayoutModule->backgroundPB->setStyleSheet(
1277                 colorButtonStyleSheet(newColor));
1278         // save color
1279         set_backgroundcolor = rgbFromHexName(fromqstr(newColor.name()));
1280         changed();
1281 }
1282
1283
1284 void GuiDocument::deleteBackgroundColor()
1285 {
1286         // set the button color back to white
1287         pageLayoutModule->backgroundPB->setStyleSheet(
1288                 colorButtonStyleSheet(QColor(Qt::white)));
1289         // save white as the set color
1290         set_backgroundcolor = rgbFromHexName("#ffffff");
1291         changed();
1292 }
1293
1294
1295 void GuiDocument::xetexChanged(bool xetex)
1296 {
1297         updateFontlist();
1298         updateDefaultFormat();
1299         langModule->encodingCO->setEnabled(!xetex &&
1300                 !langModule->defaultencodingRB->isChecked());
1301         langModule->defaultencodingRB->setEnabled(!xetex);
1302         langModule->otherencodingRB->setEnabled(!xetex);
1303
1304         fontModule->fontsDefaultCO->setEnabled(!xetex);
1305         fontModule->fontsDefaultLA->setEnabled(!xetex);
1306         fontModule->cjkFontLE->setEnabled(!xetex);
1307         fontModule->cjkFontLA->setEnabled(!xetex);
1308         string font;
1309         if (!xetex)
1310                 font = tex_fonts_sans[fontModule->fontsSansCO->currentIndex()];
1311         bool scaleable = providesScale(font);
1312         fontModule->scaleSansSB->setEnabled(scaleable);
1313         fontModule->scaleSansLA->setEnabled(scaleable);
1314         if (!xetex)
1315                 font = tex_fonts_monospaced[fontModule->fontsTypewriterCO->currentIndex()];
1316         scaleable = providesScale(font);
1317         fontModule->scaleTypewriterSB->setEnabled(scaleable);
1318         fontModule->scaleTypewriterLA->setEnabled(scaleable);
1319         if (!xetex)
1320                 font = tex_fonts_roman[fontModule->fontsRomanCO->currentIndex()];
1321         fontModule->fontScCB->setEnabled(providesSC(font));
1322         fontModule->fontOsfCB->setEnabled(providesOSF(font));
1323 }
1324
1325
1326 void GuiDocument::updateFontsize(string const & items, string const & sel)
1327 {
1328         fontModule->fontsizeCO->clear();
1329         fontModule->fontsizeCO->addItem(qt_("Default"));
1330
1331         for (int n = 0; !token(items,'|',n).empty(); ++n)
1332                 fontModule->fontsizeCO->
1333                         addItem(toqstr(token(items,'|',n)));
1334
1335         for (int n = 0; n < fontModule->fontsizeCO->count(); ++n) {
1336                 if (fromqstr(fontModule->fontsizeCO->itemText(n)) == sel) {
1337                         fontModule->fontsizeCO->setCurrentIndex(n);
1338                         break;
1339                 }
1340         }
1341 }
1342
1343
1344 void GuiDocument::updateFontlist()
1345 {
1346         fontModule->fontsRomanCO->clear();
1347         fontModule->fontsSansCO->clear();
1348         fontModule->fontsTypewriterCO->clear();
1349
1350         // With XeTeX, we have access to all system fonts, but not the LaTeX fonts
1351         if (outputModule->xetexCB->isChecked()) {
1352                 fontModule->fontsRomanCO->addItem(qt_("Default"));
1353                 fontModule->fontsSansCO->addItem(qt_("Default"));
1354                 fontModule->fontsTypewriterCO->addItem(qt_("Default"));
1355         
1356                 QFontDatabase fontdb;
1357                 QStringList families(fontdb.families());
1358                 for (QStringList::Iterator it = families.begin(); it != families.end(); ++it) {
1359                         fontModule->fontsRomanCO->addItem(*it);
1360                         fontModule->fontsSansCO->addItem(*it);
1361                         fontModule->fontsTypewriterCO->addItem(*it);
1362                 }
1363                 return;
1364         }
1365
1366         for (int n = 0; tex_fonts_roman[n][0]; ++n) {
1367                 QString font = qt_(tex_fonts_roman_gui[n]);
1368                 if (!isFontAvailable(tex_fonts_roman[n]))
1369                         font += qt_(" (not installed)");
1370                 fontModule->fontsRomanCO->addItem(font);
1371         }
1372         for (int n = 0; tex_fonts_sans[n][0]; ++n) {
1373                 QString font = qt_(tex_fonts_sans_gui[n]);
1374                 if (!isFontAvailable(tex_fonts_sans[n]))
1375                         font += qt_(" (not installed)");
1376                 fontModule->fontsSansCO->addItem(font);
1377         }
1378         for (int n = 0; tex_fonts_monospaced[n][0]; ++n) {
1379                 QString font = qt_(tex_fonts_monospaced_gui[n]);
1380                 if (!isFontAvailable(tex_fonts_monospaced[n]))
1381                         font += qt_(" (not installed)");
1382                 fontModule->fontsTypewriterCO->addItem(font);
1383         }
1384 }
1385
1386
1387 void GuiDocument::romanChanged(int item)
1388 {
1389         if (outputModule->xetexCB->isChecked())
1390                 return;
1391         string const font = tex_fonts_roman[item];
1392         fontModule->fontScCB->setEnabled(providesSC(font));
1393         fontModule->fontOsfCB->setEnabled(providesOSF(font));
1394 }
1395
1396
1397 void GuiDocument::sansChanged(int item)
1398 {
1399         if (outputModule->xetexCB->isChecked())
1400                 return;
1401         string const font = tex_fonts_sans[item];
1402         bool scaleable = providesScale(font);
1403         fontModule->scaleSansSB->setEnabled(scaleable);
1404         fontModule->scaleSansLA->setEnabled(scaleable);
1405 }
1406
1407
1408 void GuiDocument::ttChanged(int item)
1409 {
1410         if (outputModule->xetexCB->isChecked())
1411                 return;
1412         string const font = tex_fonts_monospaced[item];
1413         bool scaleable = providesScale(font);
1414         fontModule->scaleTypewriterSB->setEnabled(scaleable);
1415         fontModule->scaleTypewriterLA->setEnabled(scaleable);
1416 }
1417
1418
1419 void GuiDocument::updatePagestyle(string const & items, string const & sel)
1420 {
1421         pagestyles.clear();
1422         pageLayoutModule->pagestyleCO->clear();
1423         pageLayoutModule->pagestyleCO->addItem(qt_("Default"));
1424
1425         for (int n = 0; !token(items, '|', n).empty(); ++n) {
1426                 string style = token(items, '|', n);
1427                 QString style_gui = qt_(style);
1428                 pagestyles.push_back(pair<string, QString>(style, style_gui));
1429                 pageLayoutModule->pagestyleCO->addItem(style_gui);
1430         }
1431
1432         if (sel == "default") {
1433                 pageLayoutModule->pagestyleCO->setCurrentIndex(0);
1434                 return;
1435         }
1436
1437         int nn = 0;
1438
1439         for (size_t i = 0; i < pagestyles.size(); ++i)
1440                 if (pagestyles[i].first == sel)
1441                         nn = pageLayoutModule->pagestyleCO->findText(pagestyles[i].second);
1442
1443         if (nn > 0)
1444                 pageLayoutModule->pagestyleCO->setCurrentIndex(nn);
1445 }
1446
1447
1448 void GuiDocument::browseLayout()
1449 {
1450         QString const label1 = qt_("Layouts|#o#O");
1451         QString const dir1 = toqstr(lyxrc.document_path);
1452         QStringList const filter(qt_("LyX Layout (*.layout)"));
1453         QString file = browseRelFile(QString(), bufferFilepath(),
1454                 qt_("Local layout file"), filter, false,
1455                 label1, dir1);
1456
1457         if (!file.endsWith(".layout"))
1458                 return;
1459
1460         FileName layoutFile = support::makeAbsPath(fromqstr(file),
1461                 fromqstr(bufferFilepath()));
1462         
1463         int const ret = Alert::prompt(_("Local layout file"),
1464                 _("The layout file you have selected is a local layout\n"
1465                   "file, not one in the system or user directory. Your\n"
1466                   "document may not work with this layout if you do not\n"
1467                   "keep the layout file in the document directory."),
1468                   1, 1, _("&Set Layout"), _("&Cancel"));
1469         if (ret == 1)
1470                 return;
1471
1472         // load the layout file
1473         LayoutFileList & bcl = LayoutFileList::get();
1474         string classname = layoutFile.onlyFileName();
1475         // this will update an existing layout if that layout has been loaded before.
1476         LayoutFileIndex name = bcl.addLocalLayout(
1477                 classname.substr(0, classname.size() - 7),
1478                 layoutFile.onlyPath().absFilename());
1479
1480         if (name.empty()) {
1481                 Alert::error(_("Error"),
1482                         _("Unable to read local layout file."));                
1483                 return;
1484         }
1485
1486         // do not trigger classChanged if there is no change.
1487         if (latexModule->classCO->currentText() == toqstr(name))
1488                 return;
1489                 
1490         // add to combo box
1491         int idx = latexModule->classCO->findText(toqstr(name));
1492         if (idx == -1) {
1493                 classes_model_.insertRow(0, toqstr(name), name);
1494                 latexModule->classCO->setCurrentIndex(0);
1495         } else
1496                 latexModule->classCO->setCurrentIndex(idx);
1497         
1498         classChanged();
1499 }
1500
1501
1502 void GuiDocument::browseMaster()
1503 {
1504         QString const title = qt_("Select master document");
1505         QString const dir1 = toqstr(lyxrc.document_path);
1506         QString const old = latexModule->childDocLE->text();
1507         QString const docpath = toqstr(support::onlyPath(buffer().absFileName()));
1508         QStringList const filter(qt_("LyX Files (*.lyx)"));
1509         QString file = browseRelFile(old, docpath, title, filter, false,
1510                 qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
1511
1512         latexModule->childDocLE->setText(file);
1513 }
1514
1515
1516 void GuiDocument::classChanged()
1517 {
1518         int idx = latexModule->classCO->currentIndex();
1519         if (idx < 0) 
1520                 return;
1521         string const classname = classes_model_.getIDString(idx);
1522
1523         // check whether the selected modules have changed.
1524         bool modules_changed = false;
1525         unsigned int const srows = selectedModel()->rowCount();
1526         if (srows != bp_.getModules().size())
1527                 modules_changed = true;
1528         else {
1529                 list<string>::const_iterator mit = bp_.getModules().begin();
1530                 list<string>::const_iterator men = bp_.getModules().end();
1531                 for (unsigned int i = 0; i < srows && mit != men; ++i, ++mit)
1532                         if (selectedModel()->getIDString(i) != *mit) {
1533                                 modules_changed = true;
1534                                 break;
1535                         }
1536         }
1537
1538         if (modules_changed || lyxrc.auto_reset_options) {
1539                 if (applyPB->isEnabled()) {
1540                         int const ret = Alert::prompt(_("Unapplied changes"),
1541                                         _("Some changes in the dialog were not yet applied.\n"
1542                                         "If you do not apply now, they will be lost after this action."),
1543                                         1, 1, _("&Apply"), _("&Dismiss"));
1544                         if (ret == 0)
1545                                 applyView();
1546                 }
1547         }
1548
1549         // We load the TextClass as soon as it is selected. This is
1550         // necessary so that other options in the dialog can be updated
1551         // according to the new class. Note, however, that, if you use 
1552         // the scroll wheel when sitting on the combo box, we'll load a 
1553         // lot of TextClass objects very quickly....
1554         if (!bp_.setBaseClass(classname)) {
1555                 Alert::error(_("Error"), _("Unable to set document class."));
1556                 return;
1557         }
1558         if (lyxrc.auto_reset_options)
1559                 bp_.useClassDefaults();
1560
1561         // With the introduction of modules came a distinction between the base 
1562         // class and the document class. The former corresponds to the main layout 
1563         // file; the latter is that plus the modules (or the document-specific layout,
1564         // or  whatever else there could be). Our parameters come from the document 
1565         // class. So when we set the base class, we also need to recreate the document 
1566         // class. Otherwise, we still have the old one.
1567         bp_.makeDocumentClass();
1568         paramsToDialog();
1569 }
1570
1571
1572 void GuiDocument::bibtexChanged(int n)
1573 {
1574         biblioModule->bibtexOptionsED->setEnabled(n != 0);
1575         changed();
1576 }
1577
1578
1579 namespace {
1580         // This is an insanely complicated attempt to make this sort of thing
1581         // work with RTL languages.
1582         docstring formatStrVec(vector<string> const & v, docstring const & s) 
1583         {
1584                 //this mess formats the list as "v[0], v[1], ..., [s] v[n]"
1585                 if (v.size() == 0)
1586                         return docstring();
1587                 if (v.size() == 1) 
1588                         return from_utf8(v[0]);
1589                 if (v.size() == 2) {
1590                         docstring retval = _("%1$s and %2$s");
1591                         retval = subst(retval, _("and"), s);
1592                         return bformat(retval, from_utf8(v[0]), from_utf8(v[1]));
1593                 }
1594                 // The idea here is to format all but the last two items...
1595                 int const vSize = v.size();
1596                 docstring t2 = _("%1$s, %2$s");
1597                 docstring retval = from_utf8(v[0]);
1598                 for (int i = 1; i < vSize - 2; ++i)
1599                         retval = bformat(t2, retval, from_utf8(v[i])); 
1600                 //...and then to  plug them, and the last two, into this schema
1601                 docstring t = _("%1$s, %2$s, and %3$s");
1602                 t = subst(t, _("and"), s);
1603                 return bformat(t, retval, from_utf8(v[vSize - 2]), from_utf8(v[vSize - 1]));
1604         }
1605         
1606         vector<string> idsToNames(vector<string> const & idList)
1607         {
1608                 vector<string> retval;
1609                 vector<string>::const_iterator it  = idList.begin();
1610                 vector<string>::const_iterator end = idList.end();
1611                 for (; it != end; ++it) {
1612                         LyXModule const * const mod = theModuleList[*it];
1613                         if (!mod)
1614                                 retval.push_back(*it + " (Unavailable)");
1615                         else
1616                                 retval.push_back(mod->getName());
1617                 }
1618                 return retval;
1619         }
1620 }
1621
1622
1623 void GuiDocument::modulesToParams(BufferParams & bp)
1624 {
1625         // update list of loaded modules
1626         bp.clearLayoutModules();
1627         int const srows = modules_sel_model_.rowCount();
1628         for (int i = 0; i < srows; ++i)
1629                 bp.addLayoutModule(modules_sel_model_.getIDString(i));
1630
1631         // update the list of removed modules
1632         bp.clearRemovedModules();
1633         LayoutModuleList const & reqmods = bp.baseClass()->defaultModules();
1634         list<string>::const_iterator rit = reqmods.begin();
1635         list<string>::const_iterator ren = reqmods.end();
1636
1637         // check each of the default modules
1638         for (; rit != ren; rit++) {
1639                 list<string>::const_iterator mit = bp.getModules().begin();
1640                 list<string>::const_iterator men = bp.getModules().end();
1641                 bool found = false;
1642                 for (; mit != men; mit++) {
1643                         if (*rit == *mit) {
1644                                 found = true;
1645                                 break;
1646                         }
1647                 }
1648                 if (!found) {
1649                         // the module isn't present so must have been removed by the user
1650                         bp.addRemovedModule(*rit);
1651                 }
1652         }
1653 }
1654
1655 void GuiDocument::modulesChanged()
1656 {
1657         modulesToParams(bp_);
1658         bp_.makeDocumentClass();
1659         paramsToDialog();
1660 }
1661
1662
1663 void GuiDocument::updateModuleInfo()
1664 {
1665         selectionManager->update();
1666         
1667         //Module description
1668         bool const focus_on_selected = selectionManager->selectedFocused();
1669         QAbstractItemView * lv;
1670         if (focus_on_selected)
1671                 lv = modulesModule->selectedLV;
1672         else
1673                 lv= modulesModule->availableLV;
1674         if (lv->selectionModel()->selectedIndexes().isEmpty()) {
1675                 modulesModule->infoML->document()->clear();
1676                 return;
1677         }
1678         QModelIndex const & idx = lv->selectionModel()->currentIndex();
1679         GuiIdListModel const & id_model = 
1680                         focus_on_selected  ? modules_sel_model_ : modules_av_model_;
1681         string const modName = id_model.getIDString(idx.row());
1682         docstring desc = getModuleDescription(modName);
1683
1684         LayoutModuleList const & provmods = bp_.baseClass()->providedModules();
1685         if (std::find(provmods.begin(), provmods.end(), modName) != provmods.end()) {
1686                 if (!desc.empty())
1687                         desc += "\n";
1688                 desc += _("Module provided by document class.");
1689         }
1690
1691         vector<string> pkglist = getPackageList(modName);
1692         docstring pkgdesc = formatStrVec(pkglist, _("and"));
1693         if (!pkgdesc.empty()) {
1694                 if (!desc.empty())
1695                         desc += "\n";
1696                 desc += bformat(_("Package(s) required: %1$s."), pkgdesc);
1697         }
1698
1699         pkglist = getRequiredList(modName);
1700         if (!pkglist.empty()) {
1701                 vector<string> const reqdescs = idsToNames(pkglist);
1702                 pkgdesc = formatStrVec(reqdescs, _("or"));
1703                 if (!desc.empty())
1704                         desc += "\n";
1705                 desc += bformat(_("Module required: %1$s."), pkgdesc);
1706         }
1707
1708         pkglist = getExcludedList(modName);
1709         if (!pkglist.empty()) {
1710                 vector<string> const reqdescs = idsToNames(pkglist);
1711                 pkgdesc = formatStrVec(reqdescs, _( "and"));
1712                 if (!desc.empty())
1713                         desc += "\n";
1714                 desc += bformat(_("Modules excluded: %1$s."), pkgdesc);
1715         }
1716
1717         if (!isModuleAvailable(modName)) {
1718                 if (!desc.empty())
1719                         desc += "\n";
1720                 desc += _("WARNING: Some required packages are unavailable!");
1721         }
1722
1723         modulesModule->infoML->document()->setPlainText(toqstr(desc));
1724 }
1725
1726
1727 void GuiDocument::updateNumbering()
1728 {
1729         DocumentClass const & tclass = documentClass();
1730
1731         numberingModule->tocTW->setUpdatesEnabled(false);
1732         numberingModule->tocTW->clear();
1733
1734         int const depth = numberingModule->depthSL->value();
1735         int const toc = numberingModule->tocSL->value();
1736         QString const no = qt_("No");
1737         QString const yes = qt_("Yes");
1738         QTreeWidgetItem * item = 0;
1739
1740         DocumentClass::const_iterator lit = tclass.begin();
1741         DocumentClass::const_iterator len = tclass.end();
1742         for (; lit != len; ++lit) {
1743                 int const toclevel = lit->toclevel;
1744                 if (toclevel != Layout::NOT_IN_TOC && lit->labeltype == LABEL_COUNTER) {
1745                         item = new QTreeWidgetItem(numberingModule->tocTW);
1746                         item->setText(0, toqstr(translateIfPossible(lit->name())));
1747                         item->setText(1, (toclevel <= depth) ? yes : no);
1748                         item->setText(2, (toclevel <= toc) ? yes : no);
1749                 }
1750         }
1751
1752         numberingModule->tocTW->setUpdatesEnabled(true);
1753         numberingModule->tocTW->update();
1754 }
1755
1756
1757 void GuiDocument::updateDefaultFormat()
1758 {
1759         // make a copy in order to consider unapplied changes
1760         Buffer * tmpbuf = const_cast<Buffer *>(&buffer());
1761         tmpbuf->params().useXetex = outputModule->xetexCB->isChecked();
1762         int idx = latexModule->classCO->currentIndex();
1763         if (idx >= 0) {
1764                 string const classname = classes_model_.getIDString(idx);
1765                 tmpbuf->params().setBaseClass(classname);
1766                 tmpbuf->params().makeDocumentClass();
1767         }
1768         outputModule->defaultFormatCO->blockSignals(true);
1769         outputModule->defaultFormatCO->clear();
1770         outputModule->defaultFormatCO->addItem(qt_("Default"),
1771                                 QVariant(QString("default")));
1772         typedef vector<Format const *> Formats;
1773         Formats formats = tmpbuf->exportableFormats(true);
1774         Formats::const_iterator cit = formats.begin();
1775         Formats::const_iterator end = formats.end();
1776         for (; cit != end; ++cit)
1777                 outputModule->defaultFormatCO->addItem(qt_((*cit)->prettyname()),
1778                                 QVariant(toqstr((*cit)->name())));
1779         outputModule->defaultFormatCO->blockSignals(false);
1780 }
1781
1782
1783 void GuiDocument::applyView()
1784 {
1785         // preamble
1786         preambleModule->apply(bp_);
1787
1788         // date
1789         bp_.suppress_date = latexModule->suppressDateCB->isChecked();
1790
1791         // biblio
1792         bp_.setCiteEngine(ENGINE_BASIC);
1793
1794         if (biblioModule->citeNatbibRB->isChecked()) {
1795                 bool const use_numerical_citations =
1796                         biblioModule->citeStyleCO->currentIndex();
1797                 if (use_numerical_citations)
1798                         bp_.setCiteEngine(ENGINE_NATBIB_NUMERICAL);
1799                 else
1800                         bp_.setCiteEngine(ENGINE_NATBIB_AUTHORYEAR);
1801
1802         } else if (biblioModule->citeJurabibRB->isChecked())
1803                 bp_.setCiteEngine(ENGINE_JURABIB);
1804
1805         bp_.use_bibtopic =
1806                 biblioModule->bibtopicCB->isChecked();
1807
1808         string const bibtex_command =
1809                 fromqstr(biblioModule->bibtexCO->itemData(
1810                         biblioModule->bibtexCO->currentIndex()).toString());
1811         string const bibtex_options =
1812                 fromqstr(biblioModule->bibtexOptionsED->text());
1813         if (bibtex_command == "default" || bibtex_options.empty())
1814                 bp_.bibtex_command = bibtex_command;
1815         else
1816                 bp_.bibtex_command = bibtex_command + " " + bibtex_options;
1817
1818         // Indices
1819         indicesModule->apply(bp_);
1820
1821         // language & quotes
1822         if (langModule->defaultencodingRB->isChecked()) {
1823                 bp_.inputenc = "auto";
1824         } else {
1825                 int i = langModule->encodingCO->currentIndex();
1826                 if (i == 0)
1827                         bp_.inputenc = "default";
1828                 else {
1829                         QString const enc_gui =
1830                                 langModule->encodingCO->currentText();
1831                         Encodings::const_iterator it = encodings.begin();
1832                         Encodings::const_iterator const end = encodings.end();
1833                         bool found = false;
1834                         for (; it != end; ++it) {
1835                                 if (qt_(it->guiName()) == enc_gui) {
1836                                         bp_.inputenc = it->latexName();
1837                                         found = true;
1838                                         break;
1839                                 }
1840                         }
1841                         if (!found) {
1842                                 // should not happen
1843                                 lyxerr << "GuiDocument::apply: Unknown encoding! Resetting to default" << endl;
1844                                 bp_.inputenc = "default";
1845                         }
1846                 }
1847         }
1848
1849         InsetQuotes::QuoteLanguage lga = InsetQuotes::EnglishQuotes;
1850         switch (langModule->quoteStyleCO->currentIndex()) {
1851         case 0:
1852                 lga = InsetQuotes::EnglishQuotes;
1853                 break;
1854         case 1:
1855                 lga = InsetQuotes::SwedishQuotes;
1856                 break;
1857         case 2:
1858                 lga = InsetQuotes::GermanQuotes;
1859                 break;
1860         case 3:
1861                 lga = InsetQuotes::PolishQuotes;
1862                 break;
1863         case 4:
1864                 lga = InsetQuotes::FrenchQuotes;
1865                 break;
1866         case 5:
1867                 lga = InsetQuotes::DanishQuotes;
1868                 break;
1869         }
1870         bp_.quotes_language = lga;
1871
1872         QString const lang = langModule->languageCO->itemData(
1873                 langModule->languageCO->currentIndex()).toString();
1874         bp_.language = languages.getLanguage(fromqstr(lang));
1875
1876         // numbering
1877         if (bp_.documentClass().hasTocLevels()) {
1878                 bp_.tocdepth = numberingModule->tocSL->value();
1879                 bp_.secnumdepth = numberingModule->depthSL->value();
1880         }
1881
1882         // bullets
1883         bp_.user_defined_bullet(0) = bulletsModule->bullet(0);
1884         bp_.user_defined_bullet(1) = bulletsModule->bullet(1);
1885         bp_.user_defined_bullet(2) = bulletsModule->bullet(2);
1886         bp_.user_defined_bullet(3) = bulletsModule->bullet(3);
1887
1888         // packages
1889         bp_.graphicsDriver =
1890                 tex_graphics[latexModule->psdriverCO->currentIndex()];
1891         
1892         // text layout
1893         int idx = latexModule->classCO->currentIndex();
1894         if (idx >= 0) {
1895                 string const classname = classes_model_.getIDString(idx);
1896                 bp_.setBaseClass(classname);
1897         }
1898
1899         // Modules
1900         modulesToParams(bp_);
1901
1902         // Math
1903         if (mathsModule->amsautoCB->isChecked()) {
1904                 bp_.use_amsmath = BufferParams::package_auto;
1905         } else {
1906                 if (mathsModule->amsCB->isChecked())
1907                         bp_.use_amsmath = BufferParams::package_on;
1908                 else
1909                         bp_.use_amsmath = BufferParams::package_off;
1910         }
1911
1912         if (mathsModule->esintautoCB->isChecked())
1913                 bp_.use_esint = BufferParams::package_auto;
1914         else {
1915                 if (mathsModule->esintCB->isChecked())
1916                         bp_.use_esint = BufferParams::package_on;
1917                 else
1918                         bp_.use_esint = BufferParams::package_off;
1919         }
1920
1921         // Page Layout
1922         if (pageLayoutModule->pagestyleCO->currentIndex() == 0)
1923                 bp_.pagestyle = "default";
1924         else {
1925                 QString style_gui = pageLayoutModule->pagestyleCO->currentText();
1926                 for (size_t i = 0; i != pagestyles.size(); ++i)
1927                         if (pagestyles[i].second == style_gui)
1928                                 bp_.pagestyle = pagestyles[i].first;
1929         }
1930
1931         // Text Layout
1932         switch (textLayoutModule->lspacingCO->currentIndex()) {
1933         case 0:
1934                 bp_.spacing().set(Spacing::Single);
1935                 break;
1936         case 1:
1937                 bp_.spacing().set(Spacing::Onehalf);
1938                 break;
1939         case 2:
1940                 bp_.spacing().set(Spacing::Double);
1941                 break;
1942         case 3:
1943                 bp_.spacing().set(Spacing::Other,
1944                         widgetToDoubleStr(textLayoutModule->lspacingLE));
1945                 break;
1946         }
1947
1948         if (textLayoutModule->twoColumnCB->isChecked())
1949                 bp_.columns = 2;
1950         else
1951                 bp_.columns = 1;
1952
1953         if (textLayoutModule->indentRB->isChecked()) {
1954                 // if paragraphs are separated by an indentation
1955                 bp_.paragraph_separation = BufferParams::ParagraphIndentSeparation;
1956                 switch (textLayoutModule->indentCO->currentIndex()) {
1957                 case 0:
1958                         bp_.setIndentation(HSpace(HSpace::DEFAULT));
1959                         break;
1960                 case 1: {
1961                         HSpace indent = HSpace(
1962                                 widgetsToLength(textLayoutModule->indentLE,
1963                                 textLayoutModule->indentLengthCO)
1964                                 );
1965                         bp_.setIndentation(indent);
1966                         break;
1967                         }
1968                 default:
1969                         // this should never happen
1970                         bp_.setIndentation(HSpace(HSpace::DEFAULT));
1971                         break;
1972                 }
1973         } else {
1974                 // if paragraphs are separated by a skip
1975                 bp_.paragraph_separation = BufferParams::ParagraphSkipSeparation;
1976                 switch (textLayoutModule->skipCO->currentIndex()) {
1977                 case 0:
1978                         bp_.setDefSkip(VSpace(VSpace::SMALLSKIP));
1979                         break;
1980                 case 1:
1981                         bp_.setDefSkip(VSpace(VSpace::MEDSKIP));
1982                         break;
1983                 case 2:
1984                         bp_.setDefSkip(VSpace(VSpace::BIGSKIP));
1985                         break;
1986                 case 3:
1987                         {
1988                         VSpace vs = VSpace(
1989                                 widgetsToLength(textLayoutModule->skipLE,
1990                                 textLayoutModule->skipLengthCO)
1991                                 );
1992                         bp_.setDefSkip(vs);
1993                         break;
1994                         }
1995                 default:
1996                         // this should never happen
1997                         bp_.setDefSkip(VSpace(VSpace::MEDSKIP));
1998                         break;
1999                 }
2000         }
2001
2002         bp_.options =
2003                 fromqstr(latexModule->optionsLE->text());
2004
2005         bp_.use_default_options =
2006                 latexModule->defaultOptionsCB->isChecked();
2007
2008         if (latexModule->childDocGB->isChecked())
2009                 bp_.master =
2010                         fromqstr(latexModule->childDocLE->text());
2011         else
2012                 bp_.master = string();
2013
2014         // Float Placement
2015         bp_.float_placement = floatModule->get();
2016
2017         // Listings
2018         // text should have passed validation
2019         bp_.listings_params =
2020                 InsetListingsParams(fromqstr(listingsModule->listingsED->toPlainText())).params();
2021
2022         // output
2023         bp_.defaultOutputFormat = fromqstr(outputModule->defaultFormatCO->itemData(
2024                 outputModule->defaultFormatCO->currentIndex()).toString());
2025
2026         bool const xetex = outputModule->xetexCB->isChecked();
2027         bp_.useXetex = xetex;
2028
2029         // fonts
2030         if (xetex) {
2031                 if (fontModule->fontsRomanCO->currentIndex() == 0)
2032                         bp_.fontsRoman = "default";
2033                 else
2034                         bp_.fontsRoman =
2035                                 fromqstr(fontModule->fontsRomanCO->currentText());
2036         
2037                 if (fontModule->fontsSansCO->currentIndex() == 0)
2038                         bp_.fontsSans = "default";
2039                 else
2040                         bp_.fontsSans =
2041                                 fromqstr(fontModule->fontsSansCO->currentText());
2042         
2043                 if (fontModule->fontsTypewriterCO->currentIndex() == 0)
2044                         bp_.fontsTypewriter = "default";
2045                 else
2046                         bp_.fontsTypewriter =
2047                                 fromqstr(fontModule->fontsTypewriterCO->currentText());
2048         } else {
2049                 bp_.fontsRoman =
2050                         tex_fonts_roman[fontModule->fontsRomanCO->currentIndex()];
2051         
2052                 bp_.fontsSans =
2053                         tex_fonts_sans[fontModule->fontsSansCO->currentIndex()];
2054         
2055                 bp_.fontsTypewriter =
2056                         tex_fonts_monospaced[fontModule->fontsTypewriterCO->currentIndex()];
2057         }
2058
2059         bp_.fontsCJK =
2060                 fromqstr(fontModule->cjkFontLE->text());
2061
2062         bp_.fontsSansScale = fontModule->scaleSansSB->value();
2063
2064         bp_.fontsTypewriterScale = fontModule->scaleTypewriterSB->value();
2065
2066         bp_.fontsSC = fontModule->fontScCB->isChecked();
2067
2068         bp_.fontsOSF = fontModule->fontOsfCB->isChecked();
2069
2070         if (xetex)
2071                 bp_.fontsDefaultFamily = "default";
2072         else
2073                 bp_.fontsDefaultFamily = GuiDocument::fontfamilies[
2074                         fontModule->fontsDefaultCO->currentIndex()];
2075
2076         if (fontModule->fontsizeCO->currentIndex() == 0)
2077                 bp_.fontsize = "default";
2078         else
2079                 bp_.fontsize =
2080                         fromqstr(fontModule->fontsizeCO->currentText());
2081
2082         // paper
2083         bp_.papersize = PAPER_SIZE(
2084                 pageLayoutModule->papersizeCO->currentIndex());
2085
2086         // custom, A3, B3 and B4 paper sizes need geometry
2087         int psize = pageLayoutModule->papersizeCO->currentIndex();
2088         bool geom_papersize = (psize == 1 || psize == 5 || psize == 8 || psize == 9);
2089
2090         bp_.paperwidth = widgetsToLength(pageLayoutModule->paperwidthLE,
2091                 pageLayoutModule->paperwidthUnitCO);
2092
2093         bp_.paperheight = widgetsToLength(pageLayoutModule->paperheightLE,
2094                 pageLayoutModule->paperheightUnitCO);
2095
2096         if (pageLayoutModule->facingPagesCB->isChecked())
2097                 bp_.sides = TwoSides;
2098         else
2099                 bp_.sides = OneSide;
2100
2101         if (pageLayoutModule->landscapeRB->isChecked())
2102                 bp_.orientation = ORIENTATION_LANDSCAPE;
2103         else
2104                 bp_.orientation = ORIENTATION_PORTRAIT;
2105
2106         bp_.backgroundcolor = set_backgroundcolor;
2107
2108         // margins
2109         bp_.use_geometry = !marginsModule->marginCB->isChecked()
2110                 || geom_papersize;
2111
2112         Ui::MarginsUi const * m = marginsModule;
2113
2114         bp_.leftmargin = widgetsToLength(m->innerLE, m->innerUnit);
2115         bp_.topmargin = widgetsToLength(m->topLE, m->topUnit);
2116         bp_.rightmargin = widgetsToLength(m->outerLE, m->outerUnit);
2117         bp_.bottommargin = widgetsToLength(m->bottomLE, m->bottomUnit);
2118         bp_.headheight = widgetsToLength(m->headheightLE, m->headheightUnit);
2119         bp_.headsep = widgetsToLength(m->headsepLE, m->headsepUnit);
2120         bp_.footskip = widgetsToLength(m->footskipLE, m->footskipUnit);
2121         bp_.columnsep = widgetsToLength(m->columnsepLE, m->columnsepUnit);
2122
2123         // branches
2124         branchesModule->apply(bp_);
2125
2126         // PDF support
2127         PDFOptions & pdf = bp_.pdfoptions();
2128         pdf.use_hyperref = pdfSupportModule->use_hyperrefGB->isChecked();
2129         pdf.title = fromqstr(pdfSupportModule->titleLE->text());
2130         pdf.author = fromqstr(pdfSupportModule->authorLE->text());
2131         pdf.subject = fromqstr(pdfSupportModule->subjectLE->text());
2132         pdf.keywords = fromqstr(pdfSupportModule->keywordsLE->text());
2133
2134         pdf.bookmarks = pdfSupportModule->bookmarksGB->isChecked();
2135         pdf.bookmarksnumbered = pdfSupportModule->bookmarksnumberedCB->isChecked();
2136         pdf.bookmarksopen = pdfSupportModule->bookmarksopenGB->isChecked();
2137         pdf.bookmarksopenlevel = pdfSupportModule->bookmarksopenlevelSB->value();
2138
2139         pdf.breaklinks = pdfSupportModule->breaklinksCB->isChecked();
2140         pdf.pdfborder = pdfSupportModule->pdfborderCB->isChecked();
2141         pdf.pdfusetitle = pdfSupportModule->pdfusetitleCB->isChecked();
2142         pdf.colorlinks = pdfSupportModule->colorlinksCB->isChecked();
2143         pdf.backref =
2144                 backref_opts[pdfSupportModule->backrefCO->currentIndex()];
2145         if (pdfSupportModule->fullscreenCB->isChecked())
2146                 pdf.pagemode = pdf.pagemode_fullscreen;
2147         else
2148                 pdf.pagemode.clear();
2149         pdf.quoted_options = pdf.quoted_options_check(
2150                                 fromqstr(pdfSupportModule->optionsLE->text()));
2151 }
2152
2153
2154 void GuiDocument::paramsToDialog()
2155 {
2156         // set the default unit
2157         Length::UNIT const defaultUnit = Length::defaultUnit();
2158
2159         // preamble
2160         preambleModule->update(bp_, id());
2161
2162         // date
2163         latexModule->suppressDateCB->setChecked(bp_.suppress_date);
2164
2165         // biblio
2166         biblioModule->citeDefaultRB->setChecked(
2167                 bp_.citeEngine() == ENGINE_BASIC);
2168
2169         biblioModule->citeNatbibRB->setChecked(
2170                 bp_.citeEngine() == ENGINE_NATBIB_NUMERICAL ||
2171                 bp_.citeEngine() == ENGINE_NATBIB_AUTHORYEAR);
2172
2173         biblioModule->citeStyleCO->setCurrentIndex(
2174                 bp_.citeEngine() == ENGINE_NATBIB_NUMERICAL);
2175
2176         biblioModule->citeJurabibRB->setChecked(
2177                 bp_.citeEngine() == ENGINE_JURABIB);
2178
2179         biblioModule->bibtopicCB->setChecked(
2180                 bp_.use_bibtopic);
2181
2182         string command;
2183         string options =
2184                 split(bp_.bibtex_command, command, ' ');
2185
2186         int const bpos = biblioModule->bibtexCO->findData(toqstr(command));
2187         if (bpos != -1) {
2188                 biblioModule->bibtexCO->setCurrentIndex(bpos);
2189                 biblioModule->bibtexOptionsED->setText(toqstr(options).trimmed());
2190         } else {
2191                 biblioModule->bibtexCO->setCurrentIndex(0);
2192                 biblioModule->bibtexOptionsED->clear();
2193         }
2194         biblioModule->bibtexOptionsED->setEnabled(
2195                 biblioModule->bibtexCO->currentIndex() != 0);
2196
2197         // indices
2198         indicesModule->update(bp_);
2199
2200         // language & quotes
2201         int const pos = langModule->languageCO->findData(toqstr(
2202                 bp_.language->lang()));
2203         langModule->languageCO->setCurrentIndex(pos);
2204
2205         langModule->quoteStyleCO->setCurrentIndex(
2206                 bp_.quotes_language);
2207
2208         bool default_enc = true;
2209         if (bp_.inputenc != "auto") {
2210                 default_enc = false;
2211                 if (bp_.inputenc == "default") {
2212                         langModule->encodingCO->setCurrentIndex(0);
2213                 } else {
2214                         string enc_gui;
2215                         Encodings::const_iterator it = encodings.begin();
2216                         Encodings::const_iterator const end = encodings.end();
2217                         for (; it != end; ++it) {
2218                                 if (it->latexName() == bp_.inputenc) {
2219                                         enc_gui = it->guiName();
2220                                         break;
2221                                 }
2222                         }
2223                         int const i = langModule->encodingCO->findText(
2224                                         qt_(enc_gui));
2225                         if (i >= 0)
2226                                 langModule->encodingCO->setCurrentIndex(i);
2227                         else
2228                                 // unknown encoding. Set to default.
2229                                 default_enc = true;
2230                 }
2231         }
2232         langModule->defaultencodingRB->setChecked(default_enc);
2233         langModule->otherencodingRB->setChecked(!default_enc);
2234
2235         // numbering
2236         int const min_toclevel = documentClass().min_toclevel();
2237         int const max_toclevel = documentClass().max_toclevel();
2238         if (documentClass().hasTocLevels()) {
2239                 numberingModule->setEnabled(true);
2240                 numberingModule->depthSL->setMinimum(min_toclevel - 1);
2241                 numberingModule->depthSL->setMaximum(max_toclevel);
2242                 numberingModule->depthSL->setValue(bp_.secnumdepth);
2243                 numberingModule->tocSL->setMaximum(min_toclevel - 1);
2244                 numberingModule->tocSL->setMaximum(max_toclevel);
2245                 numberingModule->tocSL->setValue(bp_.tocdepth);
2246                 updateNumbering();
2247         } else {
2248                 numberingModule->setEnabled(false);
2249                 numberingModule->tocTW->clear();
2250         }
2251
2252         // bullets
2253         bulletsModule->setBullet(0, bp_.user_defined_bullet(0));
2254         bulletsModule->setBullet(1, bp_.user_defined_bullet(1));
2255         bulletsModule->setBullet(2, bp_.user_defined_bullet(2));
2256         bulletsModule->setBullet(3, bp_.user_defined_bullet(3));
2257         bulletsModule->init();
2258
2259         // packages
2260         int nitem = findToken(tex_graphics, bp_.graphicsDriver);
2261         if (nitem >= 0)
2262                 latexModule->psdriverCO->setCurrentIndex(nitem);
2263         updateModuleInfo();
2264         
2265         mathsModule->amsCB->setChecked(
2266                 bp_.use_amsmath == BufferParams::package_on);
2267         mathsModule->amsautoCB->setChecked(
2268                 bp_.use_amsmath == BufferParams::package_auto);
2269
2270         mathsModule->esintCB->setChecked(
2271                 bp_.use_esint == BufferParams::package_on);
2272         mathsModule->esintautoCB->setChecked(
2273                 bp_.use_esint == BufferParams::package_auto);
2274
2275         switch (bp_.spacing().getSpace()) {
2276                 case Spacing::Other: nitem = 3; break;
2277                 case Spacing::Double: nitem = 2; break;
2278                 case Spacing::Onehalf: nitem = 1; break;
2279                 case Spacing::Default: case Spacing::Single: nitem = 0; break;
2280         }
2281
2282         // text layout
2283         string const & layoutID = bp_.baseClassID();
2284         setLayoutComboByIDString(layoutID);
2285
2286         updatePagestyle(documentClass().opt_pagestyle(),
2287                                  bp_.pagestyle);
2288
2289         textLayoutModule->lspacingCO->setCurrentIndex(nitem);
2290         if (bp_.spacing().getSpace() == Spacing::Other) {
2291                 doubleToWidget(textLayoutModule->lspacingLE,
2292                         bp_.spacing().getValueAsString());
2293         }
2294         setLSpacing(nitem);
2295
2296         if (bp_.paragraph_separation == BufferParams::ParagraphIndentSeparation) {
2297                 textLayoutModule->indentRB->setChecked(true);
2298                 string indentation = bp_.getIndentation().asLyXCommand();
2299                 int indent = 0;
2300                 if (indentation != "default") {
2301                         lengthToWidgets(textLayoutModule->indentLE,
2302                         textLayoutModule->indentLengthCO,
2303                         indentation, defaultUnit);
2304                         indent = 1;
2305                 }
2306                 textLayoutModule->indentCO->setCurrentIndex(indent);
2307                 setIndent(indent);
2308         } else {
2309                 textLayoutModule->skipRB->setChecked(true);
2310                 int skip = 0;
2311                 switch (bp_.getDefSkip().kind()) {
2312                 case VSpace::SMALLSKIP:
2313                         skip = 0;
2314                         break;
2315                 case VSpace::MEDSKIP:
2316                         skip = 1;
2317                         break;
2318                 case VSpace::BIGSKIP:
2319                         skip = 2;
2320                         break;
2321                 case VSpace::LENGTH:
2322                         {
2323                         skip = 3;
2324                         string const length = bp_.getDefSkip().asLyXCommand();
2325                         lengthToWidgets(textLayoutModule->skipLE,
2326                                 textLayoutModule->skipLengthCO,
2327                                 length, defaultUnit);
2328                         break;
2329                         }
2330                 default:
2331                         skip = 0;
2332                         break;
2333                 }
2334                 textLayoutModule->skipCO->setCurrentIndex(skip);
2335                 setSkip(skip);
2336         }
2337
2338         textLayoutModule->twoColumnCB->setChecked(
2339                 bp_.columns == 2);
2340
2341         if (!bp_.options.empty()) {
2342                 latexModule->optionsLE->setText(
2343                         toqstr(bp_.options));
2344         } else {
2345                 latexModule->optionsLE->setText(QString());
2346         }
2347
2348         // latex
2349         latexModule->defaultOptionsCB->setChecked(
2350                         bp_.use_default_options);
2351         updateSelectedModules();
2352         selectionManager->updateProvidedModules(
2353                         bp_.baseClass()->providedModules());
2354         selectionManager->updateExcludedModules(
2355                         bp_.baseClass()->excludedModules());
2356
2357         if (!documentClass().options().empty()) {
2358                 latexModule->defaultOptionsLE->setText(
2359                         toqstr(documentClass().options()));
2360         } else {
2361                 latexModule->defaultOptionsLE->setText(
2362                         toqstr(_("[No options predefined]")));
2363         }
2364
2365         latexModule->defaultOptionsLE->setEnabled(
2366                 bp_.use_default_options
2367                 && !documentClass().options().empty());
2368
2369         latexModule->defaultOptionsCB->setEnabled(
2370                 !documentClass().options().empty());
2371
2372         if (!bp_.master.empty()) {
2373                 latexModule->childDocGB->setChecked(true);
2374                 latexModule->childDocLE->setText(
2375                         toqstr(bp_.master));
2376         } else {
2377                 latexModule->childDocLE->setText(QString());
2378                 latexModule->childDocGB->setChecked(false);
2379         }
2380
2381         // Float Settings
2382         floatModule->set(bp_.float_placement);
2383
2384         // ListingsSettings
2385         // break listings_params to multiple lines
2386         string lstparams =
2387                 InsetListingsParams(bp_.listings_params).separatedParams();
2388         listingsModule->listingsED->setPlainText(toqstr(lstparams));
2389
2390         // Output
2391         // update combobox with formats
2392         updateDefaultFormat();
2393         int index = outputModule->defaultFormatCO->findData(toqstr(
2394                 bp_.defaultOutputFormat));
2395         // set to default if format is not found 
2396         if (index == -1)
2397                 index = 0;
2398         outputModule->defaultFormatCO->setCurrentIndex(index);
2399         outputModule->xetexCB->setEnabled(bp_.baseClass()->outputType() == lyx::LATEX);
2400         outputModule->xetexCB->setChecked(
2401                 bp_.baseClass()->outputType() == lyx::LATEX && bp_.useXetex);
2402
2403         // Fonts
2404         updateFontsize(documentClass().opt_fontsize(),
2405                         bp_.fontsize);
2406
2407         if (bp_.useXetex) {
2408                 for (int i = 0; i < fontModule->fontsRomanCO->count(); ++i) {
2409                         if (fontModule->fontsRomanCO->itemText(i) == toqstr(bp_.fontsRoman)) {
2410                                 fontModule->fontsRomanCO->setCurrentIndex(i);
2411                                 return;
2412                         }
2413                 }
2414                 
2415                 for (int i = 0; i < fontModule->fontsSansCO->count(); ++i) {
2416                         if (fontModule->fontsSansCO->itemText(i) == toqstr(bp_.fontsSans)) {
2417                                 fontModule->fontsSansCO->setCurrentIndex(i);
2418                                 return;
2419                         }
2420                 }
2421                 for (int i = 0; i < fontModule->fontsTypewriterCO->count(); ++i) {
2422                         if (fontModule->fontsTypewriterCO->itemText(i) == 
2423                                 toqstr(bp_.fontsTypewriter)) {
2424                                 fontModule->fontsTypewriterCO->setCurrentIndex(i);
2425                                 return;
2426                         }
2427                 }
2428         } else {
2429                 int n = findToken(tex_fonts_roman, bp_.fontsRoman);
2430                 if (n >= 0) {
2431                         fontModule->fontsRomanCO->setCurrentIndex(n);
2432                         romanChanged(n);
2433                 }
2434         
2435                 n = findToken(tex_fonts_sans, bp_.fontsSans);
2436                 if (n >= 0) {
2437                         fontModule->fontsSansCO->setCurrentIndex(n);
2438                         sansChanged(n);
2439                 }
2440         
2441                 n = findToken(tex_fonts_monospaced, bp_.fontsTypewriter);
2442                 if (n >= 0) {
2443                         fontModule->fontsTypewriterCO->setCurrentIndex(n);
2444                         ttChanged(n);
2445                 }
2446         }
2447
2448         if (!bp_.fontsCJK.empty())
2449                 fontModule->cjkFontLE->setText(
2450                         toqstr(bp_.fontsCJK));
2451         else
2452                 fontModule->cjkFontLE->setText(QString());
2453
2454         fontModule->fontScCB->setChecked(bp_.fontsSC);
2455         fontModule->fontOsfCB->setChecked(bp_.fontsOSF);
2456         fontModule->scaleSansSB->setValue(bp_.fontsSansScale);
2457         fontModule->scaleTypewriterSB->setValue(bp_.fontsTypewriterScale);
2458
2459         int nn = findToken(GuiDocument::fontfamilies, bp_.fontsDefaultFamily);
2460         if (nn >= 0)
2461                 fontModule->fontsDefaultCO->setCurrentIndex(nn);
2462
2463         // paper
2464         bool const extern_geometry =
2465                 documentClass().provides("geometry");
2466         int const psize = bp_.papersize;
2467         pageLayoutModule->papersizeCO->setCurrentIndex(psize);
2468         setCustomPapersize(!extern_geometry && psize == 1);
2469         pageLayoutModule->papersizeCO->setEnabled(!extern_geometry);
2470
2471         bool const landscape =
2472                 bp_.orientation == ORIENTATION_LANDSCAPE;
2473         pageLayoutModule->landscapeRB->setChecked(landscape);
2474         pageLayoutModule->portraitRB->setChecked(!landscape);
2475         pageLayoutModule->landscapeRB->setEnabled(!extern_geometry);
2476         pageLayoutModule->portraitRB->setEnabled(!extern_geometry);
2477
2478         pageLayoutModule->facingPagesCB->setChecked(
2479                 bp_.sides == TwoSides);
2480
2481         pageLayoutModule->backgroundPB->setStyleSheet(
2482                 colorButtonStyleSheet(rgb2qcolor(bp_.backgroundcolor)));
2483         set_backgroundcolor = bp_.backgroundcolor;
2484
2485         lengthToWidgets(pageLayoutModule->paperwidthLE,
2486                 pageLayoutModule->paperwidthUnitCO, bp_.paperwidth, defaultUnit);
2487         lengthToWidgets(pageLayoutModule->paperheightLE,
2488                 pageLayoutModule->paperheightUnitCO, bp_.paperheight, defaultUnit);
2489
2490         // margins
2491         Ui::MarginsUi * m = marginsModule;
2492
2493         setMargins(!bp_.use_geometry);
2494
2495         lengthToWidgets(m->topLE, m->topUnit,
2496                 bp_.topmargin, defaultUnit);
2497
2498         lengthToWidgets(m->bottomLE, m->bottomUnit,
2499                 bp_.bottommargin, defaultUnit);
2500
2501         lengthToWidgets(m->innerLE, m->innerUnit,
2502                 bp_.leftmargin, defaultUnit);
2503
2504         lengthToWidgets(m->outerLE, m->outerUnit,
2505                 bp_.rightmargin, defaultUnit);
2506
2507         lengthToWidgets(m->headheightLE, m->headheightUnit,
2508                 bp_.headheight, defaultUnit);
2509
2510         lengthToWidgets(m->headsepLE, m->headsepUnit,
2511                 bp_.headsep, defaultUnit);
2512
2513         lengthToWidgets(m->footskipLE, m->footskipUnit,
2514                 bp_.footskip, defaultUnit);
2515
2516         lengthToWidgets(m->columnsepLE, m->columnsepUnit,
2517                 bp_.columnsep, defaultUnit);
2518
2519         // branches
2520         updateUnknownBranches();
2521         branchesModule->update(bp_);
2522
2523         // PDF support
2524         PDFOptions const & pdf = bp_.pdfoptions();
2525         pdfSupportModule->use_hyperrefGB->setChecked(pdf.use_hyperref);
2526         pdfSupportModule->titleLE->setText(toqstr(pdf.title));
2527         pdfSupportModule->authorLE->setText(toqstr(pdf.author));
2528         pdfSupportModule->subjectLE->setText(toqstr(pdf.subject));
2529         pdfSupportModule->keywordsLE->setText(toqstr(pdf.keywords));
2530
2531         pdfSupportModule->bookmarksGB->setChecked(pdf.bookmarks);
2532         pdfSupportModule->bookmarksnumberedCB->setChecked(pdf.bookmarksnumbered);
2533         pdfSupportModule->bookmarksopenGB->setChecked(pdf.bookmarksopen);
2534
2535         pdfSupportModule->bookmarksopenlevelSB->setValue(pdf.bookmarksopenlevel);
2536
2537         pdfSupportModule->breaklinksCB->setChecked(pdf.breaklinks);
2538         pdfSupportModule->pdfborderCB->setChecked(pdf.pdfborder);
2539         pdfSupportModule->pdfusetitleCB->setChecked(pdf.pdfusetitle);
2540         pdfSupportModule->colorlinksCB->setChecked(pdf.colorlinks);
2541
2542         nn = findToken(backref_opts, pdf.backref);
2543         if (nn >= 0)
2544                 pdfSupportModule->backrefCO->setCurrentIndex(nn);
2545
2546         pdfSupportModule->fullscreenCB->setChecked
2547                 (pdf.pagemode == pdf.pagemode_fullscreen);
2548
2549         pdfSupportModule->optionsLE->setText(
2550                 toqstr(pdf.quoted_options));
2551
2552         // Make sure that the bc is in the INITIAL state
2553         if (bc().policy().buttonStatus(ButtonPolicy::RESTORE))
2554                 bc().restore();
2555
2556         // clear changed branches cache
2557         changedBranches_.clear();
2558 }
2559
2560
2561 void GuiDocument::saveDocDefault()
2562 {
2563         // we have to apply the params first
2564         applyView();
2565         saveAsDefault();
2566 }
2567
2568
2569 void GuiDocument::updateAvailableModules() 
2570 {
2571         modules_av_model_.clear();
2572         list<modInfoStruct> const & modInfoList = getModuleInfo();
2573         list<modInfoStruct>::const_iterator mit = modInfoList.begin();
2574         list<modInfoStruct>::const_iterator men = modInfoList.end();
2575         for (int i = 0; mit != men; ++mit, ++i)
2576                 modules_av_model_.insertRow(i, mit->name, mit->id, 
2577                                 mit->description);
2578 }
2579
2580
2581 void GuiDocument::updateSelectedModules() 
2582 {
2583         modules_sel_model_.clear();
2584         list<modInfoStruct> const selModList = getSelectedModules();
2585         list<modInfoStruct>::const_iterator mit = selModList.begin();
2586         list<modInfoStruct>::const_iterator men = selModList.end();
2587         for (int i = 0; mit != men; ++mit, ++i)
2588                 modules_sel_model_.insertRow(i, mit->name, mit->id, 
2589                                 mit->description);
2590 }
2591
2592
2593 void GuiDocument::updateContents()
2594 {
2595         // Nothing to do here as the document settings is not cursor dependant.
2596         return;
2597 }
2598
2599
2600 void GuiDocument::useClassDefaults()
2601 {
2602         if (applyPB->isEnabled()) {
2603                 int const ret = Alert::prompt(_("Unapplied changes"),
2604                                 _("Some changes in the dialog were not yet applied.\n"
2605                                   "If you do not apply now, they will be lost after this action."),
2606                                 1, 1, _("&Apply"), _("&Dismiss"));
2607                 if (ret == 0)
2608                         applyView();
2609         }
2610
2611         int idx = latexModule->classCO->currentIndex();
2612         string const classname = classes_model_.getIDString(idx);
2613         if (!bp_.setBaseClass(classname)) {
2614                 Alert::error(_("Error"), _("Unable to set document class."));
2615                 return;
2616         }
2617         bp_.useClassDefaults();
2618         paramsToDialog();
2619 }
2620
2621
2622 void GuiDocument::setLayoutComboByIDString(string const & idString)
2623 {
2624         int idx = classes_model_.findIDString(idString);
2625         if (idx < 0)
2626                 Alert::warning(_("Can't set layout!"), 
2627                         bformat(_("Unable to set layout for ID: %1$s"), from_utf8(idString)));
2628         else 
2629                 latexModule->classCO->setCurrentIndex(idx);
2630 }
2631
2632
2633 bool GuiDocument::isValid()
2634 {
2635         return validateListingsParameters().isEmpty()
2636                 && (textLayoutModule->skipCO->currentIndex() != 3
2637                         || !textLayoutModule->skipLE->text().isEmpty()
2638                         || textLayoutModule->indentRB->isChecked())
2639                 && (textLayoutModule->indentCO->currentIndex() != 1
2640                         || !textLayoutModule->indentLE->text().isEmpty()
2641                         || textLayoutModule->skipRB->isChecked());
2642 }
2643
2644
2645 char const * const GuiDocument::fontfamilies[5] = {
2646         "default", "rmdefault", "sfdefault", "ttdefault", ""
2647 };
2648
2649
2650 char const * GuiDocument::fontfamilies_gui[5] = {
2651         N_("Default"), N_("Roman"), N_("Sans Serif"), N_("Typewriter"), ""
2652 };
2653
2654
2655 bool GuiDocument::initialiseParams(string const &)
2656 {
2657         BufferView const * view = bufferview();
2658         if (!view) {
2659                 bp_ = BufferParams();
2660                 paramsToDialog();
2661                 return true;
2662         }
2663         bp_ = view->buffer().params();
2664         loadModuleInfo();
2665         updateAvailableModules();
2666         //FIXME It'd be nice to make sure here that the selected
2667         //modules are consistent: That required modules are actually
2668         //selected, and that we don't have conflicts. If so, we could
2669         //at least pop up a warning.
2670         paramsToDialog();
2671         return true;
2672 }
2673
2674
2675 void GuiDocument::clearParams()
2676 {
2677         bp_ = BufferParams();
2678 }
2679
2680
2681 BufferId GuiDocument::id() const
2682 {
2683         BufferView const * const view = bufferview();
2684         return view? &view->buffer() : 0;
2685 }
2686
2687
2688 list<GuiDocument::modInfoStruct> const & GuiDocument::getModuleInfo()
2689 {
2690         return moduleNames_;
2691 }
2692
2693
2694 list<GuiDocument::modInfoStruct> const 
2695                 GuiDocument::makeModuleInfo(LayoutModuleList const & mods)
2696 {
2697         LayoutModuleList::const_iterator it =  mods.begin();
2698         LayoutModuleList::const_iterator end = mods.end();
2699         list<modInfoStruct> mInfo;
2700         for (; it != end; ++it) {
2701                 modInfoStruct m;
2702                 m.id = *it;
2703                 LyXModule const * const mod = theModuleList[*it];
2704                 if (mod)
2705                         // FIXME Unicode
2706                         m.name = toqstr(translateIfPossible(from_utf8(mod->getName())));
2707                 else 
2708                         m.name = toqstr(*it) + toqstr(" (") + qt_("Not Found") + toqstr(")");
2709                 mInfo.push_back(m);
2710         }
2711         return mInfo;
2712 }
2713
2714
2715 list<GuiDocument::modInfoStruct> const GuiDocument::getSelectedModules()
2716 {
2717         return makeModuleInfo(params().getModules());
2718 }
2719
2720
2721 list<GuiDocument::modInfoStruct> const GuiDocument::getProvidedModules()
2722 {
2723         return makeModuleInfo(params().baseClass()->providedModules());
2724 }
2725
2726
2727 DocumentClass const & GuiDocument::documentClass() const
2728 {
2729         return bp_.documentClass();
2730 }
2731
2732
2733 static void dispatch_bufferparams(Dialog const & dialog,
2734         BufferParams const & bp, FuncCode lfun)
2735 {
2736         ostringstream ss;
2737         ss << "\\begin_header\n";
2738         bp.writeFile(ss);
2739         ss << "\\end_header\n";
2740         dialog.dispatch(FuncRequest(lfun, ss.str()));
2741 }
2742
2743
2744 void GuiDocument::dispatchParams()
2745 {
2746         // This must come first so that a language change is correctly noticed
2747         setLanguage();
2748
2749         // Apply the BufferParams. Note that this will set the base class
2750         // and then update the buffer's layout.
2751         dispatch_bufferparams(*this, params(), LFUN_BUFFER_PARAMS_APPLY);
2752
2753         if (!params().master.empty()) {
2754                 FileName const master_file = support::makeAbsPath(params().master,
2755                            support::onlyPath(buffer().absFileName()));
2756                 if (isLyXFilename(master_file.absFilename())) {
2757                         Buffer * master = checkAndLoadLyXFile(master_file);
2758                         if (master) {
2759                                 if (master->isChild(const_cast<Buffer *>(&buffer())))
2760                                         const_cast<Buffer &>(buffer()).setParent(master);
2761                                 else
2762                                         Alert::warning(_("Assigned master does not include this file"), 
2763                                                 bformat(_("You must include this file in the document\n"
2764                                                           "'%1$s' in order to use the master document\n"
2765                                                           "feature."), from_utf8(params().master)));
2766                         } else
2767                                 Alert::warning(_("Could not load master"), 
2768                                                 bformat(_("The master document '%1$s'\n"
2769                                                            "could not be loaded."),
2770                                                            from_utf8(params().master)));
2771                 }
2772         }
2773
2774         // Generate the colours requested by each new branch.
2775         BranchList & branchlist = params().branchlist();
2776         if (!branchlist.empty()) {
2777                 BranchList::const_iterator it = branchlist.begin();
2778                 BranchList::const_iterator const end = branchlist.end();
2779                 for (; it != end; ++it) {
2780                         docstring const & current_branch = it->branch();
2781                         Branch const * branch = branchlist.find(current_branch);
2782                         string const x11hexname = X11hexname(branch->color());
2783                         // display the new color
2784                         docstring const str = current_branch + ' ' + from_ascii(x11hexname);
2785                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
2786                 }
2787
2788                 // Open insets of selected branches, close deselected ones
2789                 dispatch(FuncRequest(LFUN_ALL_INSETS_TOGGLE,
2790                         "assign branch"));
2791         }
2792         // rename branches in the document
2793         executeBranchRenaming();
2794         // and clear changed branches cache
2795         changedBranches_.clear();
2796         
2797         // Generate the colours requested by indices.
2798         IndicesList & indiceslist = params().indiceslist();
2799         if (!indiceslist.empty()) {
2800                 IndicesList::const_iterator it = indiceslist.begin();
2801                 IndicesList::const_iterator const end = indiceslist.end();
2802                 for (; it != end; ++it) {
2803                         docstring const & current_index = it->shortcut();
2804                         Index const * index = indiceslist.findShortcut(current_index);
2805                         string const x11hexname = X11hexname(index->color());
2806                         // display the new color
2807                         docstring const str = current_index + ' ' + from_ascii(x11hexname);
2808                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
2809                 }
2810         }
2811         // FIXME: If we used an LFUN, we would not need those two lines:
2812         BufferView * bv = const_cast<BufferView *>(bufferview());
2813         bv->processUpdateFlags(Update::Force | Update::FitCursor);
2814 }
2815
2816
2817 void GuiDocument::setLanguage() const
2818 {
2819         Language const * const newL = bp_.language;
2820         if (buffer().params().language == newL)
2821                 return;
2822
2823         string const & lang_name = newL->lang();
2824         dispatch(FuncRequest(LFUN_BUFFER_LANGUAGE, lang_name));
2825 }
2826
2827
2828 void GuiDocument::saveAsDefault() const
2829 {
2830         dispatch_bufferparams(*this, params(), LFUN_BUFFER_SAVE_AS_DEFAULT);
2831 }
2832
2833
2834 bool GuiDocument::isFontAvailable(string const & font) const
2835 {
2836         if (font == "default" || font == "cmr"
2837             || font == "cmss" || font == "cmtt")
2838                 // these are standard
2839                 return true;
2840         if (font == "lmodern" || font == "lmss" || font == "lmtt")
2841                 return LaTeXFeatures::isAvailable("lmodern");
2842         if (font == "times" || font == "palatino"
2843                  || font == "helvet" || font == "courier")
2844                 return LaTeXFeatures::isAvailable("psnfss");
2845         if (font == "cmbr" || font == "cmtl")
2846                 return LaTeXFeatures::isAvailable("cmbright");
2847         if (font == "utopia")
2848                 return LaTeXFeatures::isAvailable("utopia")
2849                         || LaTeXFeatures::isAvailable("fourier");
2850         if (font == "beraserif" || font == "berasans"
2851                 || font == "beramono")
2852                 return LaTeXFeatures::isAvailable("bera");
2853         return LaTeXFeatures::isAvailable(font);
2854 }
2855
2856
2857 bool GuiDocument::providesOSF(string const & font) const
2858 {
2859         if (outputModule->xetexCB->isChecked())
2860                 // FIXME: we should check if the fonts really
2861                 // have OSF support. But how?
2862                 return true;
2863         if (font == "cmr")
2864                 return isFontAvailable("eco");
2865         if (font == "palatino")
2866                 return isFontAvailable("mathpazo");
2867         return false;
2868 }
2869
2870
2871 bool GuiDocument::providesSC(string const & font) const
2872 {
2873         if (outputModule->xetexCB->isChecked())
2874                 return false;
2875         if (font == "palatino")
2876                 return isFontAvailable("mathpazo");
2877         if (font == "utopia")
2878                 return isFontAvailable("fourier");
2879         return false;
2880 }
2881
2882
2883 bool GuiDocument::providesScale(string const & font) const
2884 {
2885         if (outputModule->xetexCB->isChecked())
2886                 return true;
2887         return font == "helvet" || font == "luximono"
2888                 || font == "berasans"  || font == "beramono";
2889 }
2890
2891
2892 void GuiDocument::loadModuleInfo()
2893 {
2894         moduleNames_.clear();
2895         LyXModuleList::const_iterator it  = theModuleList.begin();
2896         LyXModuleList::const_iterator end = theModuleList.end();
2897         for (; it != end; ++it) {
2898                 modInfoStruct m;
2899                 m.id = it->getID();
2900                 // FIXME Unicode
2901                 m.name = toqstr(translateIfPossible(from_utf8(it->getName())));
2902                 // this is supposed to give us the first sentence of the description
2903                 // FIXME Unicode
2904                 QString desc =
2905                         toqstr(translateIfPossible(from_utf8(it->getDescription())));
2906                 int const pos = desc.indexOf(".");
2907                 if (pos > 0)
2908                         desc.truncate(pos + 1);
2909                 m.description = desc;
2910                 moduleNames_.push_back(m);
2911         }
2912 }
2913
2914
2915 void GuiDocument::updateUnknownBranches()
2916 {
2917         list<docstring> used_branches;
2918         buffer().getUsedBranches(used_branches);
2919         list<docstring>::const_iterator it = used_branches.begin();
2920         QStringList unknown_branches;
2921         for (; it != used_branches.end() ; ++it) {
2922                 if (!buffer().params().branchlist().find(*it))
2923                         unknown_branches.append(toqstr(*it));
2924         }
2925         branchesModule->setUnknownBranches(unknown_branches);
2926 }
2927
2928
2929 void GuiDocument::branchesRename(docstring const & oldname, docstring const & newname)
2930 {
2931         map<docstring, docstring>::iterator it = changedBranches_.begin();
2932         for (; it != changedBranches_.end() ; ++it) {
2933                 if (it->second == oldname) {
2934                         // branch has already been renamed
2935                         it->second = newname;
2936                         return;
2937                 }
2938         }
2939         // store new name
2940         changedBranches_[oldname] = newname;
2941 }
2942
2943
2944 void GuiDocument::executeBranchRenaming() const
2945 {
2946         map<docstring, docstring>::const_iterator it = changedBranches_.begin();
2947         for (; it != changedBranches_.end() ; ++it) {
2948                 docstring const arg = '"' + it->first + '"' + " " + '"' + it->second + '"';
2949                 dispatch(FuncRequest(LFUN_BRANCHES_RENAME, arg));
2950         }
2951 }
2952
2953
2954 Dialog * createGuiDocument(GuiView & lv) { return new GuiDocument(lv); }
2955
2956
2957 } // namespace frontend
2958 } // namespace lyx
2959
2960 #include "moc_GuiDocument.cpp"