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