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