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