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