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