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