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