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