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