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