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