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