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