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