]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiDocument.cpp
Give us some useful tooltips for modules.
[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         // embedded files
928         embeddedFilesModule = new UiWidget<Ui::EmbeddedFilesUi>;
929         connect(embeddedFilesModule->addPB, SIGNAL(clicked()),
930                 this, SLOT(addExtraEmbeddedFile()));
931         connect(embeddedFilesModule->removePB, SIGNAL(clicked()),
932                 this, SLOT(removeExtraEmbeddedFile()));
933
934         // PDF support
935         pdfSupportModule = new UiWidget<Ui::PDFSupportUi>;
936
937         connect(pdfSupportModule->use_hyperrefGB, SIGNAL(toggled(bool)),
938                 this, SLOT(change_adaptor()));
939         connect(pdfSupportModule->titleLE, SIGNAL(textChanged(const QString &)),
940                 this, SLOT(change_adaptor()));
941         connect(pdfSupportModule->authorLE, SIGNAL(textChanged(const QString &)),
942                 this, SLOT(change_adaptor()));
943         connect(pdfSupportModule->subjectLE, SIGNAL(textChanged(const QString &)),
944                 this, SLOT(change_adaptor()));
945         connect(pdfSupportModule->keywordsLE, SIGNAL(textChanged(const QString &)),
946                 this, SLOT(change_adaptor()));
947         connect(pdfSupportModule->bookmarksGB, SIGNAL(toggled(bool)),
948                 this, SLOT(change_adaptor()));
949         connect(pdfSupportModule->bookmarksnumberedCB, SIGNAL(toggled(bool)),
950                 this, SLOT(change_adaptor()));
951         connect(pdfSupportModule->bookmarksopenGB, SIGNAL(toggled(bool)),
952                 this, SLOT(change_adaptor()));
953         connect(pdfSupportModule->bookmarksopenlevelSB, SIGNAL(valueChanged(int)),
954                 this, SLOT(change_adaptor()));
955         connect(pdfSupportModule->breaklinksCB, SIGNAL(toggled(bool)),
956                 this, SLOT(change_adaptor()));
957         connect(pdfSupportModule->pdfborderCB, SIGNAL(toggled(bool)),
958                 this, SLOT(change_adaptor()));
959         connect(pdfSupportModule->colorlinksCB, SIGNAL(toggled(bool)),
960                 this, SLOT(change_adaptor()));
961         connect(pdfSupportModule->backrefCB, SIGNAL(toggled(bool)),
962                 this, SLOT(change_adaptor()));
963         connect(pdfSupportModule->pdfusetitleCB, SIGNAL(toggled(bool)),
964                 this, SLOT(change_adaptor()));
965         connect(pdfSupportModule->pagebackrefCB, SIGNAL(toggled(bool)),
966                 this, SLOT(change_adaptor()));
967         connect(pdfSupportModule->fullscreenCB, SIGNAL(toggled(bool)),
968                 this, SLOT(change_adaptor()));
969         connect(pdfSupportModule->optionsLE, SIGNAL(textChanged(const QString &)),
970                 this, SLOT(change_adaptor()));
971
972         // float
973         floatModule = new FloatPlacement;
974         connect(floatModule, SIGNAL(changed()),
975                 this, SLOT(change_adaptor()));
976
977         docPS->addPanel(latexModule, qt_("Document Class"));
978         docPS->addPanel(fontModule, qt_("Fonts"));
979         docPS->addPanel(textLayoutModule, qt_("Text Layout"));
980         docPS->addPanel(pageLayoutModule, qt_("Page Layout"));
981         docPS->addPanel(marginsModule, qt_("Page Margins"));
982         docPS->addPanel(langModule, qt_("Language"));
983         docPS->addPanel(numberingModule, qt_("Numbering & TOC"));
984         docPS->addPanel(biblioModule, qt_("Bibliography"));
985         docPS->addPanel(pdfSupportModule, qt_("PDF Properties"));
986         docPS->addPanel(mathsModule, qt_("Math Options"));
987         docPS->addPanel(floatModule, qt_("Float Placement"));
988         docPS->addPanel(bulletsModule, qt_("Bullets"));
989         docPS->addPanel(branchesModule, qt_("Branches"));
990         docPS->addPanel(embeddedFilesModule, qt_("Embedded Files"));
991         docPS->addPanel(preambleModule, qt_("LaTeX Preamble"));
992         docPS->setCurrentPanel(qt_("Document Class"));
993 // FIXME: hack to work around resizing bug in Qt >= 4.2
994 // bug verified with Qt 4.2.{0-3} (JSpitzm)
995 #if QT_VERSION >= 0x040200
996         docPS->updateGeometry();
997 #endif
998 }
999
1000
1001 void GuiDocument::showPreamble()
1002 {
1003         docPS->setCurrentPanel(qt_("LaTeX Preamble"));
1004 }
1005
1006
1007 void GuiDocument::saveDefaultClicked()
1008 {
1009         saveDocDefault();
1010 }
1011
1012
1013 void GuiDocument::useDefaultsClicked()
1014 {
1015         useClassDefaults();
1016 }
1017
1018
1019 void GuiDocument::change_adaptor()
1020 {
1021         changed();
1022 }
1023
1024
1025 docstring GuiDocument::validate_listings_params()
1026 {
1027         // use a cache here to avoid repeated validation
1028         // of the same parameters
1029         static string param_cache = string();
1030         static docstring msg_cache = docstring();
1031         
1032         if (textLayoutModule->bypassCB->isChecked())
1033                 return docstring();
1034
1035         string params = fromqstr(textLayoutModule->listingsED->toPlainText());
1036         if (params != param_cache) {
1037                 param_cache = params;
1038                 msg_cache = InsetListingsParams(params).validate();
1039         }
1040         return msg_cache;
1041 }
1042
1043
1044 void GuiDocument::set_listings_msg()
1045 {
1046         static bool isOK = true;
1047         docstring msg = validate_listings_params();
1048         if (msg.empty()) {
1049                 if (isOK)
1050                         return;
1051                 isOK = true;
1052                 // listingsTB->setTextColor("black");
1053                 textLayoutModule->listingsTB->setPlainText(
1054                         qt_("Input listings parameters on the right. Enter ? for a list of parameters."));
1055         } else {
1056                 isOK = false;
1057                 // listingsTB->setTextColor("red");
1058                 textLayoutModule->listingsTB->setPlainText(toqstr(msg));
1059         }
1060 }
1061
1062
1063 void GuiDocument::setLSpacing(int item)
1064 {
1065         textLayoutModule->lspacingLE->setEnabled(item == 3);
1066 }
1067
1068
1069 void GuiDocument::setSkip(int item)
1070 {
1071         bool const enable = (item == 3);
1072         textLayoutModule->skipLE->setEnabled(enable);
1073         textLayoutModule->skipLengthCO->setEnabled(enable);
1074 }
1075
1076
1077 void GuiDocument::enableSkip(bool skip)
1078 {
1079         textLayoutModule->skipCO->setEnabled(skip);
1080         textLayoutModule->skipLE->setEnabled(skip);
1081         textLayoutModule->skipLengthCO->setEnabled(skip);
1082         if (skip)
1083                 setSkip(textLayoutModule->skipCO->currentIndex());
1084 }
1085
1086 void GuiDocument::portraitChanged()
1087 {
1088         setMargins(pageLayoutModule->papersizeCO->currentIndex());
1089 }
1090
1091 void GuiDocument::setMargins(bool custom)
1092 {
1093         marginsModule->marginCB->setChecked(custom);
1094         setCustomMargins(custom);
1095 }
1096
1097
1098 void GuiDocument::setCustomPapersize(int papersize)
1099 {
1100         bool const custom = (papersize == 1);
1101
1102         pageLayoutModule->paperwidthL->setEnabled(custom);
1103         pageLayoutModule->paperwidthLE->setEnabled(custom);
1104         pageLayoutModule->paperwidthUnitCO->setEnabled(custom);
1105         pageLayoutModule->paperheightL->setEnabled(custom);
1106         pageLayoutModule->paperheightLE->setEnabled(custom);
1107         pageLayoutModule->paperheightLE->setFocus();
1108         pageLayoutModule->paperheightUnitCO->setEnabled(custom);
1109 }
1110
1111
1112 void GuiDocument::setColSep()
1113 {
1114         setCustomMargins(marginsModule->marginCB->checkState() == Qt::Checked);
1115 }
1116
1117
1118 void GuiDocument::setCustomMargins(bool custom)
1119 {
1120         marginsModule->topL->setEnabled(!custom);
1121         marginsModule->topLE->setEnabled(!custom);
1122         marginsModule->topUnit->setEnabled(!custom);
1123
1124         marginsModule->bottomL->setEnabled(!custom);
1125         marginsModule->bottomLE->setEnabled(!custom);
1126         marginsModule->bottomUnit->setEnabled(!custom);
1127
1128         marginsModule->innerL->setEnabled(!custom);
1129         marginsModule->innerLE->setEnabled(!custom);
1130         marginsModule->innerUnit->setEnabled(!custom);
1131
1132         marginsModule->outerL->setEnabled(!custom);
1133         marginsModule->outerLE->setEnabled(!custom);
1134         marginsModule->outerUnit->setEnabled(!custom);
1135
1136         marginsModule->headheightL->setEnabled(!custom);
1137         marginsModule->headheightLE->setEnabled(!custom);
1138         marginsModule->headheightUnit->setEnabled(!custom);
1139
1140         marginsModule->headsepL->setEnabled(!custom);
1141         marginsModule->headsepLE->setEnabled(!custom);
1142         marginsModule->headsepUnit->setEnabled(!custom);
1143
1144         marginsModule->footskipL->setEnabled(!custom);
1145         marginsModule->footskipLE->setEnabled(!custom);
1146         marginsModule->footskipUnit->setEnabled(!custom);
1147
1148         bool const enableColSep = !custom && 
1149                         textLayoutModule->twoColumnCB->checkState() == Qt::Checked;
1150         marginsModule->columnsepL->setEnabled(enableColSep);
1151         marginsModule->columnsepLE->setEnabled(enableColSep);
1152         marginsModule->columnsepUnit->setEnabled(enableColSep);
1153 }
1154
1155
1156 void GuiDocument::updateFontsize(string const & items, string const & sel)
1157 {
1158         fontModule->fontsizeCO->clear();
1159         fontModule->fontsizeCO->addItem(qt_("Default"));
1160
1161         for (int n = 0; !token(items,'|',n).empty(); ++n)
1162                 fontModule->fontsizeCO->
1163                         addItem(toqstr(token(items,'|',n)));
1164
1165         for (int n = 0; n < fontModule->fontsizeCO->count(); ++n) {
1166                 if (fromqstr(fontModule->fontsizeCO->itemText(n)) == sel) {
1167                         fontModule->fontsizeCO->setCurrentIndex(n);
1168                         break;
1169                 }
1170         }
1171 }
1172
1173
1174 void GuiDocument::romanChanged(int item)
1175 {
1176         string const font = tex_fonts_roman[item];
1177         fontModule->fontScCB->setEnabled(providesSC(font));
1178         fontModule->fontOsfCB->setEnabled(providesOSF(font));
1179 }
1180
1181
1182 void GuiDocument::sansChanged(int item)
1183 {
1184         string const font = tex_fonts_sans[item];
1185         bool scaleable = providesScale(font);
1186         fontModule->scaleSansSB->setEnabled(scaleable);
1187         fontModule->scaleSansLA->setEnabled(scaleable);
1188 }
1189
1190
1191 void GuiDocument::ttChanged(int item)
1192 {
1193         string const font = tex_fonts_monospaced[item];
1194         bool scaleable = providesScale(font);
1195         fontModule->scaleTypewriterSB->setEnabled(scaleable);
1196         fontModule->scaleTypewriterLA->setEnabled(scaleable);
1197 }
1198
1199
1200 void GuiDocument::updatePagestyle(string const & items, string const & sel)
1201 {
1202         pagestyles.clear();
1203         pageLayoutModule->pagestyleCO->clear();
1204         pageLayoutModule->pagestyleCO->addItem(qt_("Default"));
1205
1206         for (int n = 0; !token(items,'|',n).empty(); ++n) {
1207                 string style = token(items, '|', n);
1208                 docstring style_gui = _(style);
1209                 pagestyles.push_back(pair<string, docstring>(style, style_gui));
1210                 pageLayoutModule->pagestyleCO->addItem(toqstr(style_gui));
1211         }
1212
1213         if (sel == "default") {
1214                 pageLayoutModule->pagestyleCO->setCurrentIndex(0);
1215                 return;
1216         }
1217
1218         int nn = 0;
1219
1220         for (size_t i = 0; i < pagestyles.size(); ++i)
1221                 if (pagestyles[i].first == sel)
1222                         nn = pageLayoutModule->pagestyleCO->findText(
1223                                         toqstr(pagestyles[i].second));
1224
1225         if (nn > 0)
1226                 pageLayoutModule->pagestyleCO->setCurrentIndex(nn);
1227 }
1228
1229
1230 void GuiDocument::browseLayout()
1231 {
1232         QString const label1 = qt_("Layouts|#o#O");
1233         QString const dir1 = toqstr(lyxrc.document_path);
1234         FileFilterList const filter(_("LyX Layout (*.layout)"));
1235         QString file = browseRelFile(QString(), bufferFilepath(),
1236                 qt_("Local layout file"), filter, false,
1237                 label1, dir1);
1238
1239         if (!suffixIs(fromqstr(file), ".layout"))
1240                 return;
1241
1242         FileName layoutFile = makeAbsPath(fromqstr(file),
1243                 fromqstr(bufferFilepath()));
1244         
1245         // load the layout file
1246         LayoutFileList & bcl = LayoutFileList::get();
1247         string classname = layoutFile.onlyFileName();
1248         LayoutFileIndex name = bcl.addLayoutFile(
1249                 classname.substr(0, classname.size() - 7),
1250                 layoutFile.onlyPath().absFilename(),
1251                 LayoutFileList::Local);
1252
1253         if (name.empty()) {
1254                 Alert::error(_("Error"),
1255                         _("Unable to read local layout file."));                
1256                 return;
1257         }
1258
1259         // do not trigger classChanged if there is no change.
1260         if (latexModule->classCO->currentText() == toqstr(name))
1261                 return;
1262                 
1263         // add to combo box
1264         int idx = latexModule->classCO->findText(toqstr(name));
1265         if (idx == -1) {
1266                 classes_model_.insertRow(0, toqstr(name), name);
1267                 latexModule->classCO->setCurrentIndex(0);
1268         } else
1269                 latexModule->classCO->setCurrentIndex(idx);
1270         classChanged();
1271 }
1272
1273
1274 void GuiDocument::classChanged()
1275 {
1276         int idx = latexModule->classCO->currentIndex();
1277         if (idx < 0) 
1278                 return;
1279         string const classname = classes_model_.getIDString(idx);
1280         // check if this is a local layout file
1281         if (prefixIs(classname, LayoutFileList::localPrefix)) {
1282                 int const ret = Alert::prompt(_("Local layout file"),
1283                                 _("The layout file you have selected is a local layout\n"
1284                                   "file, not one in the system or user directory. Your\n"
1285                                   "document may not work with this layout if you do not\n"
1286                                   "keep the layout file in the same directory."),
1287                                   1, 1, _("&Set Layout"), _("&Cancel"));
1288                 if (ret == 1) {
1289                         // try to reset the layout combo
1290                         setLayoutComboByIDString(bp_.baseClassID());
1291                         return;
1292                 }
1293         } else if (prefixIs(classname, LayoutFileList::embeddedPrefix)) {
1294                 int const ret = Alert::prompt(_("Embedded layout"),
1295                                 _("The layout file you have selected is an embedded layout that\n"
1296                                   "is embedded to a buffer. You cannot make use of it unless\n"
1297                                   "it is already embedded to this buffer.\n"),
1298                                   1, 1, _("&Set Layout"), _("&Cancel"));
1299                 if (ret == 1) {
1300                         setLayoutComboByIDString(bp_.baseClassID());
1301                         return;
1302                 }
1303         }
1304         // FIXME Note that by doing things this way, we load the TextClass
1305         // as soon as it is selected. So, if you use the scroll wheel when
1306         // sitting on the combo box, we'll load a lot of TextClass objects
1307         // very quickly. This could be changed.
1308         if (!bp_.setBaseClass(classname)) {
1309                 Alert::error(_("Error"), _("Unable to set document class."));
1310                 return;
1311         }
1312         if (lyxrc.auto_reset_options) {
1313                 if (applyPB->isEnabled()) {
1314                         int const ret = Alert::prompt(_("Unapplied changes"),
1315                                         _("Some changes in the dialog were not yet applied.\n"
1316                                         "If you do not apply now, they will be lost after this action."),
1317                                         1, 1, _("&Apply"), _("&Dismiss"));
1318                         if (ret == 0)
1319                                 applyView();
1320                 }
1321                 bp_.useClassDefaults();
1322                 forceUpdate();
1323         }
1324 }
1325
1326
1327 namespace {
1328         // This is an insanely complicated attempt to make this sort of thing
1329         // work with RTL languages.
1330         docstring formatStrVec(vector<string> const & v, docstring const & s) 
1331         {
1332                 //this mess formats the list as "v[0], v[1], ..., [s] v[n]"
1333                 int const vSize = v.size();
1334                 if (v.size() == 0)
1335                         return docstring();
1336                 else if (v.size() == 1) 
1337                         return from_ascii(v[0]);
1338                 else if (v.size() == 2) {
1339                         docstring retval = _("%1$s and %2$s");
1340                         retval = subst(retval, _("and"), s);
1341                         return bformat(retval, from_ascii(v[0]), from_ascii(v[1]));
1342                 }
1343                 //The idea here is to format all but the last two items...
1344                 docstring t2 = _("%1$s, %2$s");
1345                 docstring retval = from_ascii(v[0]);
1346                 for (int i = 1; i < vSize - 2; ++i)
1347                         retval = bformat(t2, retval, from_ascii(v[i])); 
1348                 //...and then to  plug them, and the last two, into this schema
1349                 docstring t = _("%1$s, %2$s, and %3$s");
1350                 t = subst(t, _("and"), s);
1351                 return bformat(t, retval, from_ascii(v[vSize - 2]), from_ascii(v[vSize - 1]));
1352         }
1353         
1354         vector<string> idsToNames(vector<string> const & idList)
1355         {
1356                 vector<string> retval;
1357                 vector<string>::const_iterator it  = idList.begin();
1358                 vector<string>::const_iterator end = idList.end();
1359                 for (; it != end; ++it) {
1360                         LyXModule const * const mod = moduleList[*it];
1361                         if (!mod)
1362                                 retval.push_back(*it + " (Unavailable)");
1363                         else
1364                                 retval.push_back(mod->getName());
1365                 }
1366                 return retval;
1367         }
1368 }
1369
1370
1371 void GuiDocument::updateModuleInfo()
1372 {
1373         selectionManager->update();
1374         
1375         //Module description
1376         bool const focusOnSelected = selectionManager->selectedFocused();
1377         QListView const * const lv = 
1378                         focusOnSelected ? latexModule->selectedLV : latexModule->availableLV;
1379         if (lv->selectionModel()->selectedIndexes().isEmpty()) {
1380                 latexModule->infoML->document()->clear();
1381                 return;
1382         }
1383         QModelIndex const & idx = lv->selectionModel()->currentIndex();
1384         GuiIdListModel const & idModel = 
1385                         focusOnSelected  ? modules_sel_model_ : modules_av_model_;
1386         string const modName = idModel.getIDString(idx.row());
1387         docstring desc = getModuleDescription(modName);
1388
1389         vector<string> pkgList = getPackageList(modName);
1390         docstring pkgdesc = formatStrVec(pkgList, _("and"));
1391         if (!pkgdesc.empty()) {
1392                 if (!desc.empty())
1393                         desc += "\n";
1394                 desc += bformat(_("Package(s) required: %1$s."), pkgdesc);
1395         }
1396
1397         pkgList = getRequiredList(modName);
1398         if (!pkgList.empty()) {
1399                 vector<string> const reqDescs = idsToNames(pkgList);
1400                 pkgdesc = formatStrVec(reqDescs, _("or"));
1401                 if (!desc.empty())
1402                         desc += "\n";
1403                 desc += bformat(_("Module required: %1$s."), pkgdesc);
1404         }
1405
1406         pkgList = getExcludedList(modName);
1407         if (!pkgList.empty()) {
1408                 vector<string> const reqDescs = idsToNames(pkgList);
1409                 pkgdesc = formatStrVec(reqDescs, _( "and"));
1410                 if (!desc.empty())
1411                         desc += "\n";
1412                 desc += bformat(_("Modules excluded: %1$s."), pkgdesc);
1413         }
1414
1415         if (!isModuleAvailable(modName)) {
1416                 if (!desc.empty())
1417                         desc += "\n";
1418                 desc += _("WARNING: Some packages are unavailable!");
1419         }
1420
1421         latexModule->infoML->document()->setPlainText(toqstr(desc));
1422 }
1423
1424
1425 void GuiDocument::setExtraEmbeddedFileList()
1426 {
1427         embeddedFilesModule->extraLW->clear();
1428         // add current embedded files
1429         vector<string> const & files = buffer().params().extraEmbeddedFiles();
1430         vector<string>::const_iterator fit = files.begin();
1431         vector<string>::const_iterator fit_end = files.end();
1432         for (; fit != fit_end; ++fit)
1433                 embeddedFilesModule->extraLW->addItem(toqstr(*fit));
1434 }
1435
1436
1437 void GuiDocument::addExtraEmbeddedFile()
1438 {
1439         QString const label1 = qt_("Documents|#o#O");
1440         QString const dir1 = toqstr(lyxrc.document_path);
1441         FileFilterList const filter(_("LyX Layout (*.layout);;LaTeX Classes (*.{cls,sty});;BibTeX Databases (*.{bib,bst})"));
1442         QString file = browseRelFile(QString(), bufferFilepath(),
1443                 qt_("Extra embedded file"), filter, true, label1, dir1);
1444
1445         if (file.isEmpty())
1446                 return;
1447
1448         if (embeddedFilesModule->extraLW->findItems(file, Qt::MatchExactly).empty())
1449                 embeddedFilesModule->extraLW->addItem(file);
1450 }
1451
1452
1453 void GuiDocument::removeExtraEmbeddedFile()
1454 {
1455         int index = embeddedFilesModule->extraLW->currentRow();
1456         delete embeddedFilesModule->extraLW->takeItem(index);
1457 }
1458
1459
1460 void GuiDocument::updateNumbering()
1461 {
1462         DocumentClass const & tclass = bp_.documentClass();
1463
1464         numberingModule->tocTW->setUpdatesEnabled(false);
1465         numberingModule->tocTW->clear();
1466
1467         int const depth = numberingModule->depthSL->value();
1468         int const toc = numberingModule->tocSL->value();
1469         QString const no = qt_("No");
1470         QString const yes = qt_("Yes");
1471         QTreeWidgetItem * item = 0;
1472
1473         DocumentClass::const_iterator lit = tclass.begin();
1474         DocumentClass::const_iterator len = tclass.end();
1475         for (; lit != len; ++lit) {
1476                 int const toclevel = lit->toclevel;
1477                 if (toclevel != Layout::NOT_IN_TOC && lit->labeltype == LABEL_COUNTER) {
1478                         item = new QTreeWidgetItem(numberingModule->tocTW);
1479                         item->setText(0, toqstr(translateIfPossible(lit->name())));
1480                         item->setText(1, (toclevel <= depth) ? yes : no);
1481                         item->setText(2, (toclevel <= toc) ? yes : no);
1482                 }
1483         }
1484
1485         numberingModule->tocTW->setUpdatesEnabled(true);
1486         numberingModule->tocTW->update();
1487 }
1488
1489
1490 void GuiDocument::apply(BufferParams & params)
1491 {
1492         // preamble
1493         preambleModule->apply(params);
1494
1495         // biblio
1496         params.setCiteEngine(biblio::ENGINE_BASIC);
1497
1498         if (biblioModule->citeNatbibRB->isChecked()) {
1499                 bool const use_numerical_citations =
1500                         biblioModule->citeStyleCO->currentIndex();
1501                 if (use_numerical_citations)
1502                         params.setCiteEngine(biblio::ENGINE_NATBIB_NUMERICAL);
1503                 else
1504                         params.setCiteEngine(biblio::ENGINE_NATBIB_AUTHORYEAR);
1505
1506         } else if (biblioModule->citeJurabibRB->isChecked())
1507                 params.setCiteEngine(biblio::ENGINE_JURABIB);
1508
1509         params.use_bibtopic =
1510                 biblioModule->bibtopicCB->isChecked();
1511
1512         // language & quotes
1513         if (langModule->defaultencodingRB->isChecked()) {
1514                 params.inputenc = "auto";
1515         } else {
1516                 int i = langModule->encodingCO->currentIndex();
1517                 if (i == 0)
1518                         params.inputenc = "default";
1519                 else
1520                         params.inputenc =
1521                                 fromqstr(langModule->encodingCO->currentText());
1522         }
1523
1524         InsetQuotes::QuoteLanguage lga = InsetQuotes::EnglishQuotes;
1525         switch (langModule->quoteStyleCO->currentIndex()) {
1526         case 0:
1527                 lga = InsetQuotes::EnglishQuotes;
1528                 break;
1529         case 1:
1530                 lga = InsetQuotes::SwedishQuotes;
1531                 break;
1532         case 2:
1533                 lga = InsetQuotes::GermanQuotes;
1534                 break;
1535         case 3:
1536                 lga = InsetQuotes::PolishQuotes;
1537                 break;
1538         case 4:
1539                 lga = InsetQuotes::FrenchQuotes;
1540                 break;
1541         case 5:
1542                 lga = InsetQuotes::DanishQuotes;
1543                 break;
1544         }
1545         params.quotes_language = lga;
1546
1547         int const pos = langModule->languageCO->currentIndex();
1548         params.language = lyx::languages.getLanguage(fromqstr(lang_[pos]));
1549
1550         // numbering
1551         if (params.documentClass().hasTocLevels()) {
1552                 params.tocdepth = numberingModule->tocSL->value();
1553                 params.secnumdepth = numberingModule->depthSL->value();
1554         }
1555
1556         // bullets
1557         params.user_defined_bullet(0) = bulletsModule->getBullet(0);
1558         params.user_defined_bullet(1) = bulletsModule->getBullet(1);
1559         params.user_defined_bullet(2) = bulletsModule->getBullet(2);
1560         params.user_defined_bullet(3) = bulletsModule->getBullet(3);
1561
1562         // packages
1563         params.graphicsDriver =
1564                 tex_graphics[latexModule->psdriverCO->currentIndex()];
1565         
1566         // text layout
1567         int idx = latexModule->classCO->currentIndex();
1568         if (idx >= 0) {
1569                 string const classname = classes_model_.getIDString(idx);
1570                 params.setBaseClass(classname);
1571         }
1572
1573         // Modules
1574         params.clearLayoutModules();
1575         int const srows = modules_sel_model_.rowCount();
1576         vector<string> selModList;
1577         for (int i = 0; i < srows; ++i)
1578                 params.addLayoutModule(modules_sel_model_.getIDString(i));
1579
1580         if (mathsModule->amsautoCB->isChecked()) {
1581                 params.use_amsmath = BufferParams::package_auto;
1582         } else {
1583                 if (mathsModule->amsCB->isChecked())
1584                         params.use_amsmath = BufferParams::package_on;
1585                 else
1586                         params.use_amsmath = BufferParams::package_off;
1587         }
1588
1589         if (mathsModule->esintautoCB->isChecked())
1590                 params.use_esint = BufferParams::package_auto;
1591         else {
1592                 if (mathsModule->esintCB->isChecked())
1593                         params.use_esint = BufferParams::package_on;
1594                 else
1595                         params.use_esint = BufferParams::package_off;
1596         }
1597
1598         if (pageLayoutModule->pagestyleCO->currentIndex() == 0)
1599                 params.pagestyle = "default";
1600         else {
1601                 docstring style_gui =
1602                         qstring_to_ucs4(pageLayoutModule->pagestyleCO->currentText());
1603                 for (size_t i = 0; i < pagestyles.size(); ++i)
1604                         if (pagestyles[i].second == style_gui)
1605                                 params.pagestyle = pagestyles[i].first;
1606         }
1607
1608         switch (textLayoutModule->lspacingCO->currentIndex()) {
1609         case 0:
1610                 params.spacing().set(Spacing::Single);
1611                 break;
1612         case 1:
1613                 params.spacing().set(Spacing::Onehalf);
1614                 break;
1615         case 2:
1616                 params.spacing().set(Spacing::Double);
1617                 break;
1618         case 3:
1619                 params.spacing().set(Spacing::Other,
1620                         fromqstr(textLayoutModule->lspacingLE->text()));
1621                 break;
1622         }
1623
1624         if (textLayoutModule->twoColumnCB->isChecked())
1625                 params.columns = 2;
1626         else
1627                 params.columns = 1;
1628
1629         // text should have passed validation
1630         params.listings_params =
1631                 InsetListingsParams(fromqstr(textLayoutModule->listingsED->toPlainText())).params();
1632
1633         if (textLayoutModule->indentRB->isChecked())
1634                 params.paragraph_separation = BufferParams::ParagraphIndentSeparation;
1635         else
1636                 params.paragraph_separation = BufferParams::ParagraphSkipSeparation;
1637
1638         switch (textLayoutModule->skipCO->currentIndex()) {
1639         case 0:
1640                 params.setDefSkip(VSpace(VSpace::SMALLSKIP));
1641                 break;
1642         case 1:
1643                 params.setDefSkip(VSpace(VSpace::MEDSKIP));
1644                 break;
1645         case 2:
1646                 params.setDefSkip(VSpace(VSpace::BIGSKIP));
1647                 break;
1648         case 3:
1649         {
1650                 VSpace vs = VSpace(
1651                         widgetsToLength(textLayoutModule->skipLE,
1652                                 textLayoutModule->skipLengthCO)
1653                         );
1654                 params.setDefSkip(vs);
1655                 break;
1656         }
1657         default:
1658                 // DocumentDefskipCB assures that this never happens
1659                 // so Assert then !!!  - jbl
1660                 params.setDefSkip(VSpace(VSpace::MEDSKIP));
1661                 break;
1662         }
1663
1664         params.options =
1665                 fromqstr(latexModule->optionsLE->text());
1666
1667         params.float_placement = floatModule->get();
1668
1669         // fonts
1670         params.fontsRoman =
1671                 tex_fonts_roman[fontModule->fontsRomanCO->currentIndex()];
1672
1673         params.fontsSans =
1674                 tex_fonts_sans[fontModule->fontsSansCO->currentIndex()];
1675
1676         params.fontsTypewriter =
1677                 tex_fonts_monospaced[fontModule->fontsTypewriterCO->currentIndex()];
1678
1679         params.fontsSansScale = fontModule->scaleSansSB->value();
1680
1681         params.fontsTypewriterScale = fontModule->scaleTypewriterSB->value();
1682
1683         params.fontsSC = fontModule->fontScCB->isChecked();
1684
1685         params.fontsOSF = fontModule->fontOsfCB->isChecked();
1686
1687         params.fontsDefaultFamily = GuiDocument::fontfamilies[
1688                 fontModule->fontsDefaultCO->currentIndex()];
1689
1690         if (fontModule->fontsizeCO->currentIndex() == 0)
1691                 params.fontsize = "default";
1692         else
1693                 params.fontsize =
1694                         fromqstr(fontModule->fontsizeCO->currentText());
1695
1696         // paper
1697         params.papersize = PAPER_SIZE(
1698                 pageLayoutModule->papersizeCO->currentIndex());
1699
1700         // custom, A3, B3 and B4 paper sizes need geometry
1701         int psize = pageLayoutModule->papersizeCO->currentIndex();
1702         bool geom_papersize = (psize == 1 || psize == 5 || psize == 8 || psize == 9);
1703
1704         params.paperwidth = widgetsToLength(pageLayoutModule->paperwidthLE,
1705                 pageLayoutModule->paperwidthUnitCO);
1706
1707         params.paperheight = widgetsToLength(pageLayoutModule->paperheightLE,
1708                 pageLayoutModule->paperheightUnitCO);
1709
1710         if (pageLayoutModule->facingPagesCB->isChecked())
1711                 params.sides = TwoSides;
1712         else
1713                 params.sides = OneSide;
1714
1715         if (pageLayoutModule->landscapeRB->isChecked())
1716                 params.orientation = ORIENTATION_LANDSCAPE;
1717         else
1718                 params.orientation = ORIENTATION_PORTRAIT;
1719
1720         // margins
1721         params.use_geometry = !marginsModule->marginCB->isChecked()
1722                 || geom_papersize;
1723
1724         Ui::MarginsUi const * m = marginsModule;
1725
1726         params.leftmargin = widgetsToLength(m->innerLE, m->innerUnit);
1727         params.topmargin = widgetsToLength(m->topLE, m->topUnit);
1728         params.rightmargin = widgetsToLength(m->outerLE, m->outerUnit);
1729         params.bottommargin = widgetsToLength(m->bottomLE, m->bottomUnit);
1730         params.headheight = widgetsToLength(m->headheightLE, m->headheightUnit);
1731         params.headsep = widgetsToLength(m->headsepLE, m->headsepUnit);
1732         params.footskip = widgetsToLength(m->footskipLE, m->footskipUnit);
1733         params.columnsep = widgetsToLength(m->columnsepLE, m->columnsepUnit);
1734
1735         branchesModule->apply(params);
1736
1737         // PDF support
1738         PDFOptions & pdf = params.pdfoptions();
1739         pdf.use_hyperref = pdfSupportModule->use_hyperrefGB->isChecked();
1740         pdf.title = fromqstr(pdfSupportModule->titleLE->text());
1741         pdf.author = fromqstr(pdfSupportModule->authorLE->text());
1742         pdf.subject = fromqstr(pdfSupportModule->subjectLE->text());
1743         pdf.keywords = fromqstr(pdfSupportModule->keywordsLE->text());
1744
1745         pdf.bookmarks = pdfSupportModule->bookmarksGB->isChecked();
1746         pdf.bookmarksnumbered = pdfSupportModule->bookmarksnumberedCB->isChecked();
1747         pdf.bookmarksopen = pdfSupportModule->bookmarksopenGB->isChecked();
1748         pdf.bookmarksopenlevel = pdfSupportModule->bookmarksopenlevelSB->value();
1749
1750         pdf.breaklinks = pdfSupportModule->breaklinksCB->isChecked();
1751         pdf.pdfborder = pdfSupportModule->pdfborderCB->isChecked();
1752         pdf.pdfusetitle = pdfSupportModule->pdfusetitleCB->isChecked();
1753         pdf.colorlinks = pdfSupportModule->colorlinksCB->isChecked();
1754         pdf.backref = pdfSupportModule->backrefCB->isChecked();
1755         pdf.pagebackref = pdfSupportModule->pagebackrefCB->isChecked();
1756         if (pdfSupportModule->fullscreenCB->isChecked())
1757                 pdf.pagemode = pdf.pagemode_fullscreen;
1758         else
1759                 pdf.pagemode.clear();
1760         pdf.quoted_options = pdf.quoted_options_check(
1761                                 fromqstr(pdfSupportModule->optionsLE->text()));
1762
1763         // Embedded files
1764         vector<string> & files = params.extraEmbeddedFiles();
1765         files.clear();
1766         for (int i = 0; i < embeddedFilesModule->extraLW->count(); ++i) {
1767                 QListWidgetItem * item = embeddedFilesModule->extraLW->item(i);
1768                 files.push_back(fromqstr(item->text()));
1769         }
1770 }
1771
1772
1773 static int findPos(QStringList const & vec, QString const & val)
1774 {
1775         for (int i = 0; i != vec.size(); ++i)
1776                 if (vec[i] == val)
1777                         return i;
1778         return 0;
1779 }
1780
1781
1782 void GuiDocument::updateParams()
1783 {
1784         updateParams(bp_);
1785 }
1786
1787
1788 void GuiDocument::updateParams(BufferParams const & params)
1789 {
1790         // set the default unit
1791         Length::UNIT defaultUnit = Length::CM;
1792         switch (lyxrc.default_papersize) {
1793                 case PAPER_DEFAULT: break;
1794
1795                 case PAPER_USLETTER:
1796                 case PAPER_USLEGAL:
1797                 case PAPER_USEXECUTIVE:
1798                         defaultUnit = Length::IN;
1799                         break;
1800
1801                 case PAPER_A3:
1802                 case PAPER_A4:
1803                 case PAPER_A5:
1804                 case PAPER_B3:
1805                 case PAPER_B4:
1806                 case PAPER_B5:
1807                         defaultUnit = Length::CM;
1808                         break;
1809                 case PAPER_CUSTOM:
1810                         break;
1811         }
1812
1813         // preamble
1814         preambleModule->update(params, id());
1815
1816         // biblio
1817         biblioModule->citeDefaultRB->setChecked(
1818                 params.citeEngine() == biblio::ENGINE_BASIC);
1819
1820         biblioModule->citeNatbibRB->setChecked(
1821                 params.citeEngine() == biblio::ENGINE_NATBIB_NUMERICAL ||
1822                 params.citeEngine() == biblio::ENGINE_NATBIB_AUTHORYEAR);
1823
1824         biblioModule->citeStyleCO->setCurrentIndex(
1825                 params.citeEngine() == biblio::ENGINE_NATBIB_NUMERICAL);
1826
1827         biblioModule->citeJurabibRB->setChecked(
1828                 params.citeEngine() == biblio::ENGINE_JURABIB);
1829
1830         biblioModule->bibtopicCB->setChecked(
1831                 params.use_bibtopic);
1832
1833         // language & quotes
1834         int const pos = findPos(lang_, toqstr(params.language->lang()));
1835         langModule->languageCO->setCurrentIndex(pos);
1836
1837         langModule->quoteStyleCO->setCurrentIndex(
1838                 params.quotes_language);
1839
1840         bool default_enc = true;
1841         if (params.inputenc != "auto") {
1842                 default_enc = false;
1843                 if (params.inputenc == "default") {
1844                         langModule->encodingCO->setCurrentIndex(0);
1845                 } else {
1846                         int const i = langModule->encodingCO->findText(
1847                                         toqstr(params.inputenc));
1848                         if (i >= 0)
1849                                 langModule->encodingCO->setCurrentIndex(i);
1850                         else
1851                                 // unknown encoding. Set to default.
1852                                 default_enc = true;
1853                 }
1854         }
1855         langModule->defaultencodingRB->setChecked(default_enc);
1856         langModule->otherencodingRB->setChecked(!default_enc);
1857
1858         // numbering
1859         int const min_toclevel = documentClass().min_toclevel();
1860         int const max_toclevel = documentClass().max_toclevel();
1861         if (documentClass().hasTocLevels()) {
1862                 numberingModule->setEnabled(true);
1863                 numberingModule->depthSL->setMinimum(min_toclevel - 1);
1864                 numberingModule->depthSL->setMaximum(max_toclevel);
1865                 numberingModule->depthSL->setValue(params.secnumdepth);
1866                 numberingModule->tocSL->setMaximum(min_toclevel - 1);
1867                 numberingModule->tocSL->setMaximum(max_toclevel);
1868                 numberingModule->tocSL->setValue(params.tocdepth);
1869                 updateNumbering();
1870         } else {
1871                 numberingModule->setEnabled(false);
1872                 numberingModule->tocTW->clear();
1873         }
1874
1875         // bullets
1876         bulletsModule->setBullet(0, params.user_defined_bullet(0));
1877         bulletsModule->setBullet(1, params.user_defined_bullet(1));
1878         bulletsModule->setBullet(2, params.user_defined_bullet(2));
1879         bulletsModule->setBullet(3, params.user_defined_bullet(3));
1880         bulletsModule->init();
1881
1882         // packages
1883         int nitem = findToken(tex_graphics, params.graphicsDriver);
1884         if (nitem >= 0)
1885                 latexModule->psdriverCO->setCurrentIndex(nitem);
1886         updateModuleInfo();
1887         
1888         mathsModule->amsCB->setChecked(
1889                 params.use_amsmath == BufferParams::package_on);
1890         mathsModule->amsautoCB->setChecked(
1891                 params.use_amsmath == BufferParams::package_auto);
1892
1893         mathsModule->esintCB->setChecked(
1894                 params.use_esint == BufferParams::package_on);
1895         mathsModule->esintautoCB->setChecked(
1896                 params.use_esint == BufferParams::package_auto);
1897
1898         switch (params.spacing().getSpace()) {
1899                 case Spacing::Other: nitem = 3; break;
1900                 case Spacing::Double: nitem = 2; break;
1901                 case Spacing::Onehalf: nitem = 1; break;
1902                 case Spacing::Default: case Spacing::Single: nitem = 0; break;
1903         }
1904
1905         // text layout
1906         string const & layoutID = params.baseClassID();
1907         setLayoutComboByIDString(layoutID);
1908
1909         updatePagestyle(documentClass().opt_pagestyle(),
1910                                  params.pagestyle);
1911
1912         textLayoutModule->lspacingCO->setCurrentIndex(nitem);
1913         if (params.spacing().getSpace() == Spacing::Other) {
1914                 textLayoutModule->lspacingLE->setText(
1915                         toqstr(params.spacing().getValueAsString()));
1916         }
1917         setLSpacing(nitem);
1918
1919         if (params.paragraph_separation == BufferParams::ParagraphIndentSeparation)
1920                 textLayoutModule->indentRB->setChecked(true);
1921         else
1922                 textLayoutModule->skipRB->setChecked(true);
1923
1924         int skip = 0;
1925         switch (params.getDefSkip().kind()) {
1926         case VSpace::SMALLSKIP:
1927                 skip = 0;
1928                 break;
1929         case VSpace::MEDSKIP:
1930                 skip = 1;
1931                 break;
1932         case VSpace::BIGSKIP:
1933                 skip = 2;
1934                 break;
1935         case VSpace::LENGTH:
1936         {
1937                 skip = 3;
1938                 string const length = params.getDefSkip().asLyXCommand();
1939                 lengthToWidgets(textLayoutModule->skipLE,
1940                         textLayoutModule->skipLengthCO,
1941                         length, defaultUnit);
1942                 break;
1943         }
1944         default:
1945                 skip = 0;
1946                 break;
1947         }
1948         textLayoutModule->skipCO->setCurrentIndex(skip);
1949         setSkip(skip);
1950
1951         textLayoutModule->twoColumnCB->setChecked(
1952                 params.columns == 2);
1953
1954         // break listings_params to multiple lines
1955         string lstparams =
1956                 InsetListingsParams(params.listings_params).separatedParams();
1957         textLayoutModule->listingsED->setPlainText(toqstr(lstparams));
1958
1959         if (!params.options.empty()) {
1960                 latexModule->optionsLE->setText(
1961                         toqstr(params.options));
1962         } else {
1963                 latexModule->optionsLE->setText(QString());
1964         }
1965
1966         floatModule->set(params.float_placement);
1967
1968         // Fonts
1969         updateFontsize(documentClass().opt_fontsize(),
1970                         params.fontsize);
1971
1972         int n = findToken(tex_fonts_roman, params.fontsRoman);
1973         if (n >= 0) {
1974                 fontModule->fontsRomanCO->setCurrentIndex(n);
1975                 romanChanged(n);
1976         }
1977
1978         n = findToken(tex_fonts_sans, params.fontsSans);
1979         if (n >= 0)     {
1980                 fontModule->fontsSansCO->setCurrentIndex(n);
1981                 sansChanged(n);
1982         }
1983
1984         n = findToken(tex_fonts_monospaced, params.fontsTypewriter);
1985         if (n >= 0) {
1986                 fontModule->fontsTypewriterCO->setCurrentIndex(n);
1987                 ttChanged(n);
1988         }
1989
1990         fontModule->fontScCB->setChecked(params.fontsSC);
1991         fontModule->fontOsfCB->setChecked(params.fontsOSF);
1992         fontModule->scaleSansSB->setValue(params.fontsSansScale);
1993         fontModule->scaleTypewriterSB->setValue(params.fontsTypewriterScale);
1994         n = findToken(GuiDocument::fontfamilies, params.fontsDefaultFamily);
1995         if (n >= 0)
1996                 fontModule->fontsDefaultCO->setCurrentIndex(n);
1997
1998         // paper
1999         int const psize = params.papersize;
2000         pageLayoutModule->papersizeCO->setCurrentIndex(psize);
2001         setCustomPapersize(psize);
2002
2003         bool const landscape =
2004                 params.orientation == ORIENTATION_LANDSCAPE;
2005         pageLayoutModule->landscapeRB->setChecked(landscape);
2006         pageLayoutModule->portraitRB->setChecked(!landscape);
2007
2008         pageLayoutModule->facingPagesCB->setChecked(
2009                 params.sides == TwoSides);
2010
2011
2012         lengthToWidgets(pageLayoutModule->paperwidthLE,
2013                 pageLayoutModule->paperwidthUnitCO, params.paperwidth, defaultUnit);
2014
2015         lengthToWidgets(pageLayoutModule->paperheightLE,
2016                 pageLayoutModule->paperheightUnitCO, params.paperheight, defaultUnit);
2017
2018         // margins
2019         Ui::MarginsUi * m = marginsModule;
2020
2021         setMargins(!params.use_geometry);
2022
2023         lengthToWidgets(m->topLE, m->topUnit,
2024                 params.topmargin, defaultUnit);
2025
2026         lengthToWidgets(m->bottomLE, m->bottomUnit,
2027                 params.bottommargin, defaultUnit);
2028
2029         lengthToWidgets(m->innerLE, m->innerUnit,
2030                 params.leftmargin, defaultUnit);
2031
2032         lengthToWidgets(m->outerLE, m->outerUnit,
2033                 params.rightmargin, defaultUnit);
2034
2035         lengthToWidgets(m->headheightLE, m->headheightUnit,
2036                 params.headheight, defaultUnit);
2037
2038         lengthToWidgets(m->headsepLE, m->headsepUnit,
2039                 params.headsep, defaultUnit);
2040
2041         lengthToWidgets(m->footskipLE, m->footskipUnit,
2042                 params.footskip, defaultUnit);
2043
2044         lengthToWidgets(m->columnsepLE, m->columnsepUnit,
2045                 params.columnsep, defaultUnit);
2046
2047         branchesModule->update(params);
2048
2049         // PDF support
2050         PDFOptions const & pdf = params.pdfoptions();
2051         pdfSupportModule->use_hyperrefGB->setChecked(pdf.use_hyperref);
2052         pdfSupportModule->titleLE->setText(toqstr(pdf.title));
2053         pdfSupportModule->authorLE->setText(toqstr(pdf.author));
2054         pdfSupportModule->subjectLE->setText(toqstr(pdf.subject));
2055         pdfSupportModule->keywordsLE->setText(toqstr(pdf.keywords));
2056
2057         pdfSupportModule->bookmarksGB->setChecked(pdf.bookmarks);
2058         pdfSupportModule->bookmarksnumberedCB->setChecked(pdf.bookmarksnumbered);
2059         pdfSupportModule->bookmarksopenGB->setChecked(pdf.bookmarksopen);
2060
2061         pdfSupportModule->bookmarksopenlevelSB->setValue(pdf.bookmarksopenlevel);
2062
2063         pdfSupportModule->breaklinksCB->setChecked(pdf.breaklinks);
2064         pdfSupportModule->pdfborderCB->setChecked(pdf.pdfborder);
2065         pdfSupportModule->pdfusetitleCB->setChecked(pdf.pdfusetitle);
2066         pdfSupportModule->colorlinksCB->setChecked(pdf.colorlinks);
2067         pdfSupportModule->backrefCB->setChecked(pdf.backref);
2068         pdfSupportModule->pagebackrefCB->setChecked(pdf.pagebackref);
2069         pdfSupportModule->fullscreenCB->setChecked
2070                 (pdf.pagemode == pdf.pagemode_fullscreen);
2071
2072         pdfSupportModule->optionsLE->setText(
2073                 toqstr(pdf.quoted_options));
2074         
2075         setExtraEmbeddedFileList();
2076 }
2077
2078
2079 void GuiDocument::applyView()
2080 {
2081         apply(params());
2082 }
2083
2084
2085 void GuiDocument::saveDocDefault()
2086 {
2087         // we have to apply the params first
2088         applyView();
2089         saveAsDefault();
2090 }
2091
2092
2093 void GuiDocument::updateAvailableModules() 
2094 {
2095         modules_av_model_.clear();
2096         vector<modInfoStruct> const & modInfoList = getModuleInfo();
2097         int const mSize = modInfoList.size();
2098         for (int i = 0; i != mSize; ++i) {
2099                 modInfoStruct const & modInfo = modInfoList[i];
2100                 modules_av_model_.insertRow(i, modInfo.name, modInfo.id, 
2101                                 modInfo.description);
2102         }
2103 }
2104
2105
2106 void GuiDocument::updateSelectedModules() 
2107 {
2108         // and selected ones, too
2109         modules_sel_model_.clear();
2110         vector<modInfoStruct> const selModList = getSelectedModules();
2111         int const sSize = selModList.size();
2112         for (int i = 0; i != sSize; ++i) {
2113                 modInfoStruct const & modInfo = selModList[i];
2114                 modules_sel_model_.insertRow(i, modInfo.name, modInfo.id,
2115                                 modInfo.description);
2116         }
2117 }
2118
2119
2120 void GuiDocument::updateContents()
2121 {
2122         if (id() == current_id_)
2123                 return;
2124
2125         updateAvailableModules();
2126         updateSelectedModules();
2127         
2128         //FIXME It'd be nice to make sure here that the selected
2129         //modules are consistent: That required modules are actually
2130         //selected, and that we don't have conflicts. If so, we could
2131         //at least pop up a warning.
2132         updateParams(bp_);
2133         current_id_ = id();
2134 }
2135
2136
2137 void GuiDocument::forceUpdate()
2138 {
2139         // reset to force dialog update
2140         current_id_ = 0;
2141         updateContents();
2142 }
2143
2144
2145 void GuiDocument::useClassDefaults()
2146 {
2147         if (applyPB->isEnabled()) {
2148                 int const ret = Alert::prompt(_("Unapplied changes"),
2149                                 _("Some changes in the dialog were not yet applied.\n"
2150                                   "If you do not apply now, they will be lost after this action."),
2151                                 1, 1, _("&Apply"), _("&Dismiss"));
2152                 if (ret == 0)
2153                         applyView();
2154         }
2155
2156         int idx = latexModule->classCO->currentIndex();
2157         string const classname = classes_model_.getIDString(idx);
2158         if (!bp_.setBaseClass(classname)) {
2159                 Alert::error(_("Error"), _("Unable to set document class."));
2160                 return;
2161         }
2162         bp_.useClassDefaults();
2163         forceUpdate();
2164 }
2165
2166
2167 void GuiDocument::setLayoutComboByIDString(std::string const & idString)
2168 {
2169         int idx = classes_model_.findIDString(idString);
2170         if (idx < 0)
2171                 Alert::warning(_("Can't set layout!"), 
2172                         bformat(_("Unable to set layout for ID: %1$s"), from_utf8(idString)));
2173         else 
2174                 latexModule->classCO->setCurrentIndex(idx);
2175 }
2176
2177
2178 bool GuiDocument::isValid()
2179 {
2180         return validate_listings_params().empty()
2181                 && (textLayoutModule->skipCO->currentIndex() != 3
2182                         || !textLayoutModule->skipLE->text().isEmpty());
2183 }
2184
2185
2186 char const * const GuiDocument::fontfamilies[5] = {
2187         "default", "rmdefault", "sfdefault", "ttdefault", ""
2188 };
2189
2190
2191 char const * GuiDocument::fontfamilies_gui[5] = {
2192         N_("Default"), N_("Roman"), N_("Sans Serif"), N_("Typewriter"), ""
2193 };
2194
2195
2196 bool GuiDocument::initialiseParams(string const &)
2197 {
2198         bp_ = buffer().params();
2199         loadModuleInfo();
2200         return true;
2201 }
2202
2203
2204 void GuiDocument::clearParams()
2205 {
2206         bp_ = BufferParams();
2207 }
2208
2209
2210 BufferId GuiDocument::id() const
2211 {
2212         return &buffer();
2213 }
2214
2215
2216 vector<GuiDocument::modInfoStruct> const & GuiDocument::getModuleInfo()
2217 {
2218         return moduleNames_;
2219 }
2220
2221
2222 vector<GuiDocument::modInfoStruct> const GuiDocument::getSelectedModules()
2223 {
2224         vector<string> const & mods = params().getModules();
2225         vector<string>::const_iterator it =  mods.begin();
2226         vector<string>::const_iterator end = mods.end();
2227         vector<modInfoStruct> mInfo;
2228         for (; it != end; ++it) {
2229                 modInfoStruct m;
2230                 m.id = *it;
2231                 LyXModule * mod = moduleList[*it];
2232                 if (mod)
2233                         m.name = qt_(mod->getName());
2234                 else 
2235                         m.name = toqstr(*it) + toqstr(" (") + qt_("Not Found") + toqstr(")");
2236                 mInfo.push_back(m);
2237         }
2238         return mInfo;
2239 }
2240
2241
2242 DocumentClass const & GuiDocument::documentClass() const
2243 {
2244         return bp_.documentClass();
2245 }
2246
2247
2248 static void dispatch_bufferparams(Dialog const & dialog,
2249         BufferParams const & bp, FuncCode lfun)
2250 {
2251         ostringstream ss;
2252         ss << "\\begin_header\n";
2253         bp.writeFile(ss);
2254         ss << "\\end_header\n";
2255         dialog.dispatch(FuncRequest(lfun, ss.str()));
2256 }
2257
2258
2259 void GuiDocument::dispatchParams()
2260 {
2261         // This must come first so that a language change is correctly noticed
2262         setLanguage();
2263
2264         // Apply the BufferParams. Note that this will set the base class
2265         // and then update the buffer's layout.
2266         dispatch_bufferparams(*this, params(), LFUN_BUFFER_PARAMS_APPLY);
2267
2268         // Generate the colours requested by each new branch.
2269         BranchList & branchlist = params().branchlist();
2270         if (!branchlist.empty()) {
2271                 BranchList::const_iterator it = branchlist.begin();
2272                 BranchList::const_iterator const end = branchlist.end();
2273                 for (; it != end; ++it) {
2274                         docstring const & current_branch = it->getBranch();
2275                         Branch const * branch = branchlist.find(current_branch);
2276                         string const x11hexname = X11hexname(branch->getColor());
2277                         // display the new color
2278                         docstring const str = current_branch + ' ' + from_ascii(x11hexname);
2279                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
2280                 }
2281
2282                 // Open insets of selected branches, close deselected ones
2283                 dispatch(FuncRequest(LFUN_ALL_INSETS_TOGGLE,
2284                         "assign branch"));
2285         }
2286         // FIXME: If we used an LFUN, we would not need those two lines:
2287         bufferview()->processUpdateFlags(Update::Force | Update::FitCursor);
2288 }
2289
2290
2291 void GuiDocument::setLanguage() const
2292 {
2293         Language const * const newL = bp_.language;
2294         if (buffer().params().language == newL)
2295                 return;
2296
2297         string const & lang_name = newL->lang();
2298         dispatch(FuncRequest(LFUN_BUFFER_LANGUAGE, lang_name));
2299 }
2300
2301
2302 void GuiDocument::saveAsDefault() const
2303 {
2304         dispatch_bufferparams(*this, params(), LFUN_BUFFER_SAVE_AS_DEFAULT);
2305 }
2306
2307
2308 bool GuiDocument::isFontAvailable(string const & font) const
2309 {
2310         if (font == "default" || font == "cmr"
2311             || font == "cmss" || font == "cmtt")
2312                 // these are standard
2313                 return true;
2314         if (font == "lmodern" || font == "lmss" || font == "lmtt")
2315                 return LaTeXFeatures::isAvailable("lmodern");
2316         if (font == "times" || font == "palatino"
2317                  || font == "helvet" || font == "courier")
2318                 return LaTeXFeatures::isAvailable("psnfss");
2319         if (font == "cmbr" || font == "cmtl")
2320                 return LaTeXFeatures::isAvailable("cmbright");
2321         if (font == "utopia")
2322                 return LaTeXFeatures::isAvailable("utopia")
2323                         || LaTeXFeatures::isAvailable("fourier");
2324         if (font == "beraserif" || font == "berasans"
2325                 || font == "beramono")
2326                 return LaTeXFeatures::isAvailable("bera");
2327         return LaTeXFeatures::isAvailable(font);
2328 }
2329
2330
2331 bool GuiDocument::providesOSF(string const & font) const
2332 {
2333         if (font == "cmr")
2334                 return isFontAvailable("eco");
2335         if (font == "palatino")
2336                 return isFontAvailable("mathpazo");
2337         return false;
2338 }
2339
2340
2341 bool GuiDocument::providesSC(string const & font) const
2342 {
2343         if (font == "palatino")
2344                 return isFontAvailable("mathpazo");
2345         if (font == "utopia")
2346                 return isFontAvailable("fourier");
2347         return false;
2348 }
2349
2350
2351 bool GuiDocument::providesScale(string const & font) const
2352 {
2353         return font == "helvet" || font == "luximono"
2354                 || font == "berasans"  || font == "beramono";
2355 }
2356
2357
2358 void GuiDocument::loadModuleInfo()
2359 {
2360         moduleNames_.clear();
2361         LyXModuleList::const_iterator it  = moduleList.begin();
2362         LyXModuleList::const_iterator end = moduleList.end();
2363         for (; it != end; ++it) {
2364                 modInfoStruct m;
2365                 m.id = it->getID();
2366                 m.name = qt_(it->getName());
2367                 // this is supposed to give us the first sentence of the description
2368                 QString desc = qt_(it->getDescription());
2369                 int const pos = desc.indexOf(".");
2370                 if (pos > 0)
2371                         desc.truncate(pos + 1);
2372                 m.description = desc;
2373                 moduleNames_.push_back(m);
2374         }
2375 }
2376
2377
2378 Dialog * createGuiDocument(GuiView & lv) { return new GuiDocument(lv); }
2379
2380
2381 } // namespace frontend
2382 } // namespace lyx
2383
2384 #include "GuiDocument_moc.cpp"