]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiDocument.cpp
Remove embedding stuff from Document>Settings.
[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         } else if (prefixIs(classname, LayoutFileList::embeddedPrefix)) {
1286                 int const ret = Alert::prompt(_("Embedded layout"),
1287                                 _("The layout file you have selected is an embedded layout that\n"
1288                                   "is embedded to a buffer. You cannot make use of it unless\n"
1289                                   "it is already embedded to this buffer.\n"),
1290                                   1, 1, _("&Set Layout"), _("&Cancel"));
1291                 if (ret == 1) {
1292                         setLayoutComboByIDString(bp_.baseClassID());
1293                         return;
1294                 }
1295         }
1296         // FIXME Note that by doing things this way, we load the TextClass
1297         // as soon as it is selected. So, if you use the scroll wheel when
1298         // sitting on the combo box, we'll load a lot of TextClass objects
1299         // very quickly. This could be changed.
1300         if (!bp_.setBaseClass(classname)) {
1301                 Alert::error(_("Error"), _("Unable to set document class."));
1302                 return;
1303         }
1304         if (lyxrc.auto_reset_options) {
1305                 if (applyPB->isEnabled()) {
1306                         int const ret = Alert::prompt(_("Unapplied changes"),
1307                                         _("Some changes in the dialog were not yet applied.\n"
1308                                         "If you do not apply now, they will be lost after this action."),
1309                                         1, 1, _("&Apply"), _("&Dismiss"));
1310                         if (ret == 0)
1311                                 applyView();
1312                 }
1313                 bp_.useClassDefaults();
1314                 forceUpdate();
1315         }
1316 }
1317
1318
1319 namespace {
1320         // This is an insanely complicated attempt to make this sort of thing
1321         // work with RTL languages.
1322         docstring formatStrVec(vector<string> const & v, docstring const & s) 
1323         {
1324                 //this mess formats the list as "v[0], v[1], ..., [s] v[n]"
1325                 int const vSize = v.size();
1326                 if (v.size() == 0)
1327                         return docstring();
1328                 else if (v.size() == 1) 
1329                         return from_ascii(v[0]);
1330                 else if (v.size() == 2) {
1331                         docstring retval = _("%1$s and %2$s");
1332                         retval = subst(retval, _("and"), s);
1333                         return bformat(retval, from_ascii(v[0]), from_ascii(v[1]));
1334                 }
1335                 //The idea here is to format all but the last two items...
1336                 docstring t2 = _("%1$s, %2$s");
1337                 docstring retval = from_ascii(v[0]);
1338                 for (int i = 1; i < vSize - 2; ++i)
1339                         retval = bformat(t2, retval, from_ascii(v[i])); 
1340                 //...and then to  plug them, and the last two, into this schema
1341                 docstring t = _("%1$s, %2$s, and %3$s");
1342                 t = subst(t, _("and"), s);
1343                 return bformat(t, retval, from_ascii(v[vSize - 2]), from_ascii(v[vSize - 1]));
1344         }
1345         
1346         vector<string> idsToNames(vector<string> const & idList)
1347         {
1348                 vector<string> retval;
1349                 vector<string>::const_iterator it  = idList.begin();
1350                 vector<string>::const_iterator end = idList.end();
1351                 for (; it != end; ++it) {
1352                         LyXModule const * const mod = moduleList[*it];
1353                         if (!mod)
1354                                 retval.push_back(*it + " (Unavailable)");
1355                         else
1356                                 retval.push_back(mod->getName());
1357                 }
1358                 return retval;
1359         }
1360 }
1361
1362
1363 void GuiDocument::updateModuleInfo()
1364 {
1365         selectionManager->update();
1366         
1367         //Module description
1368         bool const focusOnSelected = selectionManager->selectedFocused();
1369         QListView const * const lv = 
1370                         focusOnSelected ? latexModule->selectedLV : latexModule->availableLV;
1371         if (lv->selectionModel()->selectedIndexes().isEmpty()) {
1372                 latexModule->infoML->document()->clear();
1373                 return;
1374         }
1375         QModelIndex const & idx = lv->selectionModel()->currentIndex();
1376         GuiIdListModel const & idModel = 
1377                         focusOnSelected  ? modules_sel_model_ : modules_av_model_;
1378         string const modName = idModel.getIDString(idx.row());
1379         docstring desc = getModuleDescription(modName);
1380
1381         vector<string> pkgList = getPackageList(modName);
1382         docstring pkgdesc = formatStrVec(pkgList, _("and"));
1383         if (!pkgdesc.empty()) {
1384                 if (!desc.empty())
1385                         desc += "\n";
1386                 desc += bformat(_("Package(s) required: %1$s."), pkgdesc);
1387         }
1388
1389         pkgList = getRequiredList(modName);
1390         if (!pkgList.empty()) {
1391                 vector<string> const reqDescs = idsToNames(pkgList);
1392                 pkgdesc = formatStrVec(reqDescs, _("or"));
1393                 if (!desc.empty())
1394                         desc += "\n";
1395                 desc += bformat(_("Module required: %1$s."), pkgdesc);
1396         }
1397
1398         pkgList = getExcludedList(modName);
1399         if (!pkgList.empty()) {
1400                 vector<string> const reqDescs = idsToNames(pkgList);
1401                 pkgdesc = formatStrVec(reqDescs, _( "and"));
1402                 if (!desc.empty())
1403                         desc += "\n";
1404                 desc += bformat(_("Modules excluded: %1$s."), pkgdesc);
1405         }
1406
1407         if (!isModuleAvailable(modName)) {
1408                 if (!desc.empty())
1409                         desc += "\n";
1410                 desc += _("WARNING: Some packages are unavailable!");
1411         }
1412
1413         latexModule->infoML->document()->setPlainText(toqstr(desc));
1414 }
1415
1416
1417 void GuiDocument::updateNumbering()
1418 {
1419         DocumentClass const & tclass = bp_.documentClass();
1420
1421         numberingModule->tocTW->setUpdatesEnabled(false);
1422         numberingModule->tocTW->clear();
1423
1424         int const depth = numberingModule->depthSL->value();
1425         int const toc = numberingModule->tocSL->value();
1426         QString const no = qt_("No");
1427         QString const yes = qt_("Yes");
1428         QTreeWidgetItem * item = 0;
1429
1430         DocumentClass::const_iterator lit = tclass.begin();
1431         DocumentClass::const_iterator len = tclass.end();
1432         for (; lit != len; ++lit) {
1433                 int const toclevel = lit->toclevel;
1434                 if (toclevel != Layout::NOT_IN_TOC && lit->labeltype == LABEL_COUNTER) {
1435                         item = new QTreeWidgetItem(numberingModule->tocTW);
1436                         item->setText(0, toqstr(translateIfPossible(lit->name())));
1437                         item->setText(1, (toclevel <= depth) ? yes : no);
1438                         item->setText(2, (toclevel <= toc) ? yes : no);
1439                 }
1440         }
1441
1442         numberingModule->tocTW->setUpdatesEnabled(true);
1443         numberingModule->tocTW->update();
1444 }
1445
1446
1447 void GuiDocument::apply(BufferParams & params)
1448 {
1449         // preamble
1450         preambleModule->apply(params);
1451
1452         // biblio
1453         params.setCiteEngine(biblio::ENGINE_BASIC);
1454
1455         if (biblioModule->citeNatbibRB->isChecked()) {
1456                 bool const use_numerical_citations =
1457                         biblioModule->citeStyleCO->currentIndex();
1458                 if (use_numerical_citations)
1459                         params.setCiteEngine(biblio::ENGINE_NATBIB_NUMERICAL);
1460                 else
1461                         params.setCiteEngine(biblio::ENGINE_NATBIB_AUTHORYEAR);
1462
1463         } else if (biblioModule->citeJurabibRB->isChecked())
1464                 params.setCiteEngine(biblio::ENGINE_JURABIB);
1465
1466         params.use_bibtopic =
1467                 biblioModule->bibtopicCB->isChecked();
1468
1469         // language & quotes
1470         if (langModule->defaultencodingRB->isChecked()) {
1471                 params.inputenc = "auto";
1472         } else {
1473                 int i = langModule->encodingCO->currentIndex();
1474                 if (i == 0)
1475                         params.inputenc = "default";
1476                 else
1477                         params.inputenc =
1478                                 fromqstr(langModule->encodingCO->currentText());
1479         }
1480
1481         InsetQuotes::QuoteLanguage lga = InsetQuotes::EnglishQuotes;
1482         switch (langModule->quoteStyleCO->currentIndex()) {
1483         case 0:
1484                 lga = InsetQuotes::EnglishQuotes;
1485                 break;
1486         case 1:
1487                 lga = InsetQuotes::SwedishQuotes;
1488                 break;
1489         case 2:
1490                 lga = InsetQuotes::GermanQuotes;
1491                 break;
1492         case 3:
1493                 lga = InsetQuotes::PolishQuotes;
1494                 break;
1495         case 4:
1496                 lga = InsetQuotes::FrenchQuotes;
1497                 break;
1498         case 5:
1499                 lga = InsetQuotes::DanishQuotes;
1500                 break;
1501         }
1502         params.quotes_language = lga;
1503
1504         int const pos = langModule->languageCO->currentIndex();
1505         params.language = lyx::languages.getLanguage(fromqstr(lang_[pos]));
1506
1507         // numbering
1508         if (params.documentClass().hasTocLevels()) {
1509                 params.tocdepth = numberingModule->tocSL->value();
1510                 params.secnumdepth = numberingModule->depthSL->value();
1511         }
1512
1513         // bullets
1514         params.user_defined_bullet(0) = bulletsModule->getBullet(0);
1515         params.user_defined_bullet(1) = bulletsModule->getBullet(1);
1516         params.user_defined_bullet(2) = bulletsModule->getBullet(2);
1517         params.user_defined_bullet(3) = bulletsModule->getBullet(3);
1518
1519         // packages
1520         params.graphicsDriver =
1521                 tex_graphics[latexModule->psdriverCO->currentIndex()];
1522         
1523         // text layout
1524         int idx = latexModule->classCO->currentIndex();
1525         if (idx >= 0) {
1526                 string const classname = classes_model_.getIDString(idx);
1527                 params.setBaseClass(classname);
1528         }
1529
1530         // Modules
1531         params.clearLayoutModules();
1532         int const srows = modules_sel_model_.rowCount();
1533         vector<string> selModList;
1534         for (int i = 0; i < srows; ++i)
1535                 params.addLayoutModule(modules_sel_model_.getIDString(i));
1536
1537         if (mathsModule->amsautoCB->isChecked()) {
1538                 params.use_amsmath = BufferParams::package_auto;
1539         } else {
1540                 if (mathsModule->amsCB->isChecked())
1541                         params.use_amsmath = BufferParams::package_on;
1542                 else
1543                         params.use_amsmath = BufferParams::package_off;
1544         }
1545
1546         if (mathsModule->esintautoCB->isChecked())
1547                 params.use_esint = BufferParams::package_auto;
1548         else {
1549                 if (mathsModule->esintCB->isChecked())
1550                         params.use_esint = BufferParams::package_on;
1551                 else
1552                         params.use_esint = BufferParams::package_off;
1553         }
1554
1555         if (pageLayoutModule->pagestyleCO->currentIndex() == 0)
1556                 params.pagestyle = "default";
1557         else {
1558                 docstring style_gui =
1559                         qstring_to_ucs4(pageLayoutModule->pagestyleCO->currentText());
1560                 for (size_t i = 0; i < pagestyles.size(); ++i)
1561                         if (pagestyles[i].second == style_gui)
1562                                 params.pagestyle = pagestyles[i].first;
1563         }
1564
1565         switch (textLayoutModule->lspacingCO->currentIndex()) {
1566         case 0:
1567                 params.spacing().set(Spacing::Single);
1568                 break;
1569         case 1:
1570                 params.spacing().set(Spacing::Onehalf);
1571                 break;
1572         case 2:
1573                 params.spacing().set(Spacing::Double);
1574                 break;
1575         case 3:
1576                 params.spacing().set(Spacing::Other,
1577                         fromqstr(textLayoutModule->lspacingLE->text()));
1578                 break;
1579         }
1580
1581         if (textLayoutModule->twoColumnCB->isChecked())
1582                 params.columns = 2;
1583         else
1584                 params.columns = 1;
1585
1586         // text should have passed validation
1587         params.listings_params =
1588                 InsetListingsParams(fromqstr(textLayoutModule->listingsED->toPlainText())).params();
1589
1590         if (textLayoutModule->indentRB->isChecked())
1591                 params.paragraph_separation = BufferParams::ParagraphIndentSeparation;
1592         else
1593                 params.paragraph_separation = BufferParams::ParagraphSkipSeparation;
1594
1595         switch (textLayoutModule->skipCO->currentIndex()) {
1596         case 0:
1597                 params.setDefSkip(VSpace(VSpace::SMALLSKIP));
1598                 break;
1599         case 1:
1600                 params.setDefSkip(VSpace(VSpace::MEDSKIP));
1601                 break;
1602         case 2:
1603                 params.setDefSkip(VSpace(VSpace::BIGSKIP));
1604                 break;
1605         case 3:
1606         {
1607                 VSpace vs = VSpace(
1608                         widgetsToLength(textLayoutModule->skipLE,
1609                                 textLayoutModule->skipLengthCO)
1610                         );
1611                 params.setDefSkip(vs);
1612                 break;
1613         }
1614         default:
1615                 // DocumentDefskipCB assures that this never happens
1616                 // so Assert then !!!  - jbl
1617                 params.setDefSkip(VSpace(VSpace::MEDSKIP));
1618                 break;
1619         }
1620
1621         params.options =
1622                 fromqstr(latexModule->optionsLE->text());
1623
1624         params.float_placement = floatModule->get();
1625
1626         // fonts
1627         params.fontsRoman =
1628                 tex_fonts_roman[fontModule->fontsRomanCO->currentIndex()];
1629
1630         params.fontsSans =
1631                 tex_fonts_sans[fontModule->fontsSansCO->currentIndex()];
1632
1633         params.fontsTypewriter =
1634                 tex_fonts_monospaced[fontModule->fontsTypewriterCO->currentIndex()];
1635
1636         params.fontsSansScale = fontModule->scaleSansSB->value();
1637
1638         params.fontsTypewriterScale = fontModule->scaleTypewriterSB->value();
1639
1640         params.fontsSC = fontModule->fontScCB->isChecked();
1641
1642         params.fontsOSF = fontModule->fontOsfCB->isChecked();
1643
1644         params.fontsDefaultFamily = GuiDocument::fontfamilies[
1645                 fontModule->fontsDefaultCO->currentIndex()];
1646
1647         if (fontModule->fontsizeCO->currentIndex() == 0)
1648                 params.fontsize = "default";
1649         else
1650                 params.fontsize =
1651                         fromqstr(fontModule->fontsizeCO->currentText());
1652
1653         // paper
1654         params.papersize = PAPER_SIZE(
1655                 pageLayoutModule->papersizeCO->currentIndex());
1656
1657         // custom, A3, B3 and B4 paper sizes need geometry
1658         int psize = pageLayoutModule->papersizeCO->currentIndex();
1659         bool geom_papersize = (psize == 1 || psize == 5 || psize == 8 || psize == 9);
1660
1661         params.paperwidth = widgetsToLength(pageLayoutModule->paperwidthLE,
1662                 pageLayoutModule->paperwidthUnitCO);
1663
1664         params.paperheight = widgetsToLength(pageLayoutModule->paperheightLE,
1665                 pageLayoutModule->paperheightUnitCO);
1666
1667         if (pageLayoutModule->facingPagesCB->isChecked())
1668                 params.sides = TwoSides;
1669         else
1670                 params.sides = OneSide;
1671
1672         if (pageLayoutModule->landscapeRB->isChecked())
1673                 params.orientation = ORIENTATION_LANDSCAPE;
1674         else
1675                 params.orientation = ORIENTATION_PORTRAIT;
1676
1677         // margins
1678         params.use_geometry = !marginsModule->marginCB->isChecked()
1679                 || geom_papersize;
1680
1681         Ui::MarginsUi const * m = marginsModule;
1682
1683         params.leftmargin = widgetsToLength(m->innerLE, m->innerUnit);
1684         params.topmargin = widgetsToLength(m->topLE, m->topUnit);
1685         params.rightmargin = widgetsToLength(m->outerLE, m->outerUnit);
1686         params.bottommargin = widgetsToLength(m->bottomLE, m->bottomUnit);
1687         params.headheight = widgetsToLength(m->headheightLE, m->headheightUnit);
1688         params.headsep = widgetsToLength(m->headsepLE, m->headsepUnit);
1689         params.footskip = widgetsToLength(m->footskipLE, m->footskipUnit);
1690         params.columnsep = widgetsToLength(m->columnsepLE, m->columnsepUnit);
1691
1692         branchesModule->apply(params);
1693
1694         // PDF support
1695         PDFOptions & pdf = params.pdfoptions();
1696         pdf.use_hyperref = pdfSupportModule->use_hyperrefGB->isChecked();
1697         pdf.title = fromqstr(pdfSupportModule->titleLE->text());
1698         pdf.author = fromqstr(pdfSupportModule->authorLE->text());
1699         pdf.subject = fromqstr(pdfSupportModule->subjectLE->text());
1700         pdf.keywords = fromqstr(pdfSupportModule->keywordsLE->text());
1701
1702         pdf.bookmarks = pdfSupportModule->bookmarksGB->isChecked();
1703         pdf.bookmarksnumbered = pdfSupportModule->bookmarksnumberedCB->isChecked();
1704         pdf.bookmarksopen = pdfSupportModule->bookmarksopenGB->isChecked();
1705         pdf.bookmarksopenlevel = pdfSupportModule->bookmarksopenlevelSB->value();
1706
1707         pdf.breaklinks = pdfSupportModule->breaklinksCB->isChecked();
1708         pdf.pdfborder = pdfSupportModule->pdfborderCB->isChecked();
1709         pdf.pdfusetitle = pdfSupportModule->pdfusetitleCB->isChecked();
1710         pdf.colorlinks = pdfSupportModule->colorlinksCB->isChecked();
1711         pdf.backref = pdfSupportModule->backrefCB->isChecked();
1712         pdf.pagebackref = pdfSupportModule->pagebackrefCB->isChecked();
1713         if (pdfSupportModule->fullscreenCB->isChecked())
1714                 pdf.pagemode = pdf.pagemode_fullscreen;
1715         else
1716                 pdf.pagemode.clear();
1717         pdf.quoted_options = pdf.quoted_options_check(
1718                                 fromqstr(pdfSupportModule->optionsLE->text()));
1719 }
1720
1721
1722 static int findPos(QStringList const & vec, QString const & val)
1723 {
1724         for (int i = 0; i != vec.size(); ++i)
1725                 if (vec[i] == val)
1726                         return i;
1727         return 0;
1728 }
1729
1730
1731 void GuiDocument::updateParams()
1732 {
1733         updateParams(bp_);
1734 }
1735
1736
1737 void GuiDocument::updateParams(BufferParams const & params)
1738 {
1739         // set the default unit
1740         Length::UNIT defaultUnit = Length::CM;
1741         switch (lyxrc.default_papersize) {
1742                 case PAPER_DEFAULT: break;
1743
1744                 case PAPER_USLETTER:
1745                 case PAPER_USLEGAL:
1746                 case PAPER_USEXECUTIVE:
1747                         defaultUnit = Length::IN;
1748                         break;
1749
1750                 case PAPER_A3:
1751                 case PAPER_A4:
1752                 case PAPER_A5:
1753                 case PAPER_B3:
1754                 case PAPER_B4:
1755                 case PAPER_B5:
1756                         defaultUnit = Length::CM;
1757                         break;
1758                 case PAPER_CUSTOM:
1759                         break;
1760         }
1761
1762         // preamble
1763         preambleModule->update(params, id());
1764
1765         // biblio
1766         biblioModule->citeDefaultRB->setChecked(
1767                 params.citeEngine() == biblio::ENGINE_BASIC);
1768
1769         biblioModule->citeNatbibRB->setChecked(
1770                 params.citeEngine() == biblio::ENGINE_NATBIB_NUMERICAL ||
1771                 params.citeEngine() == biblio::ENGINE_NATBIB_AUTHORYEAR);
1772
1773         biblioModule->citeStyleCO->setCurrentIndex(
1774                 params.citeEngine() == biblio::ENGINE_NATBIB_NUMERICAL);
1775
1776         biblioModule->citeJurabibRB->setChecked(
1777                 params.citeEngine() == biblio::ENGINE_JURABIB);
1778
1779         biblioModule->bibtopicCB->setChecked(
1780                 params.use_bibtopic);
1781
1782         // language & quotes
1783         int const pos = findPos(lang_, toqstr(params.language->lang()));
1784         langModule->languageCO->setCurrentIndex(pos);
1785
1786         langModule->quoteStyleCO->setCurrentIndex(
1787                 params.quotes_language);
1788
1789         bool default_enc = true;
1790         if (params.inputenc != "auto") {
1791                 default_enc = false;
1792                 if (params.inputenc == "default") {
1793                         langModule->encodingCO->setCurrentIndex(0);
1794                 } else {
1795                         int const i = langModule->encodingCO->findText(
1796                                         toqstr(params.inputenc));
1797                         if (i >= 0)
1798                                 langModule->encodingCO->setCurrentIndex(i);
1799                         else
1800                                 // unknown encoding. Set to default.
1801                                 default_enc = true;
1802                 }
1803         }
1804         langModule->defaultencodingRB->setChecked(default_enc);
1805         langModule->otherencodingRB->setChecked(!default_enc);
1806
1807         // numbering
1808         int const min_toclevel = documentClass().min_toclevel();
1809         int const max_toclevel = documentClass().max_toclevel();
1810         if (documentClass().hasTocLevels()) {
1811                 numberingModule->setEnabled(true);
1812                 numberingModule->depthSL->setMinimum(min_toclevel - 1);
1813                 numberingModule->depthSL->setMaximum(max_toclevel);
1814                 numberingModule->depthSL->setValue(params.secnumdepth);
1815                 numberingModule->tocSL->setMaximum(min_toclevel - 1);
1816                 numberingModule->tocSL->setMaximum(max_toclevel);
1817                 numberingModule->tocSL->setValue(params.tocdepth);
1818                 updateNumbering();
1819         } else {
1820                 numberingModule->setEnabled(false);
1821                 numberingModule->tocTW->clear();
1822         }
1823
1824         // bullets
1825         bulletsModule->setBullet(0, params.user_defined_bullet(0));
1826         bulletsModule->setBullet(1, params.user_defined_bullet(1));
1827         bulletsModule->setBullet(2, params.user_defined_bullet(2));
1828         bulletsModule->setBullet(3, params.user_defined_bullet(3));
1829         bulletsModule->init();
1830
1831         // packages
1832         int nitem = findToken(tex_graphics, params.graphicsDriver);
1833         if (nitem >= 0)
1834                 latexModule->psdriverCO->setCurrentIndex(nitem);
1835         updateModuleInfo();
1836         
1837         mathsModule->amsCB->setChecked(
1838                 params.use_amsmath == BufferParams::package_on);
1839         mathsModule->amsautoCB->setChecked(
1840                 params.use_amsmath == BufferParams::package_auto);
1841
1842         mathsModule->esintCB->setChecked(
1843                 params.use_esint == BufferParams::package_on);
1844         mathsModule->esintautoCB->setChecked(
1845                 params.use_esint == BufferParams::package_auto);
1846
1847         switch (params.spacing().getSpace()) {
1848                 case Spacing::Other: nitem = 3; break;
1849                 case Spacing::Double: nitem = 2; break;
1850                 case Spacing::Onehalf: nitem = 1; break;
1851                 case Spacing::Default: case Spacing::Single: nitem = 0; break;
1852         }
1853
1854         // text layout
1855         string const & layoutID = params.baseClassID();
1856         setLayoutComboByIDString(layoutID);
1857
1858         updatePagestyle(documentClass().opt_pagestyle(),
1859                                  params.pagestyle);
1860
1861         textLayoutModule->lspacingCO->setCurrentIndex(nitem);
1862         if (params.spacing().getSpace() == Spacing::Other) {
1863                 textLayoutModule->lspacingLE->setText(
1864                         toqstr(params.spacing().getValueAsString()));
1865         }
1866         setLSpacing(nitem);
1867
1868         if (params.paragraph_separation == BufferParams::ParagraphIndentSeparation)
1869                 textLayoutModule->indentRB->setChecked(true);
1870         else
1871                 textLayoutModule->skipRB->setChecked(true);
1872
1873         int skip = 0;
1874         switch (params.getDefSkip().kind()) {
1875         case VSpace::SMALLSKIP:
1876                 skip = 0;
1877                 break;
1878         case VSpace::MEDSKIP:
1879                 skip = 1;
1880                 break;
1881         case VSpace::BIGSKIP:
1882                 skip = 2;
1883                 break;
1884         case VSpace::LENGTH:
1885         {
1886                 skip = 3;
1887                 string const length = params.getDefSkip().asLyXCommand();
1888                 lengthToWidgets(textLayoutModule->skipLE,
1889                         textLayoutModule->skipLengthCO,
1890                         length, defaultUnit);
1891                 break;
1892         }
1893         default:
1894                 skip = 0;
1895                 break;
1896         }
1897         textLayoutModule->skipCO->setCurrentIndex(skip);
1898         setSkip(skip);
1899
1900         textLayoutModule->twoColumnCB->setChecked(
1901                 params.columns == 2);
1902
1903         // break listings_params to multiple lines
1904         string lstparams =
1905                 InsetListingsParams(params.listings_params).separatedParams();
1906         textLayoutModule->listingsED->setPlainText(toqstr(lstparams));
1907
1908         if (!params.options.empty()) {
1909                 latexModule->optionsLE->setText(
1910                         toqstr(params.options));
1911         } else {
1912                 latexModule->optionsLE->setText(QString());
1913         }
1914
1915         floatModule->set(params.float_placement);
1916
1917         // Fonts
1918         updateFontsize(documentClass().opt_fontsize(),
1919                         params.fontsize);
1920
1921         int n = findToken(tex_fonts_roman, params.fontsRoman);
1922         if (n >= 0) {
1923                 fontModule->fontsRomanCO->setCurrentIndex(n);
1924                 romanChanged(n);
1925         }
1926
1927         n = findToken(tex_fonts_sans, params.fontsSans);
1928         if (n >= 0)     {
1929                 fontModule->fontsSansCO->setCurrentIndex(n);
1930                 sansChanged(n);
1931         }
1932
1933         n = findToken(tex_fonts_monospaced, params.fontsTypewriter);
1934         if (n >= 0) {
1935                 fontModule->fontsTypewriterCO->setCurrentIndex(n);
1936                 ttChanged(n);
1937         }
1938
1939         fontModule->fontScCB->setChecked(params.fontsSC);
1940         fontModule->fontOsfCB->setChecked(params.fontsOSF);
1941         fontModule->scaleSansSB->setValue(params.fontsSansScale);
1942         fontModule->scaleTypewriterSB->setValue(params.fontsTypewriterScale);
1943         n = findToken(GuiDocument::fontfamilies, params.fontsDefaultFamily);
1944         if (n >= 0)
1945                 fontModule->fontsDefaultCO->setCurrentIndex(n);
1946
1947         // paper
1948         int const psize = params.papersize;
1949         pageLayoutModule->papersizeCO->setCurrentIndex(psize);
1950         setCustomPapersize(psize);
1951
1952         bool const landscape =
1953                 params.orientation == ORIENTATION_LANDSCAPE;
1954         pageLayoutModule->landscapeRB->setChecked(landscape);
1955         pageLayoutModule->portraitRB->setChecked(!landscape);
1956
1957         pageLayoutModule->facingPagesCB->setChecked(
1958                 params.sides == TwoSides);
1959
1960
1961         lengthToWidgets(pageLayoutModule->paperwidthLE,
1962                 pageLayoutModule->paperwidthUnitCO, params.paperwidth, defaultUnit);
1963
1964         lengthToWidgets(pageLayoutModule->paperheightLE,
1965                 pageLayoutModule->paperheightUnitCO, params.paperheight, defaultUnit);
1966
1967         // margins
1968         Ui::MarginsUi * m = marginsModule;
1969
1970         setMargins(!params.use_geometry);
1971
1972         lengthToWidgets(m->topLE, m->topUnit,
1973                 params.topmargin, defaultUnit);
1974
1975         lengthToWidgets(m->bottomLE, m->bottomUnit,
1976                 params.bottommargin, defaultUnit);
1977
1978         lengthToWidgets(m->innerLE, m->innerUnit,
1979                 params.leftmargin, defaultUnit);
1980
1981         lengthToWidgets(m->outerLE, m->outerUnit,
1982                 params.rightmargin, defaultUnit);
1983
1984         lengthToWidgets(m->headheightLE, m->headheightUnit,
1985                 params.headheight, defaultUnit);
1986
1987         lengthToWidgets(m->headsepLE, m->headsepUnit,
1988                 params.headsep, defaultUnit);
1989
1990         lengthToWidgets(m->footskipLE, m->footskipUnit,
1991                 params.footskip, defaultUnit);
1992
1993         lengthToWidgets(m->columnsepLE, m->columnsepUnit,
1994                 params.columnsep, defaultUnit);
1995
1996         branchesModule->update(params);
1997
1998         // PDF support
1999         PDFOptions const & pdf = params.pdfoptions();
2000         pdfSupportModule->use_hyperrefGB->setChecked(pdf.use_hyperref);
2001         pdfSupportModule->titleLE->setText(toqstr(pdf.title));
2002         pdfSupportModule->authorLE->setText(toqstr(pdf.author));
2003         pdfSupportModule->subjectLE->setText(toqstr(pdf.subject));
2004         pdfSupportModule->keywordsLE->setText(toqstr(pdf.keywords));
2005
2006         pdfSupportModule->bookmarksGB->setChecked(pdf.bookmarks);
2007         pdfSupportModule->bookmarksnumberedCB->setChecked(pdf.bookmarksnumbered);
2008         pdfSupportModule->bookmarksopenGB->setChecked(pdf.bookmarksopen);
2009
2010         pdfSupportModule->bookmarksopenlevelSB->setValue(pdf.bookmarksopenlevel);
2011
2012         pdfSupportModule->breaklinksCB->setChecked(pdf.breaklinks);
2013         pdfSupportModule->pdfborderCB->setChecked(pdf.pdfborder);
2014         pdfSupportModule->pdfusetitleCB->setChecked(pdf.pdfusetitle);
2015         pdfSupportModule->colorlinksCB->setChecked(pdf.colorlinks);
2016         pdfSupportModule->backrefCB->setChecked(pdf.backref);
2017         pdfSupportModule->pagebackrefCB->setChecked(pdf.pagebackref);
2018         pdfSupportModule->fullscreenCB->setChecked
2019                 (pdf.pagemode == pdf.pagemode_fullscreen);
2020
2021         pdfSupportModule->optionsLE->setText(
2022                 toqstr(pdf.quoted_options));
2023 }
2024
2025
2026 void GuiDocument::applyView()
2027 {
2028         apply(params());
2029 }
2030
2031
2032 void GuiDocument::saveDocDefault()
2033 {
2034         // we have to apply the params first
2035         applyView();
2036         saveAsDefault();
2037 }
2038
2039
2040 void GuiDocument::updateAvailableModules() 
2041 {
2042         modules_av_model_.clear();
2043         vector<modInfoStruct> const & modInfoList = getModuleInfo();
2044         int const mSize = modInfoList.size();
2045         for (int i = 0; i != mSize; ++i) {
2046                 modInfoStruct const & modInfo = modInfoList[i];
2047                 modules_av_model_.insertRow(i, modInfo.name, modInfo.id, 
2048                                 modInfo.description);
2049         }
2050 }
2051
2052
2053 void GuiDocument::updateSelectedModules() 
2054 {
2055         // and selected ones, too
2056         modules_sel_model_.clear();
2057         vector<modInfoStruct> const selModList = getSelectedModules();
2058         int const sSize = selModList.size();
2059         for (int i = 0; i != sSize; ++i) {
2060                 modInfoStruct const & modInfo = selModList[i];
2061                 modules_sel_model_.insertRow(i, modInfo.name, modInfo.id,
2062                                 modInfo.description);
2063         }
2064 }
2065
2066
2067 void GuiDocument::updateContents()
2068 {
2069         if (id() == current_id_)
2070                 return;
2071
2072         updateAvailableModules();
2073         updateSelectedModules();
2074         
2075         //FIXME It'd be nice to make sure here that the selected
2076         //modules are consistent: That required modules are actually
2077         //selected, and that we don't have conflicts. If so, we could
2078         //at least pop up a warning.
2079         updateParams(bp_);
2080         current_id_ = id();
2081 }
2082
2083
2084 void GuiDocument::forceUpdate()
2085 {
2086         // reset to force dialog update
2087         current_id_ = 0;
2088         updateContents();
2089 }
2090
2091
2092 void GuiDocument::useClassDefaults()
2093 {
2094         if (applyPB->isEnabled()) {
2095                 int const ret = Alert::prompt(_("Unapplied changes"),
2096                                 _("Some changes in the dialog were not yet applied.\n"
2097                                   "If you do not apply now, they will be lost after this action."),
2098                                 1, 1, _("&Apply"), _("&Dismiss"));
2099                 if (ret == 0)
2100                         applyView();
2101         }
2102
2103         int idx = latexModule->classCO->currentIndex();
2104         string const classname = classes_model_.getIDString(idx);
2105         if (!bp_.setBaseClass(classname)) {
2106                 Alert::error(_("Error"), _("Unable to set document class."));
2107                 return;
2108         }
2109         bp_.useClassDefaults();
2110         forceUpdate();
2111 }
2112
2113
2114 void GuiDocument::setLayoutComboByIDString(std::string const & idString)
2115 {
2116         int idx = classes_model_.findIDString(idString);
2117         if (idx < 0)
2118                 Alert::warning(_("Can't set layout!"), 
2119                         bformat(_("Unable to set layout for ID: %1$s"), from_utf8(idString)));
2120         else 
2121                 latexModule->classCO->setCurrentIndex(idx);
2122 }
2123
2124
2125 bool GuiDocument::isValid()
2126 {
2127         return validate_listings_params().empty()
2128                 && (textLayoutModule->skipCO->currentIndex() != 3
2129                         || !textLayoutModule->skipLE->text().isEmpty());
2130 }
2131
2132
2133 char const * const GuiDocument::fontfamilies[5] = {
2134         "default", "rmdefault", "sfdefault", "ttdefault", ""
2135 };
2136
2137
2138 char const * GuiDocument::fontfamilies_gui[5] = {
2139         N_("Default"), N_("Roman"), N_("Sans Serif"), N_("Typewriter"), ""
2140 };
2141
2142
2143 bool GuiDocument::initialiseParams(string const &)
2144 {
2145         bp_ = buffer().params();
2146         loadModuleInfo();
2147         return true;
2148 }
2149
2150
2151 void GuiDocument::clearParams()
2152 {
2153         bp_ = BufferParams();
2154 }
2155
2156
2157 BufferId GuiDocument::id() const
2158 {
2159         return &buffer();
2160 }
2161
2162
2163 vector<GuiDocument::modInfoStruct> const & GuiDocument::getModuleInfo()
2164 {
2165         return moduleNames_;
2166 }
2167
2168
2169 vector<GuiDocument::modInfoStruct> const GuiDocument::getSelectedModules()
2170 {
2171         vector<string> const & mods = params().getModules();
2172         vector<string>::const_iterator it =  mods.begin();
2173         vector<string>::const_iterator end = mods.end();
2174         vector<modInfoStruct> mInfo;
2175         for (; it != end; ++it) {
2176                 modInfoStruct m;
2177                 m.id = *it;
2178                 LyXModule * mod = moduleList[*it];
2179                 if (mod)
2180                         m.name = qt_(mod->getName());
2181                 else 
2182                         m.name = toqstr(*it) + toqstr(" (") + qt_("Not Found") + toqstr(")");
2183                 mInfo.push_back(m);
2184         }
2185         return mInfo;
2186 }
2187
2188
2189 DocumentClass const & GuiDocument::documentClass() const
2190 {
2191         return bp_.documentClass();
2192 }
2193
2194
2195 static void dispatch_bufferparams(Dialog const & dialog,
2196         BufferParams const & bp, FuncCode lfun)
2197 {
2198         ostringstream ss;
2199         ss << "\\begin_header\n";
2200         bp.writeFile(ss);
2201         ss << "\\end_header\n";
2202         dialog.dispatch(FuncRequest(lfun, ss.str()));
2203 }
2204
2205
2206 void GuiDocument::dispatchParams()
2207 {
2208         // This must come first so that a language change is correctly noticed
2209         setLanguage();
2210
2211         // Apply the BufferParams. Note that this will set the base class
2212         // and then update the buffer's layout.
2213         dispatch_bufferparams(*this, params(), LFUN_BUFFER_PARAMS_APPLY);
2214
2215         // Generate the colours requested by each new branch.
2216         BranchList & branchlist = params().branchlist();
2217         if (!branchlist.empty()) {
2218                 BranchList::const_iterator it = branchlist.begin();
2219                 BranchList::const_iterator const end = branchlist.end();
2220                 for (; it != end; ++it) {
2221                         docstring const & current_branch = it->getBranch();
2222                         Branch const * branch = branchlist.find(current_branch);
2223                         string const x11hexname = X11hexname(branch->getColor());
2224                         // display the new color
2225                         docstring const str = current_branch + ' ' + from_ascii(x11hexname);
2226                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
2227                 }
2228
2229                 // Open insets of selected branches, close deselected ones
2230                 dispatch(FuncRequest(LFUN_ALL_INSETS_TOGGLE,
2231                         "assign branch"));
2232         }
2233         // FIXME: If we used an LFUN, we would not need those two lines:
2234         bufferview()->processUpdateFlags(Update::Force | Update::FitCursor);
2235 }
2236
2237
2238 void GuiDocument::setLanguage() const
2239 {
2240         Language const * const newL = bp_.language;
2241         if (buffer().params().language == newL)
2242                 return;
2243
2244         string const & lang_name = newL->lang();
2245         dispatch(FuncRequest(LFUN_BUFFER_LANGUAGE, lang_name));
2246 }
2247
2248
2249 void GuiDocument::saveAsDefault() const
2250 {
2251         dispatch_bufferparams(*this, params(), LFUN_BUFFER_SAVE_AS_DEFAULT);
2252 }
2253
2254
2255 bool GuiDocument::isFontAvailable(string const & font) const
2256 {
2257         if (font == "default" || font == "cmr"
2258             || font == "cmss" || font == "cmtt")
2259                 // these are standard
2260                 return true;
2261         if (font == "lmodern" || font == "lmss" || font == "lmtt")
2262                 return LaTeXFeatures::isAvailable("lmodern");
2263         if (font == "times" || font == "palatino"
2264                  || font == "helvet" || font == "courier")
2265                 return LaTeXFeatures::isAvailable("psnfss");
2266         if (font == "cmbr" || font == "cmtl")
2267                 return LaTeXFeatures::isAvailable("cmbright");
2268         if (font == "utopia")
2269                 return LaTeXFeatures::isAvailable("utopia")
2270                         || LaTeXFeatures::isAvailable("fourier");
2271         if (font == "beraserif" || font == "berasans"
2272                 || font == "beramono")
2273                 return LaTeXFeatures::isAvailable("bera");
2274         return LaTeXFeatures::isAvailable(font);
2275 }
2276
2277
2278 bool GuiDocument::providesOSF(string const & font) const
2279 {
2280         if (font == "cmr")
2281                 return isFontAvailable("eco");
2282         if (font == "palatino")
2283                 return isFontAvailable("mathpazo");
2284         return false;
2285 }
2286
2287
2288 bool GuiDocument::providesSC(string const & font) const
2289 {
2290         if (font == "palatino")
2291                 return isFontAvailable("mathpazo");
2292         if (font == "utopia")
2293                 return isFontAvailable("fourier");
2294         return false;
2295 }
2296
2297
2298 bool GuiDocument::providesScale(string const & font) const
2299 {
2300         return font == "helvet" || font == "luximono"
2301                 || font == "berasans"  || font == "beramono";
2302 }
2303
2304
2305 void GuiDocument::loadModuleInfo()
2306 {
2307         moduleNames_.clear();
2308         LyXModuleList::const_iterator it  = moduleList.begin();
2309         LyXModuleList::const_iterator end = moduleList.end();
2310         for (; it != end; ++it) {
2311                 modInfoStruct m;
2312                 m.id = it->getID();
2313                 m.name = qt_(it->getName());
2314                 // this is supposed to give us the first sentence of the description
2315                 QString desc = qt_(it->getDescription());
2316                 int const pos = desc.indexOf(".");
2317                 if (pos > 0)
2318                         desc.truncate(pos + 1);
2319                 m.description = desc;
2320                 moduleNames_.push_back(m);
2321         }
2322 }
2323
2324
2325 Dialog * createGuiDocument(GuiView & lv) { return new GuiDocument(lv); }
2326
2327
2328 } // namespace frontend
2329 } // namespace lyx
2330
2331 #include "GuiDocument_moc.cpp"