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