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