]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiDocument.cpp
Finally make the label color of multiple index entries work.
[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(setCustomPapersize(int)));
662         connect(pageLayoutModule->papersizeCO, SIGNAL(activated(int)),
663                 this, SLOT(setCustomPapersize(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::setCustomPapersize(int papersize)
1158 {
1159         bool const custom = (papersize == 1);
1160
1161         pageLayoutModule->paperwidthL->setEnabled(custom);
1162         pageLayoutModule->paperwidthLE->setEnabled(custom);
1163         pageLayoutModule->paperwidthUnitCO->setEnabled(custom);
1164         pageLayoutModule->paperheightL->setEnabled(custom);
1165         pageLayoutModule->paperheightLE->setEnabled(custom);
1166         pageLayoutModule->paperheightLE->setFocus();
1167         pageLayoutModule->paperheightUnitCO->setEnabled(custom);
1168 }
1169
1170
1171 void GuiDocument::setColSep()
1172 {
1173         setCustomMargins(marginsModule->marginCB->checkState() == Qt::Checked);
1174 }
1175
1176
1177 void GuiDocument::setCustomMargins(bool custom)
1178 {
1179         marginsModule->topL->setEnabled(!custom);
1180         marginsModule->topLE->setEnabled(!custom);
1181         marginsModule->topUnit->setEnabled(!custom);
1182
1183         marginsModule->bottomL->setEnabled(!custom);
1184         marginsModule->bottomLE->setEnabled(!custom);
1185         marginsModule->bottomUnit->setEnabled(!custom);
1186
1187         marginsModule->innerL->setEnabled(!custom);
1188         marginsModule->innerLE->setEnabled(!custom);
1189         marginsModule->innerUnit->setEnabled(!custom);
1190
1191         marginsModule->outerL->setEnabled(!custom);
1192         marginsModule->outerLE->setEnabled(!custom);
1193         marginsModule->outerUnit->setEnabled(!custom);
1194
1195         marginsModule->headheightL->setEnabled(!custom);
1196         marginsModule->headheightLE->setEnabled(!custom);
1197         marginsModule->headheightUnit->setEnabled(!custom);
1198
1199         marginsModule->headsepL->setEnabled(!custom);
1200         marginsModule->headsepLE->setEnabled(!custom);
1201         marginsModule->headsepUnit->setEnabled(!custom);
1202
1203         marginsModule->footskipL->setEnabled(!custom);
1204         marginsModule->footskipLE->setEnabled(!custom);
1205         marginsModule->footskipUnit->setEnabled(!custom);
1206
1207         bool const enableColSep = !custom && 
1208                         textLayoutModule->twoColumnCB->checkState() == Qt::Checked;
1209         marginsModule->columnsepL->setEnabled(enableColSep);
1210         marginsModule->columnsepLE->setEnabled(enableColSep);
1211         marginsModule->columnsepUnit->setEnabled(enableColSep);
1212 }
1213
1214 void GuiDocument::changeBackgroundColor()
1215 {
1216         QColor const & newColor = QColorDialog::getColor(
1217                 rgb2qcolor(set_backgroundcolor), asQWidget());
1218         if (!newColor.isValid())
1219                 return;
1220         // set the button color
1221         pageLayoutModule->backgroundPB->setStyleSheet(
1222                 colorButtonStyleSheet(newColor));
1223         // save color
1224         set_backgroundcolor = rgbFromHexName(fromqstr(newColor.name()));
1225         changed();
1226 }
1227
1228
1229 void GuiDocument::deleteBackgroundColor()
1230 {
1231         // set the button color back to white
1232         pageLayoutModule->backgroundPB->setStyleSheet(
1233                 colorButtonStyleSheet(QColor(Qt::white)));
1234         // save white as the set color
1235         set_backgroundcolor = rgbFromHexName("#ffffff");
1236         changed();
1237 }
1238
1239
1240 void GuiDocument::xetexChanged(bool xetex)
1241 {
1242         updateFontlist();
1243         updateDefaultFormat();
1244         langModule->encodingCO->setEnabled(!xetex &&
1245                 !langModule->defaultencodingRB->isChecked());
1246         langModule->defaultencodingRB->setEnabled(!xetex);
1247         langModule->otherencodingRB->setEnabled(!xetex);
1248
1249         fontModule->fontsDefaultCO->setEnabled(!xetex);
1250         fontModule->fontsDefaultLA->setEnabled(!xetex);
1251         fontModule->cjkFontLE->setEnabled(!xetex);
1252         fontModule->cjkFontLA->setEnabled(!xetex);
1253         string font;
1254         if (!xetex)
1255                 font = tex_fonts_sans[fontModule->fontsSansCO->currentIndex()];
1256         bool scaleable = providesScale(font);
1257         fontModule->scaleSansSB->setEnabled(scaleable);
1258         fontModule->scaleSansLA->setEnabled(scaleable);
1259         if (!xetex)
1260                 font = tex_fonts_monospaced[fontModule->fontsTypewriterCO->currentIndex()];
1261         scaleable = providesScale(font);
1262         fontModule->scaleTypewriterSB->setEnabled(scaleable);
1263         fontModule->scaleTypewriterLA->setEnabled(scaleable);
1264         if (!xetex)
1265                 font = tex_fonts_roman[fontModule->fontsRomanCO->currentIndex()];
1266         fontModule->fontScCB->setEnabled(providesSC(font));
1267         fontModule->fontOsfCB->setEnabled(providesOSF(font));
1268 }
1269
1270
1271 void GuiDocument::updateFontsize(string const & items, string const & sel)
1272 {
1273         fontModule->fontsizeCO->clear();
1274         fontModule->fontsizeCO->addItem(qt_("Default"));
1275
1276         for (int n = 0; !token(items,'|',n).empty(); ++n)
1277                 fontModule->fontsizeCO->
1278                         addItem(toqstr(token(items,'|',n)));
1279
1280         for (int n = 0; n < fontModule->fontsizeCO->count(); ++n) {
1281                 if (fromqstr(fontModule->fontsizeCO->itemText(n)) == sel) {
1282                         fontModule->fontsizeCO->setCurrentIndex(n);
1283                         break;
1284                 }
1285         }
1286 }
1287
1288
1289 void GuiDocument::updateFontlist()
1290 {
1291         fontModule->fontsRomanCO->clear();
1292         fontModule->fontsSansCO->clear();
1293         fontModule->fontsTypewriterCO->clear();
1294
1295         // With XeTeX, we have access to all system fonts, but not the LaTeX fonts
1296         if (outputModule->xetexCB->isChecked()) {
1297                 fontModule->fontsRomanCO->addItem(qt_("Default"));
1298                 fontModule->fontsSansCO->addItem(qt_("Default"));
1299                 fontModule->fontsTypewriterCO->addItem(qt_("Default"));
1300         
1301                 QFontDatabase fontdb;
1302                 QStringList families(fontdb.families());
1303                 for (QStringList::Iterator it = families.begin(); it != families.end(); ++it) {
1304                         fontModule->fontsRomanCO->addItem(*it);
1305                         fontModule->fontsSansCO->addItem(*it);
1306                         fontModule->fontsTypewriterCO->addItem(*it);
1307                 }
1308                 return;
1309         }
1310
1311         for (int n = 0; tex_fonts_roman[n][0]; ++n) {
1312                 QString font = qt_(tex_fonts_roman_gui[n]);
1313                 if (!isFontAvailable(tex_fonts_roman[n]))
1314                         font += qt_(" (not installed)");
1315                 fontModule->fontsRomanCO->addItem(font);
1316         }
1317         for (int n = 0; tex_fonts_sans[n][0]; ++n) {
1318                 QString font = qt_(tex_fonts_sans_gui[n]);
1319                 if (!isFontAvailable(tex_fonts_sans[n]))
1320                         font += qt_(" (not installed)");
1321                 fontModule->fontsSansCO->addItem(font);
1322         }
1323         for (int n = 0; tex_fonts_monospaced[n][0]; ++n) {
1324                 QString font = qt_(tex_fonts_monospaced_gui[n]);
1325                 if (!isFontAvailable(tex_fonts_monospaced[n]))
1326                         font += qt_(" (not installed)");
1327                 fontModule->fontsTypewriterCO->addItem(font);
1328         }
1329 }
1330
1331
1332 void GuiDocument::romanChanged(int item)
1333 {
1334         if (outputModule->xetexCB->isChecked())
1335                 return;
1336         string const font = tex_fonts_roman[item];
1337         fontModule->fontScCB->setEnabled(providesSC(font));
1338         fontModule->fontOsfCB->setEnabled(providesOSF(font));
1339 }
1340
1341
1342 void GuiDocument::sansChanged(int item)
1343 {
1344         if (outputModule->xetexCB->isChecked())
1345                 return;
1346         string const font = tex_fonts_sans[item];
1347         bool scaleable = providesScale(font);
1348         fontModule->scaleSansSB->setEnabled(scaleable);
1349         fontModule->scaleSansLA->setEnabled(scaleable);
1350 }
1351
1352
1353 void GuiDocument::ttChanged(int item)
1354 {
1355         if (outputModule->xetexCB->isChecked())
1356                 return;
1357         string const font = tex_fonts_monospaced[item];
1358         bool scaleable = providesScale(font);
1359         fontModule->scaleTypewriterSB->setEnabled(scaleable);
1360         fontModule->scaleTypewriterLA->setEnabled(scaleable);
1361 }
1362
1363
1364 void GuiDocument::updatePagestyle(string const & items, string const & sel)
1365 {
1366         pagestyles.clear();
1367         pageLayoutModule->pagestyleCO->clear();
1368         pageLayoutModule->pagestyleCO->addItem(qt_("Default"));
1369
1370         for (int n = 0; !token(items, '|', n).empty(); ++n) {
1371                 string style = token(items, '|', n);
1372                 QString style_gui = qt_(style);
1373                 pagestyles.push_back(pair<string, QString>(style, style_gui));
1374                 pageLayoutModule->pagestyleCO->addItem(style_gui);
1375         }
1376
1377         if (sel == "default") {
1378                 pageLayoutModule->pagestyleCO->setCurrentIndex(0);
1379                 return;
1380         }
1381
1382         int nn = 0;
1383
1384         for (size_t i = 0; i < pagestyles.size(); ++i)
1385                 if (pagestyles[i].first == sel)
1386                         nn = pageLayoutModule->pagestyleCO->findText(pagestyles[i].second);
1387
1388         if (nn > 0)
1389                 pageLayoutModule->pagestyleCO->setCurrentIndex(nn);
1390 }
1391
1392
1393 void GuiDocument::browseLayout()
1394 {
1395         QString const label1 = qt_("Layouts|#o#O");
1396         QString const dir1 = toqstr(lyxrc.document_path);
1397         QStringList const filter(qt_("LyX Layout (*.layout)"));
1398         QString file = browseRelFile(QString(), bufferFilepath(),
1399                 qt_("Local layout file"), filter, false,
1400                 label1, dir1);
1401
1402         if (!file.endsWith(".layout"))
1403                 return;
1404
1405         FileName layoutFile = support::makeAbsPath(fromqstr(file),
1406                 fromqstr(bufferFilepath()));
1407         
1408         int const ret = Alert::prompt(_("Local layout file"),
1409                 _("The layout file you have selected is a local layout\n"
1410                   "file, not one in the system or user directory. Your\n"
1411                   "document may not work with this layout if you do not\n"
1412                   "keep the layout file in the document directory."),
1413                   1, 1, _("&Set Layout"), _("&Cancel"));
1414         if (ret == 1)
1415                 return;
1416
1417         // load the layout file
1418         LayoutFileList & bcl = LayoutFileList::get();
1419         string classname = layoutFile.onlyFileName();
1420         // this will update an existing layout if that layout has been loaded before.
1421         LayoutFileIndex name = bcl.addLocalLayout(
1422                 classname.substr(0, classname.size() - 7),
1423                 layoutFile.onlyPath().absFilename());
1424
1425         if (name.empty()) {
1426                 Alert::error(_("Error"),
1427                         _("Unable to read local layout file."));                
1428                 return;
1429         }
1430
1431         // do not trigger classChanged if there is no change.
1432         if (latexModule->classCO->currentText() == toqstr(name))
1433                 return;
1434                 
1435         // add to combo box
1436         int idx = latexModule->classCO->findText(toqstr(name));
1437         if (idx == -1) {
1438                 classes_model_.insertRow(0, toqstr(name), name);
1439                 latexModule->classCO->setCurrentIndex(0);
1440         } else
1441                 latexModule->classCO->setCurrentIndex(idx);
1442         
1443         classChanged();
1444 }
1445
1446
1447 void GuiDocument::browseMaster()
1448 {
1449         QString const title = qt_("Select master document");
1450         QString const dir1 = toqstr(lyxrc.document_path);
1451         QString const old = latexModule->childDocLE->text();
1452         QString const docpath = toqstr(support::onlyPath(buffer().absFileName()));
1453         QStringList const filter(qt_("LyX Files (*.lyx)"));
1454         QString file = browseRelFile(old, docpath, title, filter, false,
1455                 qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
1456
1457         latexModule->childDocLE->setText(file);
1458 }
1459
1460
1461 void GuiDocument::classChanged()
1462 {
1463         int idx = latexModule->classCO->currentIndex();
1464         if (idx < 0) 
1465                 return;
1466         string const classname = classes_model_.getIDString(idx);
1467
1468         // check whether the selected modules have changed.
1469         bool modules_changed = false;
1470         unsigned int const srows = selectedModel()->rowCount();
1471         if (srows != bp_.getModules().size())
1472                 modules_changed = true;
1473         else {
1474                 list<string>::const_iterator mit = bp_.getModules().begin();
1475                 list<string>::const_iterator men = bp_.getModules().end();
1476                 for (unsigned int i = 0; i < srows && mit != men; ++i, ++mit)
1477                         if (selectedModel()->getIDString(i) != *mit) {
1478                                 modules_changed = true;
1479                                 break;
1480                         }
1481         }
1482
1483         if (modules_changed || lyxrc.auto_reset_options) {
1484                 if (applyPB->isEnabled()) {
1485                         int const ret = Alert::prompt(_("Unapplied changes"),
1486                                         _("Some changes in the dialog were not yet applied.\n"
1487                                         "If you do not apply now, they will be lost after this action."),
1488                                         1, 1, _("&Apply"), _("&Dismiss"));
1489                         if (ret == 0)
1490                                 applyView();
1491                 }
1492         }
1493
1494         // We load the TextClass as soon as it is selected. This is
1495         // necessary so that other options in the dialog can be updated
1496         // according to the new class. Note, however, that, if you use 
1497         // the scroll wheel when sitting on the combo box, we'll load a 
1498         // lot of TextClass objects very quickly....
1499         if (!bp_.setBaseClass(classname)) {
1500                 Alert::error(_("Error"), _("Unable to set document class."));
1501                 return;
1502         }
1503         if (lyxrc.auto_reset_options)
1504                 bp_.useClassDefaults();
1505
1506         // With the introduction of modules came a distinction between the base 
1507         // class and the document class. The former corresponds to the main layout 
1508         // file; the latter is that plus the modules (or the document-specific layout,
1509         // or  whatever else there could be). Our parameters come from the document 
1510         // class. So when we set the base class, we also need to recreate the document 
1511         // class. Otherwise, we still have the old one.
1512         bp_.makeDocumentClass();
1513         paramsToDialog();
1514 }
1515
1516
1517 void GuiDocument::bibtexChanged(int n)
1518 {
1519         biblioModule->bibtexOptionsED->setEnabled(n != 0);
1520         changed();
1521 }
1522
1523
1524 namespace {
1525         // This is an insanely complicated attempt to make this sort of thing
1526         // work with RTL languages.
1527         docstring formatStrVec(vector<string> const & v, docstring const & s) 
1528         {
1529                 //this mess formats the list as "v[0], v[1], ..., [s] v[n]"
1530                 if (v.size() == 0)
1531                         return docstring();
1532                 if (v.size() == 1) 
1533                         return from_utf8(v[0]);
1534                 if (v.size() == 2) {
1535                         docstring retval = _("%1$s and %2$s");
1536                         retval = subst(retval, _("and"), s);
1537                         return bformat(retval, from_utf8(v[0]), from_utf8(v[1]));
1538                 }
1539                 // The idea here is to format all but the last two items...
1540                 int const vSize = v.size();
1541                 docstring t2 = _("%1$s, %2$s");
1542                 docstring retval = from_utf8(v[0]);
1543                 for (int i = 1; i < vSize - 2; ++i)
1544                         retval = bformat(t2, retval, from_utf8(v[i])); 
1545                 //...and then to  plug them, and the last two, into this schema
1546                 docstring t = _("%1$s, %2$s, and %3$s");
1547                 t = subst(t, _("and"), s);
1548                 return bformat(t, retval, from_utf8(v[vSize - 2]), from_utf8(v[vSize - 1]));
1549         }
1550         
1551         vector<string> idsToNames(vector<string> const & idList)
1552         {
1553                 vector<string> retval;
1554                 vector<string>::const_iterator it  = idList.begin();
1555                 vector<string>::const_iterator end = idList.end();
1556                 for (; it != end; ++it) {
1557                         LyXModule const * const mod = moduleList[*it];
1558                         if (!mod)
1559                                 retval.push_back(*it + " (Unavailable)");
1560                         else
1561                                 retval.push_back(mod->getName());
1562                 }
1563                 return retval;
1564         }
1565 }
1566
1567
1568 void GuiDocument::modulesToParams(BufferParams & bp)
1569 {
1570         // update list of loaded modules
1571         bp.clearLayoutModules();
1572         int const srows = modules_sel_model_.rowCount();
1573         for (int i = 0; i < srows; ++i)
1574                 bp.addLayoutModule(modules_sel_model_.getIDString(i));
1575
1576         // update the list of removed modules
1577         bp.clearRemovedModules();
1578         LayoutModuleList const & reqmods = bp.baseClass()->defaultModules();
1579         list<string>::const_iterator rit = reqmods.begin();
1580         list<string>::const_iterator ren = reqmods.end();
1581
1582         // check each of the default modules
1583         for (; rit != ren; rit++) {
1584                 list<string>::const_iterator mit = bp.getModules().begin();
1585                 list<string>::const_iterator men = bp.getModules().end();
1586                 bool found = false;
1587                 for (; mit != men; mit++) {
1588                         if (*rit == *mit) {
1589                                 found = true;
1590                                 break;
1591                         }
1592                 }
1593                 if (!found) {
1594                         // the module isn't present so must have been removed by the user
1595                         bp.addRemovedModule(*rit);
1596                 }
1597         }
1598 }
1599
1600 void GuiDocument::modulesChanged()
1601 {
1602         modulesToParams(bp_);
1603         bp_.makeDocumentClass();
1604         paramsToDialog();
1605 }
1606
1607
1608 void GuiDocument::updateModuleInfo()
1609 {
1610         selectionManager->update();
1611         
1612         //Module description
1613         bool const focus_on_selected = selectionManager->selectedFocused();
1614         QListView const * const lv = 
1615                         focus_on_selected ? modulesModule->selectedLV : modulesModule->availableLV;
1616         if (lv->selectionModel()->selectedIndexes().isEmpty()) {
1617                 modulesModule->infoML->document()->clear();
1618                 return;
1619         }
1620         QModelIndex const & idx = lv->selectionModel()->currentIndex();
1621         GuiIdListModel const & id_model = 
1622                         focus_on_selected  ? modules_sel_model_ : modules_av_model_;
1623         string const modName = id_model.getIDString(idx.row());
1624         docstring desc = getModuleDescription(modName);
1625
1626         LayoutModuleList const & provmods = bp_.baseClass()->providedModules();
1627         if (std::find(provmods.begin(), provmods.end(), modName) != provmods.end()) {
1628                 if (!desc.empty())
1629                         desc += "\n";
1630                 desc += _("Module provided by document class.");
1631         }
1632
1633         vector<string> pkglist = getPackageList(modName);
1634         docstring pkgdesc = formatStrVec(pkglist, _("and"));
1635         if (!pkgdesc.empty()) {
1636                 if (!desc.empty())
1637                         desc += "\n";
1638                 desc += bformat(_("Package(s) required: %1$s."), pkgdesc);
1639         }
1640
1641         pkglist = getRequiredList(modName);
1642         if (!pkglist.empty()) {
1643                 vector<string> const reqdescs = idsToNames(pkglist);
1644                 pkgdesc = formatStrVec(reqdescs, _("or"));
1645                 if (!desc.empty())
1646                         desc += "\n";
1647                 desc += bformat(_("Module required: %1$s."), pkgdesc);
1648         }
1649
1650         pkglist = getExcludedList(modName);
1651         if (!pkglist.empty()) {
1652                 vector<string> const reqdescs = idsToNames(pkglist);
1653                 pkgdesc = formatStrVec(reqdescs, _( "and"));
1654                 if (!desc.empty())
1655                         desc += "\n";
1656                 desc += bformat(_("Modules excluded: %1$s."), pkgdesc);
1657         }
1658
1659         if (!isModuleAvailable(modName)) {
1660                 if (!desc.empty())
1661                         desc += "\n";
1662                 desc += _("WARNING: Some required packages are unavailable!");
1663         }
1664
1665         modulesModule->infoML->document()->setPlainText(toqstr(desc));
1666 }
1667
1668
1669 void GuiDocument::updateNumbering()
1670 {
1671         DocumentClass const & tclass = documentClass();
1672
1673         numberingModule->tocTW->setUpdatesEnabled(false);
1674         numberingModule->tocTW->clear();
1675
1676         int const depth = numberingModule->depthSL->value();
1677         int const toc = numberingModule->tocSL->value();
1678         QString const no = qt_("No");
1679         QString const yes = qt_("Yes");
1680         QTreeWidgetItem * item = 0;
1681
1682         DocumentClass::const_iterator lit = tclass.begin();
1683         DocumentClass::const_iterator len = tclass.end();
1684         for (; lit != len; ++lit) {
1685                 int const toclevel = lit->toclevel;
1686                 if (toclevel != Layout::NOT_IN_TOC && lit->labeltype == LABEL_COUNTER) {
1687                         item = new QTreeWidgetItem(numberingModule->tocTW);
1688                         item->setText(0, toqstr(translateIfPossible(lit->name())));
1689                         item->setText(1, (toclevel <= depth) ? yes : no);
1690                         item->setText(2, (toclevel <= toc) ? yes : no);
1691                 }
1692         }
1693
1694         numberingModule->tocTW->setUpdatesEnabled(true);
1695         numberingModule->tocTW->update();
1696 }
1697
1698
1699 void GuiDocument::updateDefaultFormat()
1700 {
1701         // make a copy in order to consider unapplied changes
1702         Buffer * tmpbuf = const_cast<Buffer *>(&buffer());
1703         tmpbuf->params().useXetex = outputModule->xetexCB->isChecked();
1704         int idx = latexModule->classCO->currentIndex();
1705         if (idx >= 0) {
1706                 string const classname = classes_model_.getIDString(idx);
1707                 tmpbuf->params().setBaseClass(classname);
1708                 tmpbuf->params().makeDocumentClass();
1709         }
1710         outputModule->defaultFormatCO->blockSignals(true);
1711         outputModule->defaultFormatCO->clear();
1712         outputModule->defaultFormatCO->addItem(qt_("Default"),
1713                                 QVariant(QString("default")));
1714         typedef vector<Format const *> Formats;
1715         Formats formats = tmpbuf->exportableFormats(true);
1716         Formats::const_iterator cit = formats.begin();
1717         Formats::const_iterator end = formats.end();
1718         for (; cit != end; ++cit)
1719                 outputModule->defaultFormatCO->addItem(qt_((*cit)->prettyname()),
1720                                 QVariant(toqstr((*cit)->name())));
1721         outputModule->defaultFormatCO->blockSignals(false);
1722 }
1723
1724
1725 void GuiDocument::applyView()
1726 {
1727         // preamble
1728         preambleModule->apply(bp_);
1729
1730         // biblio
1731         bp_.setCiteEngine(ENGINE_BASIC);
1732
1733         if (biblioModule->citeNatbibRB->isChecked()) {
1734                 bool const use_numerical_citations =
1735                         biblioModule->citeStyleCO->currentIndex();
1736                 if (use_numerical_citations)
1737                         bp_.setCiteEngine(ENGINE_NATBIB_NUMERICAL);
1738                 else
1739                         bp_.setCiteEngine(ENGINE_NATBIB_AUTHORYEAR);
1740
1741         } else if (biblioModule->citeJurabibRB->isChecked())
1742                 bp_.setCiteEngine(ENGINE_JURABIB);
1743
1744         bp_.use_bibtopic =
1745                 biblioModule->bibtopicCB->isChecked();
1746
1747         string const bibtex_command =
1748                 fromqstr(biblioModule->bibtexCO->itemData(
1749                         biblioModule->bibtexCO->currentIndex()).toString());
1750         string const bibtex_options =
1751                 fromqstr(biblioModule->bibtexOptionsED->text());
1752         if (bibtex_command == "default" || bibtex_options.empty())
1753                 bp_.bibtex_command = bibtex_command;
1754         else
1755                 bp_.bibtex_command = bibtex_command + " " + bibtex_options;
1756
1757         // Indices
1758         indicesModule->apply(bp_);
1759
1760         // language & quotes
1761         if (langModule->defaultencodingRB->isChecked()) {
1762                 bp_.inputenc = "auto";
1763         } else {
1764                 int i = langModule->encodingCO->currentIndex();
1765                 if (i == 0)
1766                         bp_.inputenc = "default";
1767                 else {
1768                         QString const enc_gui =
1769                                 langModule->encodingCO->currentText();
1770                         Encodings::const_iterator it = encodings.begin();
1771                         Encodings::const_iterator const end = encodings.end();
1772                         bool found = false;
1773                         for (; it != end; ++it) {
1774                                 if (qt_(it->guiName()) == enc_gui) {
1775                                         bp_.inputenc = it->latexName();
1776                                         found = true;
1777                                         break;
1778                                 }
1779                         }
1780                         if (!found) {
1781                                 // should not happen
1782                                 lyxerr << "GuiDocument::apply: Unknown encoding! Resetting to default" << endl;
1783                                 bp_.inputenc = "default";
1784                         }
1785                 }
1786         }
1787
1788         InsetQuotes::QuoteLanguage lga = InsetQuotes::EnglishQuotes;
1789         switch (langModule->quoteStyleCO->currentIndex()) {
1790         case 0:
1791                 lga = InsetQuotes::EnglishQuotes;
1792                 break;
1793         case 1:
1794                 lga = InsetQuotes::SwedishQuotes;
1795                 break;
1796         case 2:
1797                 lga = InsetQuotes::GermanQuotes;
1798                 break;
1799         case 3:
1800                 lga = InsetQuotes::PolishQuotes;
1801                 break;
1802         case 4:
1803                 lga = InsetQuotes::FrenchQuotes;
1804                 break;
1805         case 5:
1806                 lga = InsetQuotes::DanishQuotes;
1807                 break;
1808         }
1809         bp_.quotes_language = lga;
1810
1811         QString const lang = langModule->languageCO->itemData(
1812                 langModule->languageCO->currentIndex()).toString();
1813         bp_.language = languages.getLanguage(fromqstr(lang));
1814
1815         // numbering
1816         if (bp_.documentClass().hasTocLevels()) {
1817                 bp_.tocdepth = numberingModule->tocSL->value();
1818                 bp_.secnumdepth = numberingModule->depthSL->value();
1819         }
1820
1821         // bullets
1822         bp_.user_defined_bullet(0) = bulletsModule->bullet(0);
1823         bp_.user_defined_bullet(1) = bulletsModule->bullet(1);
1824         bp_.user_defined_bullet(2) = bulletsModule->bullet(2);
1825         bp_.user_defined_bullet(3) = bulletsModule->bullet(3);
1826
1827         // packages
1828         bp_.graphicsDriver =
1829                 tex_graphics[latexModule->psdriverCO->currentIndex()];
1830         
1831         // text layout
1832         int idx = latexModule->classCO->currentIndex();
1833         if (idx >= 0) {
1834                 string const classname = classes_model_.getIDString(idx);
1835                 bp_.setBaseClass(classname);
1836         }
1837
1838         // Modules
1839         modulesToParams(bp_);
1840
1841         if (mathsModule->amsautoCB->isChecked()) {
1842                 bp_.use_amsmath = BufferParams::package_auto;
1843         } else {
1844                 if (mathsModule->amsCB->isChecked())
1845                         bp_.use_amsmath = BufferParams::package_on;
1846                 else
1847                         bp_.use_amsmath = BufferParams::package_off;
1848         }
1849
1850         if (mathsModule->esintautoCB->isChecked())
1851                 bp_.use_esint = BufferParams::package_auto;
1852         else {
1853                 if (mathsModule->esintCB->isChecked())
1854                         bp_.use_esint = BufferParams::package_on;
1855                 else
1856                         bp_.use_esint = BufferParams::package_off;
1857         }
1858
1859         if (pageLayoutModule->pagestyleCO->currentIndex() == 0)
1860                 bp_.pagestyle = "default";
1861         else {
1862                 QString style_gui = pageLayoutModule->pagestyleCO->currentText();
1863                 for (size_t i = 0; i != pagestyles.size(); ++i)
1864                         if (pagestyles[i].second == style_gui)
1865                                 bp_.pagestyle = pagestyles[i].first;
1866         }
1867
1868         switch (textLayoutModule->lspacingCO->currentIndex()) {
1869         case 0:
1870                 bp_.spacing().set(Spacing::Single);
1871                 break;
1872         case 1:
1873                 bp_.spacing().set(Spacing::Onehalf);
1874                 break;
1875         case 2:
1876                 bp_.spacing().set(Spacing::Double);
1877                 break;
1878         case 3:
1879                 bp_.spacing().set(Spacing::Other,
1880                         widgetToDoubleStr(textLayoutModule->lspacingLE));
1881                 break;
1882         }
1883
1884         if (textLayoutModule->twoColumnCB->isChecked())
1885                 bp_.columns = 2;
1886         else
1887                 bp_.columns = 1;
1888
1889         // text should have passed validation
1890         bp_.listings_params =
1891                 InsetListingsParams(fromqstr(textLayoutModule->listingsED->toPlainText())).params();
1892
1893         if (textLayoutModule->indentRB->isChecked())
1894                 bp_.paragraph_separation = BufferParams::ParagraphIndentSeparation;
1895         else
1896                 bp_.paragraph_separation = BufferParams::ParagraphSkipSeparation;
1897
1898         switch (textLayoutModule->skipCO->currentIndex()) {
1899         case 0:
1900                 bp_.setDefSkip(VSpace(VSpace::SMALLSKIP));
1901                 break;
1902         case 1:
1903                 bp_.setDefSkip(VSpace(VSpace::MEDSKIP));
1904                 break;
1905         case 2:
1906                 bp_.setDefSkip(VSpace(VSpace::BIGSKIP));
1907                 break;
1908         case 3:
1909         {
1910                 VSpace vs = VSpace(
1911                         widgetsToLength(textLayoutModule->skipLE,
1912                                 textLayoutModule->skipLengthCO)
1913                         );
1914                 bp_.setDefSkip(vs);
1915                 break;
1916         }
1917         default:
1918                 // DocumentDefskipCB assures that this never happens
1919                 // so Assert then !!!  - jbl
1920                 bp_.setDefSkip(VSpace(VSpace::MEDSKIP));
1921                 break;
1922         }
1923
1924         bp_.options =
1925                 fromqstr(latexModule->optionsLE->text());
1926
1927         bp_.use_default_options =
1928                 latexModule->defaultOptionsCB->isChecked();
1929
1930         if (latexModule->childDocGB->isChecked())
1931                 bp_.master =
1932                         fromqstr(latexModule->childDocLE->text());
1933         else
1934                 bp_.master = string();
1935
1936         bp_.float_placement = floatModule->get();
1937
1938         // output
1939         bp_.defaultOutputFormat = fromqstr(outputModule->defaultFormatCO->itemData(
1940                 outputModule->defaultFormatCO->currentIndex()).toString());
1941
1942         bool const xetex = outputModule->xetexCB->isChecked();
1943         bp_.useXetex = xetex;
1944
1945         // fonts
1946         if (xetex) {
1947                 if (fontModule->fontsRomanCO->currentIndex() == 0)
1948                         bp_.fontsRoman = "default";
1949                 else
1950                         bp_.fontsRoman =
1951                                 fromqstr(fontModule->fontsRomanCO->currentText());
1952         
1953                 if (fontModule->fontsSansCO->currentIndex() == 0)
1954                         bp_.fontsSans = "default";
1955                 else
1956                         bp_.fontsSans =
1957                                 fromqstr(fontModule->fontsSansCO->currentText());
1958         
1959                 if (fontModule->fontsTypewriterCO->currentIndex() == 0)
1960                         bp_.fontsTypewriter = "default";
1961                 else
1962                         bp_.fontsTypewriter =
1963                                 fromqstr(fontModule->fontsTypewriterCO->currentText());
1964         } else {
1965                 bp_.fontsRoman =
1966                         tex_fonts_roman[fontModule->fontsRomanCO->currentIndex()];
1967         
1968                 bp_.fontsSans =
1969                         tex_fonts_sans[fontModule->fontsSansCO->currentIndex()];
1970         
1971                 bp_.fontsTypewriter =
1972                         tex_fonts_monospaced[fontModule->fontsTypewriterCO->currentIndex()];
1973         }
1974
1975         bp_.fontsCJK =
1976                 fromqstr(fontModule->cjkFontLE->text());
1977
1978         bp_.fontsSansScale = fontModule->scaleSansSB->value();
1979
1980         bp_.fontsTypewriterScale = fontModule->scaleTypewriterSB->value();
1981
1982         bp_.fontsSC = fontModule->fontScCB->isChecked();
1983
1984         bp_.fontsOSF = fontModule->fontOsfCB->isChecked();
1985
1986         if (xetex)
1987                 bp_.fontsDefaultFamily = "default";
1988         else
1989                 bp_.fontsDefaultFamily = GuiDocument::fontfamilies[
1990                         fontModule->fontsDefaultCO->currentIndex()];
1991
1992         if (fontModule->fontsizeCO->currentIndex() == 0)
1993                 bp_.fontsize = "default";
1994         else
1995                 bp_.fontsize =
1996                         fromqstr(fontModule->fontsizeCO->currentText());
1997
1998         // paper
1999         bp_.papersize = PAPER_SIZE(
2000                 pageLayoutModule->papersizeCO->currentIndex());
2001
2002         // custom, A3, B3 and B4 paper sizes need geometry
2003         int psize = pageLayoutModule->papersizeCO->currentIndex();
2004         bool geom_papersize = (psize == 1 || psize == 5 || psize == 8 || psize == 9);
2005
2006         bp_.paperwidth = widgetsToLength(pageLayoutModule->paperwidthLE,
2007                 pageLayoutModule->paperwidthUnitCO);
2008
2009         bp_.paperheight = widgetsToLength(pageLayoutModule->paperheightLE,
2010                 pageLayoutModule->paperheightUnitCO);
2011
2012         if (pageLayoutModule->facingPagesCB->isChecked())
2013                 bp_.sides = TwoSides;
2014         else
2015                 bp_.sides = OneSide;
2016
2017         if (pageLayoutModule->landscapeRB->isChecked())
2018                 bp_.orientation = ORIENTATION_LANDSCAPE;
2019         else
2020                 bp_.orientation = ORIENTATION_PORTRAIT;
2021
2022         bp_.backgroundcolor = set_backgroundcolor;
2023
2024         // margins
2025         bp_.use_geometry = !marginsModule->marginCB->isChecked()
2026                 || geom_papersize;
2027
2028         Ui::MarginsUi const * m = marginsModule;
2029
2030         bp_.leftmargin = widgetsToLength(m->innerLE, m->innerUnit);
2031         bp_.topmargin = widgetsToLength(m->topLE, m->topUnit);
2032         bp_.rightmargin = widgetsToLength(m->outerLE, m->outerUnit);
2033         bp_.bottommargin = widgetsToLength(m->bottomLE, m->bottomUnit);
2034         bp_.headheight = widgetsToLength(m->headheightLE, m->headheightUnit);
2035         bp_.headsep = widgetsToLength(m->headsepLE, m->headsepUnit);
2036         bp_.footskip = widgetsToLength(m->footskipLE, m->footskipUnit);
2037         bp_.columnsep = widgetsToLength(m->columnsepLE, m->columnsepUnit);
2038
2039         // branches
2040         branchesModule->apply(bp_);
2041
2042         // PDF support
2043         PDFOptions & pdf = bp_.pdfoptions();
2044         pdf.use_hyperref = pdfSupportModule->use_hyperrefGB->isChecked();
2045         pdf.title = fromqstr(pdfSupportModule->titleLE->text());
2046         pdf.author = fromqstr(pdfSupportModule->authorLE->text());
2047         pdf.subject = fromqstr(pdfSupportModule->subjectLE->text());
2048         pdf.keywords = fromqstr(pdfSupportModule->keywordsLE->text());
2049
2050         pdf.bookmarks = pdfSupportModule->bookmarksGB->isChecked();
2051         pdf.bookmarksnumbered = pdfSupportModule->bookmarksnumberedCB->isChecked();
2052         pdf.bookmarksopen = pdfSupportModule->bookmarksopenGB->isChecked();
2053         pdf.bookmarksopenlevel = pdfSupportModule->bookmarksopenlevelSB->value();
2054
2055         pdf.breaklinks = pdfSupportModule->breaklinksCB->isChecked();
2056         pdf.pdfborder = pdfSupportModule->pdfborderCB->isChecked();
2057         pdf.pdfusetitle = pdfSupportModule->pdfusetitleCB->isChecked();
2058         pdf.colorlinks = pdfSupportModule->colorlinksCB->isChecked();
2059         pdf.backref =
2060                 backref_opts[pdfSupportModule->backrefCO->currentIndex()];
2061         if (pdfSupportModule->fullscreenCB->isChecked())
2062                 pdf.pagemode = pdf.pagemode_fullscreen;
2063         else
2064                 pdf.pagemode.clear();
2065         pdf.quoted_options = pdf.quoted_options_check(
2066                                 fromqstr(pdfSupportModule->optionsLE->text()));
2067 }
2068
2069
2070 void GuiDocument::paramsToDialog()
2071 {
2072         // set the default unit
2073         Length::UNIT const defaultUnit = Length::defaultUnit();
2074
2075         // preamble
2076         preambleModule->update(bp_, id());
2077
2078         // biblio
2079         biblioModule->citeDefaultRB->setChecked(
2080                 bp_.citeEngine() == ENGINE_BASIC);
2081
2082         biblioModule->citeNatbibRB->setChecked(
2083                 bp_.citeEngine() == ENGINE_NATBIB_NUMERICAL ||
2084                 bp_.citeEngine() == ENGINE_NATBIB_AUTHORYEAR);
2085
2086         biblioModule->citeStyleCO->setCurrentIndex(
2087                 bp_.citeEngine() == ENGINE_NATBIB_NUMERICAL);
2088
2089         biblioModule->citeJurabibRB->setChecked(
2090                 bp_.citeEngine() == ENGINE_JURABIB);
2091
2092         biblioModule->bibtopicCB->setChecked(
2093                 bp_.use_bibtopic);
2094
2095         string command;
2096         string options =
2097                 split(bp_.bibtex_command, command, ' ');
2098
2099         int const bpos = biblioModule->bibtexCO->findData(toqstr(command));
2100         if (bpos != -1) {
2101                 biblioModule->bibtexCO->setCurrentIndex(bpos);
2102                 biblioModule->bibtexOptionsED->setText(toqstr(options).trimmed());
2103         } else {
2104                 biblioModule->bibtexCO->setCurrentIndex(0);
2105                 biblioModule->bibtexOptionsED->clear();
2106         }
2107         biblioModule->bibtexOptionsED->setEnabled(
2108                 biblioModule->bibtexCO->currentIndex() != 0);
2109
2110         // indices
2111         indicesModule->update(bp_);
2112
2113         // language & quotes
2114         int const pos = langModule->languageCO->findData(toqstr(
2115                 bp_.language->lang()));
2116         langModule->languageCO->setCurrentIndex(pos);
2117
2118         langModule->quoteStyleCO->setCurrentIndex(
2119                 bp_.quotes_language);
2120
2121         bool default_enc = true;
2122         if (bp_.inputenc != "auto") {
2123                 default_enc = false;
2124                 if (bp_.inputenc == "default") {
2125                         langModule->encodingCO->setCurrentIndex(0);
2126                 } else {
2127                         string enc_gui;
2128                         Encodings::const_iterator it = encodings.begin();
2129                         Encodings::const_iterator const end = encodings.end();
2130                         for (; it != end; ++it) {
2131                                 if (it->latexName() == bp_.inputenc) {
2132                                         enc_gui = it->guiName();
2133                                         break;
2134                                 }
2135                         }
2136                         int const i = langModule->encodingCO->findText(
2137                                         qt_(enc_gui));
2138                         if (i >= 0)
2139                                 langModule->encodingCO->setCurrentIndex(i);
2140                         else
2141                                 // unknown encoding. Set to default.
2142                                 default_enc = true;
2143                 }
2144         }
2145         langModule->defaultencodingRB->setChecked(default_enc);
2146         langModule->otherencodingRB->setChecked(!default_enc);
2147
2148         // numbering
2149         int const min_toclevel = documentClass().min_toclevel();
2150         int const max_toclevel = documentClass().max_toclevel();
2151         if (documentClass().hasTocLevels()) {
2152                 numberingModule->setEnabled(true);
2153                 numberingModule->depthSL->setMinimum(min_toclevel - 1);
2154                 numberingModule->depthSL->setMaximum(max_toclevel);
2155                 numberingModule->depthSL->setValue(bp_.secnumdepth);
2156                 numberingModule->tocSL->setMaximum(min_toclevel - 1);
2157                 numberingModule->tocSL->setMaximum(max_toclevel);
2158                 numberingModule->tocSL->setValue(bp_.tocdepth);
2159                 updateNumbering();
2160         } else {
2161                 numberingModule->setEnabled(false);
2162                 numberingModule->tocTW->clear();
2163         }
2164
2165         // bullets
2166         bulletsModule->setBullet(0, bp_.user_defined_bullet(0));
2167         bulletsModule->setBullet(1, bp_.user_defined_bullet(1));
2168         bulletsModule->setBullet(2, bp_.user_defined_bullet(2));
2169         bulletsModule->setBullet(3, bp_.user_defined_bullet(3));
2170         bulletsModule->init();
2171
2172         // packages
2173         int nitem = findToken(tex_graphics, bp_.graphicsDriver);
2174         if (nitem >= 0)
2175                 latexModule->psdriverCO->setCurrentIndex(nitem);
2176         updateModuleInfo();
2177         
2178         mathsModule->amsCB->setChecked(
2179                 bp_.use_amsmath == BufferParams::package_on);
2180         mathsModule->amsautoCB->setChecked(
2181                 bp_.use_amsmath == BufferParams::package_auto);
2182
2183         mathsModule->esintCB->setChecked(
2184                 bp_.use_esint == BufferParams::package_on);
2185         mathsModule->esintautoCB->setChecked(
2186                 bp_.use_esint == BufferParams::package_auto);
2187
2188         switch (bp_.spacing().getSpace()) {
2189                 case Spacing::Other: nitem = 3; break;
2190                 case Spacing::Double: nitem = 2; break;
2191                 case Spacing::Onehalf: nitem = 1; break;
2192                 case Spacing::Default: case Spacing::Single: nitem = 0; break;
2193         }
2194
2195         // text layout
2196         string const & layoutID = bp_.baseClassID();
2197         setLayoutComboByIDString(layoutID);
2198
2199         updatePagestyle(documentClass().opt_pagestyle(),
2200                                  bp_.pagestyle);
2201
2202         textLayoutModule->lspacingCO->setCurrentIndex(nitem);
2203         if (bp_.spacing().getSpace() == Spacing::Other) {
2204                 doubleToWidget(textLayoutModule->lspacingLE,
2205                         bp_.spacing().getValueAsString());
2206         }
2207         setLSpacing(nitem);
2208
2209         if (bp_.paragraph_separation == BufferParams::ParagraphIndentSeparation)
2210                 textLayoutModule->indentRB->setChecked(true);
2211         else
2212                 textLayoutModule->skipRB->setChecked(true);
2213
2214         int skip = 0;
2215         switch (bp_.getDefSkip().kind()) {
2216         case VSpace::SMALLSKIP:
2217                 skip = 0;
2218                 break;
2219         case VSpace::MEDSKIP:
2220                 skip = 1;
2221                 break;
2222         case VSpace::BIGSKIP:
2223                 skip = 2;
2224                 break;
2225         case VSpace::LENGTH:
2226         {
2227                 skip = 3;
2228                 string const length = bp_.getDefSkip().asLyXCommand();
2229                 lengthToWidgets(textLayoutModule->skipLE,
2230                         textLayoutModule->skipLengthCO,
2231                         length, defaultUnit);
2232                 break;
2233         }
2234         default:
2235                 skip = 0;
2236                 break;
2237         }
2238         textLayoutModule->skipCO->setCurrentIndex(skip);
2239         setSkip(skip);
2240
2241         textLayoutModule->twoColumnCB->setChecked(
2242                 bp_.columns == 2);
2243
2244         // break listings_params to multiple lines
2245         string lstparams =
2246                 InsetListingsParams(bp_.listings_params).separatedParams();
2247         textLayoutModule->listingsED->setPlainText(toqstr(lstparams));
2248
2249         if (!bp_.options.empty()) {
2250                 latexModule->optionsLE->setText(
2251                         toqstr(bp_.options));
2252         } else {
2253                 latexModule->optionsLE->setText(QString());
2254         }
2255
2256         // latex
2257         latexModule->defaultOptionsCB->setChecked(
2258                         bp_.use_default_options);
2259         updateSelectedModules();
2260         selectionManager->updateProvidedModules(
2261                         bp_.baseClass()->providedModules());
2262         selectionManager->updateExcludedModules(
2263                         bp_.baseClass()->excludedModules());
2264
2265         if (!documentClass().options().empty()) {
2266                 latexModule->defaultOptionsLE->setText(
2267                         toqstr(documentClass().options()));
2268         } else {
2269                 latexModule->defaultOptionsLE->setText(
2270                         toqstr(_("[No options predefined]")));
2271         }
2272
2273         latexModule->defaultOptionsLE->setEnabled(
2274                 bp_.use_default_options
2275                 && !documentClass().options().empty());
2276
2277         latexModule->defaultOptionsCB->setEnabled(
2278                 !documentClass().options().empty());
2279
2280         if (!bp_.master.empty()) {
2281                 latexModule->childDocGB->setChecked(true);
2282                 latexModule->childDocLE->setText(
2283                         toqstr(bp_.master));
2284         } else {
2285                 latexModule->childDocLE->setText(QString());
2286                 latexModule->childDocGB->setChecked(false);
2287         }
2288
2289         floatModule->set(bp_.float_placement);
2290
2291         // Output
2292         // update combobox with formats
2293         updateDefaultFormat();
2294         int index = outputModule->defaultFormatCO->findData(toqstr(
2295                 bp_.defaultOutputFormat));
2296         // set to default if format is not found 
2297         if (index == -1)
2298                 index = 0;
2299         outputModule->defaultFormatCO->setCurrentIndex(index);
2300         outputModule->xetexCB->setEnabled(bp_.baseClass()->outputType() == lyx::LATEX);
2301         outputModule->xetexCB->setChecked(
2302                 bp_.baseClass()->outputType() == lyx::LATEX && bp_.useXetex);
2303
2304         // Fonts
2305         updateFontsize(documentClass().opt_fontsize(),
2306                         bp_.fontsize);
2307
2308         if (bp_.useXetex) {
2309                 for (int i = 0; i < fontModule->fontsRomanCO->count(); ++i) {
2310                         if (fontModule->fontsRomanCO->itemText(i) == toqstr(bp_.fontsRoman)) {
2311                                 fontModule->fontsRomanCO->setCurrentIndex(i);
2312                                 return;
2313                         }
2314                 }
2315                 
2316                 for (int i = 0; i < fontModule->fontsSansCO->count(); ++i) {
2317                         if (fontModule->fontsSansCO->itemText(i) == toqstr(bp_.fontsSans)) {
2318                                 fontModule->fontsSansCO->setCurrentIndex(i);
2319                                 return;
2320                         }
2321                 }
2322                 for (int i = 0; i < fontModule->fontsTypewriterCO->count(); ++i) {
2323                         if (fontModule->fontsTypewriterCO->itemText(i) == 
2324                                 toqstr(bp_.fontsTypewriter)) {
2325                                 fontModule->fontsTypewriterCO->setCurrentIndex(i);
2326                                 return;
2327                         }
2328                 }
2329         } else {
2330                 int n = findToken(tex_fonts_roman, bp_.fontsRoman);
2331                 if (n >= 0) {
2332                         fontModule->fontsRomanCO->setCurrentIndex(n);
2333                         romanChanged(n);
2334                 }
2335         
2336                 n = findToken(tex_fonts_sans, bp_.fontsSans);
2337                 if (n >= 0) {
2338                         fontModule->fontsSansCO->setCurrentIndex(n);
2339                         sansChanged(n);
2340                 }
2341         
2342                 n = findToken(tex_fonts_monospaced, bp_.fontsTypewriter);
2343                 if (n >= 0) {
2344                         fontModule->fontsTypewriterCO->setCurrentIndex(n);
2345                         ttChanged(n);
2346                 }
2347         }
2348
2349         if (!bp_.fontsCJK.empty())
2350                 fontModule->cjkFontLE->setText(
2351                         toqstr(bp_.fontsCJK));
2352         else
2353                 fontModule->cjkFontLE->setText(QString());
2354
2355         fontModule->fontScCB->setChecked(bp_.fontsSC);
2356         fontModule->fontOsfCB->setChecked(bp_.fontsOSF);
2357         fontModule->scaleSansSB->setValue(bp_.fontsSansScale);
2358         fontModule->scaleTypewriterSB->setValue(bp_.fontsTypewriterScale);
2359
2360         int nn = findToken(GuiDocument::fontfamilies, bp_.fontsDefaultFamily);
2361         if (nn >= 0)
2362                 fontModule->fontsDefaultCO->setCurrentIndex(nn);
2363
2364         // paper
2365         bool const extern_geometry =
2366                 documentClass().provides("geometry");
2367         int const psize = bp_.papersize;
2368         pageLayoutModule->papersizeCO->setCurrentIndex(psize);
2369         setCustomPapersize(!extern_geometry && psize);
2370         pageLayoutModule->papersizeCO->setEnabled(!extern_geometry);
2371
2372         bool const landscape =
2373                 bp_.orientation == ORIENTATION_LANDSCAPE;
2374         pageLayoutModule->landscapeRB->setChecked(landscape);
2375         pageLayoutModule->portraitRB->setChecked(!landscape);
2376         pageLayoutModule->landscapeRB->setEnabled(!extern_geometry);
2377         pageLayoutModule->portraitRB->setEnabled(!extern_geometry);
2378
2379         pageLayoutModule->facingPagesCB->setChecked(
2380                 bp_.sides == TwoSides);
2381
2382         pageLayoutModule->backgroundPB->setStyleSheet(
2383                 colorButtonStyleSheet(rgb2qcolor(bp_.backgroundcolor)));
2384         set_backgroundcolor = bp_.backgroundcolor;
2385
2386         lengthToWidgets(pageLayoutModule->paperwidthLE,
2387                 pageLayoutModule->paperwidthUnitCO, bp_.paperwidth, defaultUnit);
2388         lengthToWidgets(pageLayoutModule->paperheightLE,
2389                 pageLayoutModule->paperheightUnitCO, bp_.paperheight, defaultUnit);
2390
2391         // margins
2392         Ui::MarginsUi * m = marginsModule;
2393
2394         setMargins(!bp_.use_geometry);
2395
2396         lengthToWidgets(m->topLE, m->topUnit,
2397                 bp_.topmargin, defaultUnit);
2398
2399         lengthToWidgets(m->bottomLE, m->bottomUnit,
2400                 bp_.bottommargin, defaultUnit);
2401
2402         lengthToWidgets(m->innerLE, m->innerUnit,
2403                 bp_.leftmargin, defaultUnit);
2404
2405         lengthToWidgets(m->outerLE, m->outerUnit,
2406                 bp_.rightmargin, defaultUnit);
2407
2408         lengthToWidgets(m->headheightLE, m->headheightUnit,
2409                 bp_.headheight, defaultUnit);
2410
2411         lengthToWidgets(m->headsepLE, m->headsepUnit,
2412                 bp_.headsep, defaultUnit);
2413
2414         lengthToWidgets(m->footskipLE, m->footskipUnit,
2415                 bp_.footskip, defaultUnit);
2416
2417         lengthToWidgets(m->columnsepLE, m->columnsepUnit,
2418                 bp_.columnsep, defaultUnit);
2419
2420         // branches
2421         updateUnknownBranches();
2422         branchesModule->update(bp_);
2423
2424         // PDF support
2425         PDFOptions const & pdf = bp_.pdfoptions();
2426         pdfSupportModule->use_hyperrefGB->setChecked(pdf.use_hyperref);
2427         pdfSupportModule->titleLE->setText(toqstr(pdf.title));
2428         pdfSupportModule->authorLE->setText(toqstr(pdf.author));
2429         pdfSupportModule->subjectLE->setText(toqstr(pdf.subject));
2430         pdfSupportModule->keywordsLE->setText(toqstr(pdf.keywords));
2431
2432         pdfSupportModule->bookmarksGB->setChecked(pdf.bookmarks);
2433         pdfSupportModule->bookmarksnumberedCB->setChecked(pdf.bookmarksnumbered);
2434         pdfSupportModule->bookmarksopenGB->setChecked(pdf.bookmarksopen);
2435
2436         pdfSupportModule->bookmarksopenlevelSB->setValue(pdf.bookmarksopenlevel);
2437
2438         pdfSupportModule->breaklinksCB->setChecked(pdf.breaklinks);
2439         pdfSupportModule->pdfborderCB->setChecked(pdf.pdfborder);
2440         pdfSupportModule->pdfusetitleCB->setChecked(pdf.pdfusetitle);
2441         pdfSupportModule->colorlinksCB->setChecked(pdf.colorlinks);
2442
2443         nn = findToken(backref_opts, pdf.backref);
2444         if (nn >= 0)
2445                 pdfSupportModule->backrefCO->setCurrentIndex(nn);
2446
2447         pdfSupportModule->fullscreenCB->setChecked
2448                 (pdf.pagemode == pdf.pagemode_fullscreen);
2449
2450         pdfSupportModule->optionsLE->setText(
2451                 toqstr(pdf.quoted_options));
2452
2453         // Make sure that the bc is in the INITIAL state
2454         if (bc().policy().buttonStatus(ButtonPolicy::RESTORE))
2455                 bc().restore();
2456
2457         // clear changed branches cache
2458         changedBranches_.clear();
2459 }
2460
2461
2462 void GuiDocument::saveDocDefault()
2463 {
2464         // we have to apply the params first
2465         applyView();
2466         saveAsDefault();
2467 }
2468
2469
2470 void GuiDocument::updateAvailableModules() 
2471 {
2472         modules_av_model_.clear();
2473         list<modInfoStruct> const & modInfoList = getModuleInfo();
2474         list<modInfoStruct>::const_iterator mit = modInfoList.begin();
2475         list<modInfoStruct>::const_iterator men = modInfoList.end();
2476         for (int i = 0; mit != men; ++mit, ++i)
2477                 modules_av_model_.insertRow(i, mit->name, mit->id, 
2478                                 mit->description);
2479 }
2480
2481
2482 void GuiDocument::updateSelectedModules() 
2483 {
2484         modules_sel_model_.clear();
2485         list<modInfoStruct> const selModList = getSelectedModules();
2486         list<modInfoStruct>::const_iterator mit = selModList.begin();
2487         list<modInfoStruct>::const_iterator men = selModList.end();
2488         for (int i = 0; mit != men; ++mit, ++i)
2489                 modules_sel_model_.insertRow(i, mit->name, mit->id, 
2490                                 mit->description);
2491 }
2492
2493
2494 void GuiDocument::updateContents()
2495 {
2496         // Nothing to do here as the document settings is not cursor dependant.
2497         return;
2498 }
2499
2500
2501 void GuiDocument::useClassDefaults()
2502 {
2503         if (applyPB->isEnabled()) {
2504                 int const ret = Alert::prompt(_("Unapplied changes"),
2505                                 _("Some changes in the dialog were not yet applied.\n"
2506                                   "If you do not apply now, they will be lost after this action."),
2507                                 1, 1, _("&Apply"), _("&Dismiss"));
2508                 if (ret == 0)
2509                         applyView();
2510         }
2511
2512         int idx = latexModule->classCO->currentIndex();
2513         string const classname = classes_model_.getIDString(idx);
2514         if (!bp_.setBaseClass(classname)) {
2515                 Alert::error(_("Error"), _("Unable to set document class."));
2516                 return;
2517         }
2518         bp_.useClassDefaults();
2519         paramsToDialog();
2520 }
2521
2522
2523 void GuiDocument::setLayoutComboByIDString(string const & idString)
2524 {
2525         int idx = classes_model_.findIDString(idString);
2526         if (idx < 0)
2527                 Alert::warning(_("Can't set layout!"), 
2528                         bformat(_("Unable to set layout for ID: %1$s"), from_utf8(idString)));
2529         else 
2530                 latexModule->classCO->setCurrentIndex(idx);
2531 }
2532
2533
2534 bool GuiDocument::isValid()
2535 {
2536         return validateListingsParameters().isEmpty()
2537                 && (textLayoutModule->skipCO->currentIndex() != 3
2538                         || !textLayoutModule->skipLE->text().isEmpty());
2539 }
2540
2541
2542 char const * const GuiDocument::fontfamilies[5] = {
2543         "default", "rmdefault", "sfdefault", "ttdefault", ""
2544 };
2545
2546
2547 char const * GuiDocument::fontfamilies_gui[5] = {
2548         N_("Default"), N_("Roman"), N_("Sans Serif"), N_("Typewriter"), ""
2549 };
2550
2551
2552 bool GuiDocument::initialiseParams(string const &)
2553 {
2554         BufferView const * view = bufferview();
2555         if (!view) {
2556                 bp_ = BufferParams();
2557                 paramsToDialog();
2558                 return true;
2559         }
2560         bp_ = view->buffer().params();
2561         loadModuleInfo();
2562         updateAvailableModules();
2563         //FIXME It'd be nice to make sure here that the selected
2564         //modules are consistent: That required modules are actually
2565         //selected, and that we don't have conflicts. If so, we could
2566         //at least pop up a warning.
2567         paramsToDialog();
2568         return true;
2569 }
2570
2571
2572 void GuiDocument::clearParams()
2573 {
2574         bp_ = BufferParams();
2575 }
2576
2577
2578 BufferId GuiDocument::id() const
2579 {
2580         BufferView const * const view = bufferview();
2581         return view? &view->buffer() : 0;
2582 }
2583
2584
2585 list<GuiDocument::modInfoStruct> const & GuiDocument::getModuleInfo()
2586 {
2587         return moduleNames_;
2588 }
2589
2590
2591 list<GuiDocument::modInfoStruct> const 
2592                 GuiDocument::makeModuleInfo(LayoutModuleList const & mods)
2593 {
2594         LayoutModuleList::const_iterator it =  mods.begin();
2595         LayoutModuleList::const_iterator end = mods.end();
2596         list<modInfoStruct> mInfo;
2597         for (; it != end; ++it) {
2598                 modInfoStruct m;
2599                 m.id = *it;
2600                 LyXModule * mod = moduleList[*it];
2601                 if (mod)
2602                         // FIXME Unicode
2603                         m.name = toqstr(translateIfPossible(from_utf8(mod->getName())));
2604                 else 
2605                         m.name = toqstr(*it) + toqstr(" (") + qt_("Not Found") + toqstr(")");
2606                 mInfo.push_back(m);
2607         }
2608         return mInfo;
2609 }
2610
2611
2612 list<GuiDocument::modInfoStruct> const GuiDocument::getSelectedModules()
2613 {
2614         return makeModuleInfo(params().getModules());
2615 }
2616
2617
2618 list<GuiDocument::modInfoStruct> const GuiDocument::getProvidedModules()
2619 {
2620         return makeModuleInfo(params().baseClass()->providedModules());
2621 }
2622
2623
2624 DocumentClass const & GuiDocument::documentClass() const
2625 {
2626         return bp_.documentClass();
2627 }
2628
2629
2630 static void dispatch_bufferparams(Dialog const & dialog,
2631         BufferParams const & bp, FuncCode lfun)
2632 {
2633         ostringstream ss;
2634         ss << "\\begin_header\n";
2635         bp.writeFile(ss);
2636         ss << "\\end_header\n";
2637         dialog.dispatch(FuncRequest(lfun, ss.str()));
2638 }
2639
2640
2641 void GuiDocument::dispatchParams()
2642 {
2643         // This must come first so that a language change is correctly noticed
2644         setLanguage();
2645
2646         // Apply the BufferParams. Note that this will set the base class
2647         // and then update the buffer's layout.
2648         dispatch_bufferparams(*this, params(), LFUN_BUFFER_PARAMS_APPLY);
2649
2650         if (!params().master.empty()) {
2651                 FileName const master_file = support::makeAbsPath(params().master,
2652                            support::onlyPath(buffer().absFileName()));
2653                 if (isLyXFilename(master_file.absFilename())) {
2654                         Buffer * master = checkAndLoadLyXFile(master_file);
2655                         if (master) {
2656                                 if (master->isChild(const_cast<Buffer *>(&buffer())))
2657                                         const_cast<Buffer &>(buffer()).setParent(master);
2658                                 else
2659                                         Alert::warning(_("Assigned master does not include this file"), 
2660                                                 bformat(_("You must include this file in the document\n"
2661                                                           "'%1$s' in order to use the master document\n"
2662                                                           "feature."), from_utf8(params().master)));
2663                         } else
2664                                 Alert::warning(_("Could not load master"), 
2665                                                 bformat(_("The master document '%1$s'\n"
2666                                                            "could not be loaded."),
2667                                                            from_utf8(params().master)));
2668                 }
2669         }
2670
2671         // Generate the colours requested by each new branch.
2672         BranchList & branchlist = params().branchlist();
2673         if (!branchlist.empty()) {
2674                 BranchList::const_iterator it = branchlist.begin();
2675                 BranchList::const_iterator const end = branchlist.end();
2676                 for (; it != end; ++it) {
2677                         docstring const & current_branch = it->branch();
2678                         Branch const * branch = branchlist.find(current_branch);
2679                         string const x11hexname = X11hexname(branch->color());
2680                         // display the new color
2681                         docstring const str = current_branch + ' ' + from_ascii(x11hexname);
2682                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
2683                 }
2684
2685                 // Open insets of selected branches, close deselected ones
2686                 dispatch(FuncRequest(LFUN_ALL_INSETS_TOGGLE,
2687                         "assign branch"));
2688         }
2689         // rename branches in the document
2690         executeBranchRenaming();
2691         // and clear changed branches cache
2692         changedBranches_.clear();
2693         
2694         // Generate the colours requested by indices.
2695         IndicesList & indiceslist = params().indiceslist();
2696         if (!indiceslist.empty()) {
2697                 IndicesList::const_iterator it = indiceslist.begin();
2698                 IndicesList::const_iterator const end = indiceslist.end();
2699                 for (; it != end; ++it) {
2700                         docstring const & current_index = it->shortcut();
2701                         Index const * index = indiceslist.findShortcut(current_index);
2702                         string const x11hexname = X11hexname(index->color());
2703                         // display the new color
2704                         docstring const str = current_index + ' ' + from_ascii(x11hexname);
2705                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
2706                 }
2707         }
2708         // FIXME: If we used an LFUN, we would not need those two lines:
2709         BufferView * bv = const_cast<BufferView *>(bufferview());
2710         bv->processUpdateFlags(Update::Force | Update::FitCursor);
2711 }
2712
2713
2714 void GuiDocument::setLanguage() const
2715 {
2716         Language const * const newL = bp_.language;
2717         if (buffer().params().language == newL)
2718                 return;
2719
2720         string const & lang_name = newL->lang();
2721         dispatch(FuncRequest(LFUN_BUFFER_LANGUAGE, lang_name));
2722 }
2723
2724
2725 void GuiDocument::saveAsDefault() const
2726 {
2727         dispatch_bufferparams(*this, params(), LFUN_BUFFER_SAVE_AS_DEFAULT);
2728 }
2729
2730
2731 bool GuiDocument::isFontAvailable(string const & font) const
2732 {
2733         if (font == "default" || font == "cmr"
2734             || font == "cmss" || font == "cmtt")
2735                 // these are standard
2736                 return true;
2737         if (font == "lmodern" || font == "lmss" || font == "lmtt")
2738                 return LaTeXFeatures::isAvailable("lmodern");
2739         if (font == "times" || font == "palatino"
2740                  || font == "helvet" || font == "courier")
2741                 return LaTeXFeatures::isAvailable("psnfss");
2742         if (font == "cmbr" || font == "cmtl")
2743                 return LaTeXFeatures::isAvailable("cmbright");
2744         if (font == "utopia")
2745                 return LaTeXFeatures::isAvailable("utopia")
2746                         || LaTeXFeatures::isAvailable("fourier");
2747         if (font == "beraserif" || font == "berasans"
2748                 || font == "beramono")
2749                 return LaTeXFeatures::isAvailable("bera");
2750         return LaTeXFeatures::isAvailable(font);
2751 }
2752
2753
2754 bool GuiDocument::providesOSF(string const & font) const
2755 {
2756         if (outputModule->xetexCB->isChecked())
2757                 // FIXME: we should check if the fonts really
2758                 // have OSF support. But how?
2759                 return true;
2760         if (font == "cmr")
2761                 return isFontAvailable("eco");
2762         if (font == "palatino")
2763                 return isFontAvailable("mathpazo");
2764         return false;
2765 }
2766
2767
2768 bool GuiDocument::providesSC(string const & font) const
2769 {
2770         if (outputModule->xetexCB->isChecked())
2771                 return false;
2772         if (font == "palatino")
2773                 return isFontAvailable("mathpazo");
2774         if (font == "utopia")
2775                 return isFontAvailable("fourier");
2776         return false;
2777 }
2778
2779
2780 bool GuiDocument::providesScale(string const & font) const
2781 {
2782         if (outputModule->xetexCB->isChecked())
2783                 return true;
2784         return font == "helvet" || font == "luximono"
2785                 || font == "berasans"  || font == "beramono";
2786 }
2787
2788
2789 void GuiDocument::loadModuleInfo()
2790 {
2791         moduleNames_.clear();
2792         LyXModuleList::const_iterator it  = moduleList.begin();
2793         LyXModuleList::const_iterator end = moduleList.end();
2794         for (; it != end; ++it) {
2795                 modInfoStruct m;
2796                 m.id = it->getID();
2797                 // FIXME Unicode
2798                 m.name = toqstr(translateIfPossible(from_utf8(it->getName())));
2799                 // this is supposed to give us the first sentence of the description
2800                 // FIXME Unicode
2801                 QString desc =
2802                         toqstr(translateIfPossible(from_utf8(it->getDescription())));
2803                 int const pos = desc.indexOf(".");
2804                 if (pos > 0)
2805                         desc.truncate(pos + 1);
2806                 m.description = desc;
2807                 moduleNames_.push_back(m);
2808         }
2809 }
2810
2811
2812 void GuiDocument::updateUnknownBranches()
2813 {
2814         list<docstring> used_branches;
2815         buffer().getUsedBranches(used_branches);
2816         list<docstring>::const_iterator it = used_branches.begin();
2817         QStringList unknown_branches;
2818         for (; it != used_branches.end() ; ++it) {
2819                 if (!buffer().params().branchlist().find(*it))
2820                         unknown_branches.append(toqstr(*it));
2821         }
2822         branchesModule->setUnknownBranches(unknown_branches);
2823 }
2824
2825
2826 void GuiDocument::branchesRename(docstring const & oldname, docstring const & newname)
2827 {
2828         map<docstring, docstring>::iterator it = changedBranches_.begin();
2829         for (; it != changedBranches_.end() ; ++it) {
2830                 if (it->second == oldname) {
2831                         // branch has already been renamed
2832                         it->second = newname;
2833                         return;
2834                 }
2835         }
2836         // store new name
2837         changedBranches_[oldname] = newname;
2838 }
2839
2840
2841 void GuiDocument::executeBranchRenaming() const
2842 {
2843         map<docstring, docstring>::const_iterator it = changedBranches_.begin();
2844         for (; it != changedBranches_.end() ; ++it) {
2845                 docstring const arg = '"' + it->first + '"' + " " + '"' + it->second + '"';
2846                 dispatch(FuncRequest(LFUN_BRANCHES_RENAME, arg));
2847         }
2848 }
2849
2850
2851 Dialog * createGuiDocument(GuiView & lv) { return new GuiDocument(lv); }
2852
2853
2854 } // namespace frontend
2855 } // namespace lyx
2856
2857 #include "moc_GuiDocument.cpp"