]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiDocument.cpp
save a few cycles
[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, QString> > 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(QString)),
722                 this, SLOT(change_adaptor()));
723         connect(marginsModule->topUnit, SIGNAL(activated(int)),
724                 this, SLOT(change_adaptor()));
725         connect(marginsModule->bottomLE, SIGNAL(textChanged(QString)),
726                 this, SLOT(change_adaptor()));
727         connect(marginsModule->bottomUnit, SIGNAL(activated(int)),
728                 this, SLOT(change_adaptor()));
729         connect(marginsModule->innerLE, SIGNAL(textChanged(QString)),
730                 this, SLOT(change_adaptor()));
731         connect(marginsModule->innerUnit, SIGNAL(activated(int)),
732                 this, SLOT(change_adaptor()));
733         connect(marginsModule->outerLE, SIGNAL(textChanged(QString)),
734                 this, SLOT(change_adaptor()));
735         connect(marginsModule->outerUnit, SIGNAL(activated(int)),
736                 this, SLOT(change_adaptor()));
737         connect(marginsModule->headheightLE, SIGNAL(textChanged(QString)),
738                 this, SLOT(change_adaptor()));
739         connect(marginsModule->headheightUnit, SIGNAL(activated(int)),
740                 this, SLOT(change_adaptor()));
741         connect(marginsModule->headsepLE, SIGNAL(textChanged(QString)),
742                 this, SLOT(change_adaptor()));
743         connect(marginsModule->headsepUnit, SIGNAL(activated(int)),
744                 this, SLOT(change_adaptor()));
745         connect(marginsModule->footskipLE, SIGNAL(textChanged(QString)),
746                 this, SLOT(change_adaptor()));
747         connect(marginsModule->footskipUnit, SIGNAL(activated(int)),
748                 this, SLOT(change_adaptor()));
749         connect(marginsModule->columnsepLE, SIGNAL(textChanged(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(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(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(QString)),
951                 this, SLOT(change_adaptor()));
952         connect(pdfSupportModule->authorLE, SIGNAL(textChanged(QString)),
953                 this, SLOT(change_adaptor()));
954         connect(pdfSupportModule->subjectLE, SIGNAL(textChanged(QString)),
955                 this, SLOT(change_adaptor()));
956         connect(pdfSupportModule->keywordsLE, SIGNAL(textChanged(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(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                 QString style_gui = qt_(style);
1220                 pagestyles.push_back(pair<string, QString>(style, style_gui));
1221                 pageLayoutModule->pagestyleCO->addItem(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(pagestyles[i].second);
1234
1235         if (nn > 0)
1236                 pageLayoutModule->pagestyleCO->setCurrentIndex(nn);
1237 }
1238
1239
1240 void GuiDocument::browseLayout()
1241 {
1242         QString const label1 = qt_("Layouts|#o#O");
1243         QString const dir1 = toqstr(lyxrc.document_path);
1244         QStringList const filter(qt_("LyX Layout (*.layout)"));
1245         QString file = browseRelFile(QString(), bufferFilepath(),
1246                 qt_("Local layout file"), filter, false,
1247                 label1, dir1);
1248
1249         if (!file.endsWith(".layout"))
1250                 return;
1251
1252         FileName layoutFile = support::makeAbsPath(fromqstr(file),
1253                 fromqstr(bufferFilepath()));
1254         
1255         int const ret = Alert::prompt(_("Local layout file"),
1256                 _("The layout file you have selected is a local layout\n"
1257                   "file, not one in the system or user directory. Your\n"
1258                   "document may not work with this layout if you do not\n"
1259                   "keep the layout file in the document directory."),
1260                   1, 1, _("&Set Layout"), _("&Cancel"));
1261         if (ret == 1)
1262                 return;
1263
1264         // load the layout file
1265         LayoutFileList & bcl = LayoutFileList::get();
1266         string classname = layoutFile.onlyFileName();
1267         // this will update an existing layout if that layout has been loaded before.
1268         LayoutFileIndex name = bcl.addLocalLayout(
1269                 classname.substr(0, classname.size() - 7),
1270                 layoutFile.onlyPath().absFilename());
1271
1272         if (name.empty()) {
1273                 Alert::error(_("Error"),
1274                         _("Unable to read local layout file."));                
1275                 return;
1276         }
1277
1278         // do not trigger classChanged if there is no change.
1279         if (latexModule->classCO->currentText() == toqstr(name))
1280                 return;
1281                 
1282         // add to combo box
1283         int idx = latexModule->classCO->findText(toqstr(name));
1284         if (idx == -1) {
1285                 classes_model_.insertRow(0, toqstr(name), name);
1286                 latexModule->classCO->setCurrentIndex(0);
1287         } else
1288                 latexModule->classCO->setCurrentIndex(idx);
1289         
1290         classChanged();
1291 }
1292
1293
1294 void GuiDocument::browseMaster()
1295 {
1296         QString const title = qt_("Select master document");
1297         QString const dir1 = toqstr(lyxrc.document_path);
1298         QString const old = latexModule->childDocLE->text();
1299         QString const docpath = toqstr(support::onlyPath(buffer().absFileName()));
1300         QStringList const filter(qt_("LyX Files (*.lyx)"));
1301         QString file = browseRelFile(old, docpath, title, filter, false,
1302                 qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
1303
1304         latexModule->childDocLE->setText(file);
1305 }
1306
1307
1308 void GuiDocument::classChanged()
1309 {
1310         int idx = latexModule->classCO->currentIndex();
1311         if (idx < 0) 
1312                 return;
1313         string const classname = classes_model_.getIDString(idx);
1314
1315         // FIXME Note that by doing things this way, we load the TextClass
1316         // as soon as it is selected. So, if you use the scroll wheel when
1317         // sitting on the combo box, we'll load a lot of TextClass objects
1318         // very quickly. This could be changed.
1319         if (!bp_.setBaseClass(classname)) {
1320                 Alert::error(_("Error"), _("Unable to set document class."));
1321                 return;
1322         }
1323         if (lyxrc.auto_reset_options) {
1324                 if (applyPB->isEnabled()) {
1325                         int const ret = Alert::prompt(_("Unapplied changes"),
1326                                         _("Some changes in the dialog were not yet applied.\n"
1327                                         "If you do not apply now, they will be lost after this action."),
1328                                         1, 1, _("&Apply"), _("&Dismiss"));
1329                         if (ret == 0)
1330                                 applyView();
1331                 }
1332                 bp_.useClassDefaults();
1333                 paramsToDialog(bp_);
1334         }
1335         // FIXME There's a little bug here connected with auto_reset, namely,
1336         // that, if the preceding is skipped and the user has changed the
1337         // modules before changing the class, those changes will be lost on
1338         // update. But maybe that's what we want?
1339         updateSelectedModules();
1340 }
1341
1342
1343 namespace {
1344         // This is an insanely complicated attempt to make this sort of thing
1345         // work with RTL languages.
1346         docstring formatStrVec(vector<string> const & v, docstring const & s) 
1347         {
1348                 //this mess formats the list as "v[0], v[1], ..., [s] v[n]"
1349                 if (v.size() == 0)
1350                         return docstring();
1351                 if (v.size() == 1) 
1352                         return from_ascii(v[0]);
1353                 if (v.size() == 2) {
1354                         docstring retval = _("%1$s and %2$s");
1355                         retval = subst(retval, _("and"), s);
1356                         return bformat(retval, from_ascii(v[0]), from_ascii(v[1]));
1357                 }
1358                 // The idea here is to format all but the last two items...
1359                 int const vSize = v.size();
1360                 docstring t2 = _("%1$s, %2$s");
1361                 docstring retval = from_ascii(v[0]);
1362                 for (int i = 1; i < vSize - 2; ++i)
1363                         retval = bformat(t2, retval, from_ascii(v[i])); 
1364                 //...and then to  plug them, and the last two, into this schema
1365                 docstring t = _("%1$s, %2$s, and %3$s");
1366                 t = subst(t, _("and"), s);
1367                 return bformat(t, retval, from_ascii(v[vSize - 2]), from_ascii(v[vSize - 1]));
1368         }
1369         
1370         vector<string> idsToNames(vector<string> const & idList)
1371         {
1372                 vector<string> retval;
1373                 vector<string>::const_iterator it  = idList.begin();
1374                 vector<string>::const_iterator end = idList.end();
1375                 for (; it != end; ++it) {
1376                         LyXModule const * const mod = moduleList[*it];
1377                         if (!mod)
1378                                 retval.push_back(*it + " (Unavailable)");
1379                         else
1380                                 retval.push_back(mod->getName());
1381                 }
1382                 return retval;
1383         }
1384 }
1385
1386
1387 void GuiDocument::updateModuleInfo()
1388 {
1389         selectionManager->update();
1390         
1391         //Module description
1392         bool const focusOnSelected = selectionManager->selectedFocused();
1393         QListView const * const lv = 
1394                         focusOnSelected ? latexModule->selectedLV : latexModule->availableLV;
1395         if (lv->selectionModel()->selectedIndexes().isEmpty()) {
1396                 latexModule->infoML->document()->clear();
1397                 return;
1398         }
1399         QModelIndex const & idx = lv->selectionModel()->currentIndex();
1400         GuiIdListModel const & idModel = 
1401                         focusOnSelected  ? modules_sel_model_ : modules_av_model_;
1402         string const modName = idModel.getIDString(idx.row());
1403         docstring desc = getModuleDescription(modName);
1404
1405         vector<string> pkgList = getPackageList(modName);
1406         docstring pkgdesc = formatStrVec(pkgList, _("and"));
1407         if (!pkgdesc.empty()) {
1408                 if (!desc.empty())
1409                         desc += "\n";
1410                 desc += bformat(_("Package(s) required: %1$s."), pkgdesc);
1411         }
1412
1413         pkgList = getRequiredList(modName);
1414         if (!pkgList.empty()) {
1415                 vector<string> const reqDescs = idsToNames(pkgList);
1416                 pkgdesc = formatStrVec(reqDescs, _("or"));
1417                 if (!desc.empty())
1418                         desc += "\n";
1419                 desc += bformat(_("Module required: %1$s."), pkgdesc);
1420         }
1421
1422         pkgList = getExcludedList(modName);
1423         if (!pkgList.empty()) {
1424                 vector<string> const reqDescs = idsToNames(pkgList);
1425                 pkgdesc = formatStrVec(reqDescs, _( "and"));
1426                 if (!desc.empty())
1427                         desc += "\n";
1428                 desc += bformat(_("Modules excluded: %1$s."), pkgdesc);
1429         }
1430
1431         if (!isModuleAvailable(modName)) {
1432                 if (!desc.empty())
1433                         desc += "\n";
1434                 desc += _("WARNING: Some packages are unavailable!");
1435         }
1436
1437         latexModule->infoML->document()->setPlainText(toqstr(desc));
1438 }
1439
1440
1441 void GuiDocument::updateNumbering()
1442 {
1443         DocumentClass const & tclass = bp_.documentClass();
1444
1445         numberingModule->tocTW->setUpdatesEnabled(false);
1446         numberingModule->tocTW->clear();
1447
1448         int const depth = numberingModule->depthSL->value();
1449         int const toc = numberingModule->tocSL->value();
1450         QString const no = qt_("No");
1451         QString const yes = qt_("Yes");
1452         QTreeWidgetItem * item = 0;
1453
1454         DocumentClass::const_iterator lit = tclass.begin();
1455         DocumentClass::const_iterator len = tclass.end();
1456         for (; lit != len; ++lit) {
1457                 int const toclevel = lit->toclevel;
1458                 if (toclevel != Layout::NOT_IN_TOC && lit->labeltype == LABEL_COUNTER) {
1459                         item = new QTreeWidgetItem(numberingModule->tocTW);
1460                         item->setText(0, toqstr(translateIfPossible(lit->name())));
1461                         item->setText(1, (toclevel <= depth) ? yes : no);
1462                         item->setText(2, (toclevel <= toc) ? yes : no);
1463                 }
1464         }
1465
1466         numberingModule->tocTW->setUpdatesEnabled(true);
1467         numberingModule->tocTW->update();
1468 }
1469
1470
1471 void GuiDocument::apply(BufferParams & params)
1472 {
1473         // preamble
1474         preambleModule->apply(params);
1475
1476         // biblio
1477         params.setCiteEngine(ENGINE_BASIC);
1478
1479         if (biblioModule->citeNatbibRB->isChecked()) {
1480                 bool const use_numerical_citations =
1481                         biblioModule->citeStyleCO->currentIndex();
1482                 if (use_numerical_citations)
1483                         params.setCiteEngine(ENGINE_NATBIB_NUMERICAL);
1484                 else
1485                         params.setCiteEngine(ENGINE_NATBIB_AUTHORYEAR);
1486
1487         } else if (biblioModule->citeJurabibRB->isChecked())
1488                 params.setCiteEngine(ENGINE_JURABIB);
1489
1490         params.use_bibtopic =
1491                 biblioModule->bibtopicCB->isChecked();
1492
1493         // language & quotes
1494         if (langModule->defaultencodingRB->isChecked()) {
1495                 params.inputenc = "auto";
1496         } else {
1497                 int i = langModule->encodingCO->currentIndex();
1498                 if (i == 0)
1499                         params.inputenc = "default";
1500                 else {
1501                         QString const enc_gui =
1502                                 langModule->encodingCO->currentText();
1503                         Encodings::const_iterator it = encodings.begin();
1504                         Encodings::const_iterator const end = encodings.end();
1505                         bool found = false;
1506                         for (; it != end; ++it) {
1507                                 if (qt_(it->guiName()) == enc_gui) {
1508                                         params.inputenc = it->latexName();
1509                                         found = true;
1510                                         break;
1511                                 }
1512                         }
1513                         if (!found) {
1514                                 // should not happen
1515                                 lyxerr << "GuiDocument::apply: Unknown encoding! Resetting to default" << endl;
1516                                 params.inputenc = "default";
1517                         }
1518                 }
1519         }
1520
1521         InsetQuotes::QuoteLanguage lga = InsetQuotes::EnglishQuotes;
1522         switch (langModule->quoteStyleCO->currentIndex()) {
1523         case 0:
1524                 lga = InsetQuotes::EnglishQuotes;
1525                 break;
1526         case 1:
1527                 lga = InsetQuotes::SwedishQuotes;
1528                 break;
1529         case 2:
1530                 lga = InsetQuotes::GermanQuotes;
1531                 break;
1532         case 3:
1533                 lga = InsetQuotes::PolishQuotes;
1534                 break;
1535         case 4:
1536                 lga = InsetQuotes::FrenchQuotes;
1537                 break;
1538         case 5:
1539                 lga = InsetQuotes::DanishQuotes;
1540                 break;
1541         }
1542         params.quotes_language = lga;
1543
1544         QString const lang = langModule->languageCO->itemData(
1545                 langModule->languageCO->currentIndex()).toString();
1546         params.language = lyx::languages.getLanguage(fromqstr(lang));
1547
1548         // numbering
1549         if (params.documentClass().hasTocLevels()) {
1550                 params.tocdepth = numberingModule->tocSL->value();
1551                 params.secnumdepth = numberingModule->depthSL->value();
1552         }
1553
1554         // bullets
1555         params.user_defined_bullet(0) = bulletsModule->bullet(0);
1556         params.user_defined_bullet(1) = bulletsModule->bullet(1);
1557         params.user_defined_bullet(2) = bulletsModule->bullet(2);
1558         params.user_defined_bullet(3) = bulletsModule->bullet(3);
1559
1560         // packages
1561         params.graphicsDriver =
1562                 tex_graphics[latexModule->psdriverCO->currentIndex()];
1563         
1564         // text layout
1565         int idx = latexModule->classCO->currentIndex();
1566         if (idx >= 0) {
1567                 string const classname = classes_model_.getIDString(idx);
1568                 params.setBaseClass(classname);
1569         }
1570
1571         // Modules
1572         params.clearLayoutModules();
1573         int const srows = modules_sel_model_.rowCount();
1574         vector<string> selModList;
1575         for (int i = 0; i < srows; ++i)
1576                 params.addLayoutModule(modules_sel_model_.getIDString(i));
1577         // update the list of removed modules
1578         params.clearRemovedModules();
1579         set<string> const & reqmods = params.baseClass()->defaultModules();
1580         set<string>::const_iterator rit = reqmods.begin();
1581         set<string>::const_iterator ren = reqmods.end();
1582         // check each of the required modules
1583         for (; rit != ren; rit++) {
1584                 vector<string>::const_iterator mit = params.getModules().begin();
1585                 vector<string>::const_iterator men = params.getModules().end();
1586                 bool found = false;
1587                 for (; mit != men; mit++) {
1588                         if (*rit == *mit) {
1589                                 found = true;
1590                                 break;
1591                         }
1592                 }
1593                 if (!found) {
1594                         // the module isn't present so must have been removed by the user
1595                         params.addRemovedModule(*rit);
1596                 }
1597         }
1598
1599         if (mathsModule->amsautoCB->isChecked()) {
1600                 params.use_amsmath = BufferParams::package_auto;
1601         } else {
1602                 if (mathsModule->amsCB->isChecked())
1603                         params.use_amsmath = BufferParams::package_on;
1604                 else
1605                         params.use_amsmath = BufferParams::package_off;
1606         }
1607
1608         if (mathsModule->esintautoCB->isChecked())
1609                 params.use_esint = BufferParams::package_auto;
1610         else {
1611                 if (mathsModule->esintCB->isChecked())
1612                         params.use_esint = BufferParams::package_on;
1613                 else
1614                         params.use_esint = BufferParams::package_off;
1615         }
1616
1617         if (pageLayoutModule->pagestyleCO->currentIndex() == 0)
1618                 params.pagestyle = "default";
1619         else {
1620                 QString style_gui = pageLayoutModule->pagestyleCO->currentText();
1621                 for (size_t i = 0; i != pagestyles.size(); ++i)
1622                         if (pagestyles[i].second == style_gui)
1623                                 params.pagestyle = pagestyles[i].first;
1624         }
1625
1626         switch (textLayoutModule->lspacingCO->currentIndex()) {
1627         case 0:
1628                 params.spacing().set(Spacing::Single);
1629                 break;
1630         case 1:
1631                 params.spacing().set(Spacing::Onehalf);
1632                 break;
1633         case 2:
1634                 params.spacing().set(Spacing::Double);
1635                 break;
1636         case 3:
1637                 params.spacing().set(Spacing::Other,
1638                         fromqstr(textLayoutModule->lspacingLE->text()));
1639                 break;
1640         }
1641
1642         if (textLayoutModule->twoColumnCB->isChecked())
1643                 params.columns = 2;
1644         else
1645                 params.columns = 1;
1646
1647         // text should have passed validation
1648         params.listings_params =
1649                 InsetListingsParams(fromqstr(textLayoutModule->listingsED->toPlainText())).params();
1650
1651         if (textLayoutModule->indentRB->isChecked())
1652                 params.paragraph_separation = BufferParams::ParagraphIndentSeparation;
1653         else
1654                 params.paragraph_separation = BufferParams::ParagraphSkipSeparation;
1655
1656         switch (textLayoutModule->skipCO->currentIndex()) {
1657         case 0:
1658                 params.setDefSkip(VSpace(VSpace::SMALLSKIP));
1659                 break;
1660         case 1:
1661                 params.setDefSkip(VSpace(VSpace::MEDSKIP));
1662                 break;
1663         case 2:
1664                 params.setDefSkip(VSpace(VSpace::BIGSKIP));
1665                 break;
1666         case 3:
1667         {
1668                 VSpace vs = VSpace(
1669                         widgetsToLength(textLayoutModule->skipLE,
1670                                 textLayoutModule->skipLengthCO)
1671                         );
1672                 params.setDefSkip(vs);
1673                 break;
1674         }
1675         default:
1676                 // DocumentDefskipCB assures that this never happens
1677                 // so Assert then !!!  - jbl
1678                 params.setDefSkip(VSpace(VSpace::MEDSKIP));
1679                 break;
1680         }
1681
1682         params.options =
1683                 fromqstr(latexModule->optionsLE->text());
1684
1685         if (latexModule->childDocGB->isChecked())
1686                 params.master =
1687                         fromqstr(latexModule->childDocLE->text());
1688         else
1689                 params.master = string();
1690
1691         params.float_placement = floatModule->get();
1692
1693         // fonts
1694         params.fontsRoman =
1695                 tex_fonts_roman[fontModule->fontsRomanCO->currentIndex()];
1696
1697         params.fontsSans =
1698                 tex_fonts_sans[fontModule->fontsSansCO->currentIndex()];
1699
1700         params.fontsTypewriter =
1701                 tex_fonts_monospaced[fontModule->fontsTypewriterCO->currentIndex()];
1702
1703         params.fontsCJK =
1704                 fromqstr(fontModule->cjkFontLE->text());
1705
1706         params.fontsSansScale = fontModule->scaleSansSB->value();
1707
1708         params.fontsTypewriterScale = fontModule->scaleTypewriterSB->value();
1709
1710         params.fontsSC = fontModule->fontScCB->isChecked();
1711
1712         params.fontsOSF = fontModule->fontOsfCB->isChecked();
1713
1714         params.fontsDefaultFamily = GuiDocument::fontfamilies[
1715                 fontModule->fontsDefaultCO->currentIndex()];
1716
1717         if (fontModule->fontsizeCO->currentIndex() == 0)
1718                 params.fontsize = "default";
1719         else
1720                 params.fontsize =
1721                         fromqstr(fontModule->fontsizeCO->currentText());
1722
1723         // paper
1724         params.papersize = PAPER_SIZE(
1725                 pageLayoutModule->papersizeCO->currentIndex());
1726
1727         // custom, A3, B3 and B4 paper sizes need geometry
1728         int psize = pageLayoutModule->papersizeCO->currentIndex();
1729         bool geom_papersize = (psize == 1 || psize == 5 || psize == 8 || psize == 9);
1730
1731         params.paperwidth = widgetsToLength(pageLayoutModule->paperwidthLE,
1732                 pageLayoutModule->paperwidthUnitCO);
1733
1734         params.paperheight = widgetsToLength(pageLayoutModule->paperheightLE,
1735                 pageLayoutModule->paperheightUnitCO);
1736
1737         if (pageLayoutModule->facingPagesCB->isChecked())
1738                 params.sides = TwoSides;
1739         else
1740                 params.sides = OneSide;
1741
1742         if (pageLayoutModule->landscapeRB->isChecked())
1743                 params.orientation = ORIENTATION_LANDSCAPE;
1744         else
1745                 params.orientation = ORIENTATION_PORTRAIT;
1746
1747         // margins
1748         params.use_geometry = !marginsModule->marginCB->isChecked()
1749                 || geom_papersize;
1750
1751         Ui::MarginsUi const * m = marginsModule;
1752
1753         params.leftmargin = widgetsToLength(m->innerLE, m->innerUnit);
1754         params.topmargin = widgetsToLength(m->topLE, m->topUnit);
1755         params.rightmargin = widgetsToLength(m->outerLE, m->outerUnit);
1756         params.bottommargin = widgetsToLength(m->bottomLE, m->bottomUnit);
1757         params.headheight = widgetsToLength(m->headheightLE, m->headheightUnit);
1758         params.headsep = widgetsToLength(m->headsepLE, m->headsepUnit);
1759         params.footskip = widgetsToLength(m->footskipLE, m->footskipUnit);
1760         params.columnsep = widgetsToLength(m->columnsepLE, m->columnsepUnit);
1761
1762         branchesModule->apply(params);
1763
1764         // PDF support
1765         PDFOptions & pdf = params.pdfoptions();
1766         pdf.use_hyperref = pdfSupportModule->use_hyperrefGB->isChecked();
1767         pdf.title = fromqstr(pdfSupportModule->titleLE->text());
1768         pdf.author = fromqstr(pdfSupportModule->authorLE->text());
1769         pdf.subject = fromqstr(pdfSupportModule->subjectLE->text());
1770         pdf.keywords = fromqstr(pdfSupportModule->keywordsLE->text());
1771
1772         pdf.bookmarks = pdfSupportModule->bookmarksGB->isChecked();
1773         pdf.bookmarksnumbered = pdfSupportModule->bookmarksnumberedCB->isChecked();
1774         pdf.bookmarksopen = pdfSupportModule->bookmarksopenGB->isChecked();
1775         pdf.bookmarksopenlevel = pdfSupportModule->bookmarksopenlevelSB->value();
1776
1777         pdf.breaklinks = pdfSupportModule->breaklinksCB->isChecked();
1778         pdf.pdfborder = pdfSupportModule->pdfborderCB->isChecked();
1779         pdf.pdfusetitle = pdfSupportModule->pdfusetitleCB->isChecked();
1780         pdf.colorlinks = pdfSupportModule->colorlinksCB->isChecked();
1781         pdf.backref = pdfSupportModule->backrefCB->isChecked();
1782         pdf.pagebackref = pdfSupportModule->pagebackrefCB->isChecked();
1783         if (pdfSupportModule->fullscreenCB->isChecked())
1784                 pdf.pagemode = pdf.pagemode_fullscreen;
1785         else
1786                 pdf.pagemode.clear();
1787         pdf.quoted_options = pdf.quoted_options_check(
1788                                 fromqstr(pdfSupportModule->optionsLE->text()));
1789 }
1790
1791
1792 void GuiDocument::paramsToDialog(BufferParams const & params)
1793 {
1794         // set the default unit
1795         Length::UNIT defaultUnit = Length::CM;
1796         switch (lyxrc.default_papersize) {
1797                 case PAPER_DEFAULT: break;
1798
1799                 case PAPER_USLETTER:
1800                 case PAPER_USLEGAL:
1801                 case PAPER_USEXECUTIVE:
1802                         defaultUnit = Length::IN;
1803                         break;
1804
1805                 case PAPER_A3:
1806                 case PAPER_A4:
1807                 case PAPER_A5:
1808                 case PAPER_B3:
1809                 case PAPER_B4:
1810                 case PAPER_B5:
1811                         defaultUnit = Length::CM;
1812                         break;
1813                 case PAPER_CUSTOM:
1814                         break;
1815         }
1816
1817         // preamble
1818         preambleModule->update(params, id());
1819
1820         // biblio
1821         biblioModule->citeDefaultRB->setChecked(
1822                 params.citeEngine() == ENGINE_BASIC);
1823
1824         biblioModule->citeNatbibRB->setChecked(
1825                 params.citeEngine() == ENGINE_NATBIB_NUMERICAL ||
1826                 params.citeEngine() == ENGINE_NATBIB_AUTHORYEAR);
1827
1828         biblioModule->citeStyleCO->setCurrentIndex(
1829                 params.citeEngine() == ENGINE_NATBIB_NUMERICAL);
1830
1831         biblioModule->citeJurabibRB->setChecked(
1832                 params.citeEngine() == ENGINE_JURABIB);
1833
1834         biblioModule->bibtopicCB->setChecked(
1835                 params.use_bibtopic);
1836
1837         // language & quotes
1838         int const pos = langModule->languageCO->findData(toqstr(
1839                 params.language->lang()));
1840         langModule->languageCO->setCurrentIndex(pos);
1841
1842         langModule->quoteStyleCO->setCurrentIndex(
1843                 params.quotes_language);
1844
1845         bool default_enc = true;
1846         if (params.inputenc != "auto") {
1847                 default_enc = false;
1848                 if (params.inputenc == "default") {
1849                         langModule->encodingCO->setCurrentIndex(0);
1850                 } else {
1851                         string enc_gui;
1852                         Encodings::const_iterator it = encodings.begin();
1853                         Encodings::const_iterator const end = encodings.end();
1854                         for (; it != end; ++it) {
1855                                 if (it->latexName() == params.inputenc) {
1856                                         enc_gui = it->guiName();
1857                                         break;
1858                                 }
1859                         }
1860                         int const i = langModule->encodingCO->findText(
1861                                         qt_(enc_gui));
1862                         if (i >= 0)
1863                                 langModule->encodingCO->setCurrentIndex(i);
1864                         else
1865                                 // unknown encoding. Set to default.
1866                                 default_enc = true;
1867                 }
1868         }
1869         langModule->defaultencodingRB->setChecked(default_enc);
1870         langModule->otherencodingRB->setChecked(!default_enc);
1871
1872         // numbering
1873         int const min_toclevel = documentClass().min_toclevel();
1874         int const max_toclevel = documentClass().max_toclevel();
1875         if (documentClass().hasTocLevels()) {
1876                 numberingModule->setEnabled(true);
1877                 numberingModule->depthSL->setMinimum(min_toclevel - 1);
1878                 numberingModule->depthSL->setMaximum(max_toclevel);
1879                 numberingModule->depthSL->setValue(params.secnumdepth);
1880                 numberingModule->tocSL->setMaximum(min_toclevel - 1);
1881                 numberingModule->tocSL->setMaximum(max_toclevel);
1882                 numberingModule->tocSL->setValue(params.tocdepth);
1883                 updateNumbering();
1884         } else {
1885                 numberingModule->setEnabled(false);
1886                 numberingModule->tocTW->clear();
1887         }
1888
1889         // bullets
1890         bulletsModule->setBullet(0, params.user_defined_bullet(0));
1891         bulletsModule->setBullet(1, params.user_defined_bullet(1));
1892         bulletsModule->setBullet(2, params.user_defined_bullet(2));
1893         bulletsModule->setBullet(3, params.user_defined_bullet(3));
1894         bulletsModule->init();
1895
1896         // packages
1897         int nitem = findToken(tex_graphics, params.graphicsDriver);
1898         if (nitem >= 0)
1899                 latexModule->psdriverCO->setCurrentIndex(nitem);
1900         updateModuleInfo();
1901         
1902         mathsModule->amsCB->setChecked(
1903                 params.use_amsmath == BufferParams::package_on);
1904         mathsModule->amsautoCB->setChecked(
1905                 params.use_amsmath == BufferParams::package_auto);
1906
1907         mathsModule->esintCB->setChecked(
1908                 params.use_esint == BufferParams::package_on);
1909         mathsModule->esintautoCB->setChecked(
1910                 params.use_esint == BufferParams::package_auto);
1911
1912         switch (params.spacing().getSpace()) {
1913                 case Spacing::Other: nitem = 3; break;
1914                 case Spacing::Double: nitem = 2; break;
1915                 case Spacing::Onehalf: nitem = 1; break;
1916                 case Spacing::Default: case Spacing::Single: nitem = 0; break;
1917         }
1918
1919         // text layout
1920         string const & layoutID = params.baseClassID();
1921         setLayoutComboByIDString(layoutID);
1922
1923         updatePagestyle(documentClass().opt_pagestyle(),
1924                                  params.pagestyle);
1925
1926         textLayoutModule->lspacingCO->setCurrentIndex(nitem);
1927         if (params.spacing().getSpace() == Spacing::Other) {
1928                 textLayoutModule->lspacingLE->setText(
1929                         toqstr(params.spacing().getValueAsString()));
1930         }
1931         setLSpacing(nitem);
1932
1933         if (params.paragraph_separation == BufferParams::ParagraphIndentSeparation)
1934                 textLayoutModule->indentRB->setChecked(true);
1935         else
1936                 textLayoutModule->skipRB->setChecked(true);
1937
1938         int skip = 0;
1939         switch (params.getDefSkip().kind()) {
1940         case VSpace::SMALLSKIP:
1941                 skip = 0;
1942                 break;
1943         case VSpace::MEDSKIP:
1944                 skip = 1;
1945                 break;
1946         case VSpace::BIGSKIP:
1947                 skip = 2;
1948                 break;
1949         case VSpace::LENGTH:
1950         {
1951                 skip = 3;
1952                 string const length = params.getDefSkip().asLyXCommand();
1953                 lengthToWidgets(textLayoutModule->skipLE,
1954                         textLayoutModule->skipLengthCO,
1955                         length, defaultUnit);
1956                 break;
1957         }
1958         default:
1959                 skip = 0;
1960                 break;
1961         }
1962         textLayoutModule->skipCO->setCurrentIndex(skip);
1963         setSkip(skip);
1964
1965         textLayoutModule->twoColumnCB->setChecked(
1966                 params.columns == 2);
1967
1968         // break listings_params to multiple lines
1969         string lstparams =
1970                 InsetListingsParams(params.listings_params).separatedParams();
1971         textLayoutModule->listingsED->setPlainText(toqstr(lstparams));
1972
1973         if (!params.options.empty()) {
1974                 latexModule->optionsLE->setText(
1975                         toqstr(params.options));
1976         } else {
1977                 latexModule->optionsLE->setText(QString());
1978         }
1979
1980         if (!params.master.empty()) {
1981                 latexModule->childDocGB->setChecked(true);
1982                 latexModule->childDocLE->setText(
1983                         toqstr(params.master));
1984         } else {
1985                 latexModule->childDocLE->setText(QString());
1986                 latexModule->childDocGB->setChecked(false);
1987         }
1988
1989         floatModule->set(params.float_placement);
1990
1991         // Fonts
1992         updateFontsize(documentClass().opt_fontsize(),
1993                         params.fontsize);
1994
1995         int n = findToken(tex_fonts_roman, params.fontsRoman);
1996         if (n >= 0) {
1997                 fontModule->fontsRomanCO->setCurrentIndex(n);
1998                 romanChanged(n);
1999         }
2000
2001         n = findToken(tex_fonts_sans, params.fontsSans);
2002         if (n >= 0)     {
2003                 fontModule->fontsSansCO->setCurrentIndex(n);
2004                 sansChanged(n);
2005         }
2006
2007         n = findToken(tex_fonts_monospaced, params.fontsTypewriter);
2008         if (n >= 0) {
2009                 fontModule->fontsTypewriterCO->setCurrentIndex(n);
2010                 ttChanged(n);
2011         }
2012
2013         if (!params.fontsCJK.empty())
2014                 fontModule->cjkFontLE->setText(
2015                         toqstr(params.fontsCJK));
2016         else
2017                 fontModule->cjkFontLE->setText(QString());
2018
2019         fontModule->fontScCB->setChecked(params.fontsSC);
2020         fontModule->fontOsfCB->setChecked(params.fontsOSF);
2021         fontModule->scaleSansSB->setValue(params.fontsSansScale);
2022         fontModule->scaleTypewriterSB->setValue(params.fontsTypewriterScale);
2023         n = findToken(GuiDocument::fontfamilies, params.fontsDefaultFamily);
2024         if (n >= 0)
2025                 fontModule->fontsDefaultCO->setCurrentIndex(n);
2026
2027         // paper
2028         int const psize = params.papersize;
2029         pageLayoutModule->papersizeCO->setCurrentIndex(psize);
2030         setCustomPapersize(psize);
2031
2032         bool const landscape =
2033                 params.orientation == ORIENTATION_LANDSCAPE;
2034         pageLayoutModule->landscapeRB->setChecked(landscape);
2035         pageLayoutModule->portraitRB->setChecked(!landscape);
2036
2037         pageLayoutModule->facingPagesCB->setChecked(
2038                 params.sides == TwoSides);
2039
2040
2041         lengthToWidgets(pageLayoutModule->paperwidthLE,
2042                 pageLayoutModule->paperwidthUnitCO, params.paperwidth, defaultUnit);
2043
2044         lengthToWidgets(pageLayoutModule->paperheightLE,
2045                 pageLayoutModule->paperheightUnitCO, params.paperheight, defaultUnit);
2046
2047         // margins
2048         Ui::MarginsUi * m = marginsModule;
2049
2050         setMargins(!params.use_geometry);
2051
2052         lengthToWidgets(m->topLE, m->topUnit,
2053                 params.topmargin, defaultUnit);
2054
2055         lengthToWidgets(m->bottomLE, m->bottomUnit,
2056                 params.bottommargin, defaultUnit);
2057
2058         lengthToWidgets(m->innerLE, m->innerUnit,
2059                 params.leftmargin, defaultUnit);
2060
2061         lengthToWidgets(m->outerLE, m->outerUnit,
2062                 params.rightmargin, defaultUnit);
2063
2064         lengthToWidgets(m->headheightLE, m->headheightUnit,
2065                 params.headheight, defaultUnit);
2066
2067         lengthToWidgets(m->headsepLE, m->headsepUnit,
2068                 params.headsep, defaultUnit);
2069
2070         lengthToWidgets(m->footskipLE, m->footskipUnit,
2071                 params.footskip, defaultUnit);
2072
2073         lengthToWidgets(m->columnsepLE, m->columnsepUnit,
2074                 params.columnsep, defaultUnit);
2075
2076         branchesModule->update(params);
2077
2078         // PDF support
2079         PDFOptions const & pdf = params.pdfoptions();
2080         pdfSupportModule->use_hyperrefGB->setChecked(pdf.use_hyperref);
2081         pdfSupportModule->titleLE->setText(toqstr(pdf.title));
2082         pdfSupportModule->authorLE->setText(toqstr(pdf.author));
2083         pdfSupportModule->subjectLE->setText(toqstr(pdf.subject));
2084         pdfSupportModule->keywordsLE->setText(toqstr(pdf.keywords));
2085
2086         pdfSupportModule->bookmarksGB->setChecked(pdf.bookmarks);
2087         pdfSupportModule->bookmarksnumberedCB->setChecked(pdf.bookmarksnumbered);
2088         pdfSupportModule->bookmarksopenGB->setChecked(pdf.bookmarksopen);
2089
2090         pdfSupportModule->bookmarksopenlevelSB->setValue(pdf.bookmarksopenlevel);
2091
2092         pdfSupportModule->breaklinksCB->setChecked(pdf.breaklinks);
2093         pdfSupportModule->pdfborderCB->setChecked(pdf.pdfborder);
2094         pdfSupportModule->pdfusetitleCB->setChecked(pdf.pdfusetitle);
2095         pdfSupportModule->colorlinksCB->setChecked(pdf.colorlinks);
2096         pdfSupportModule->backrefCB->setChecked(pdf.backref);
2097         pdfSupportModule->pagebackrefCB->setChecked(pdf.pagebackref);
2098         pdfSupportModule->fullscreenCB->setChecked
2099                 (pdf.pagemode == pdf.pagemode_fullscreen);
2100
2101         pdfSupportModule->optionsLE->setText(
2102                 toqstr(pdf.quoted_options));
2103 }
2104
2105
2106 void GuiDocument::applyView()
2107 {
2108         apply(params());
2109 }
2110
2111
2112 void GuiDocument::saveDocDefault()
2113 {
2114         // we have to apply the params first
2115         applyView();
2116         saveAsDefault();
2117 }
2118
2119
2120 void GuiDocument::updateAvailableModules() 
2121 {
2122         modules_av_model_.clear();
2123         vector<modInfoStruct> const & modInfoList = getModuleInfo();
2124         int const mSize = modInfoList.size();
2125         for (int i = 0; i != mSize; ++i) {
2126                 modInfoStruct const & modInfo = modInfoList[i];
2127                 modules_av_model_.insertRow(i, modInfo.name, modInfo.id, 
2128                                 modInfo.description);
2129         }
2130 }
2131
2132
2133 void GuiDocument::updateSelectedModules() 
2134 {
2135         // and selected ones, too
2136         modules_sel_model_.clear();
2137         vector<modInfoStruct> const selModList = getSelectedModules();
2138         int const sSize = selModList.size();
2139         for (int i = 0; i != sSize; ++i) {
2140                 modInfoStruct const & modInfo = selModList[i];
2141                 modules_sel_model_.insertRow(i, modInfo.name, modInfo.id,
2142                                 modInfo.description);
2143         }
2144 }
2145
2146
2147 void GuiDocument::updateContents()
2148 {
2149         // Nothing to do here as the document settings is not cursor dependant.
2150         return;
2151 }
2152
2153
2154 void GuiDocument::useClassDefaults()
2155 {
2156         if (applyPB->isEnabled()) {
2157                 int const ret = Alert::prompt(_("Unapplied changes"),
2158                                 _("Some changes in the dialog were not yet applied.\n"
2159                                   "If you do not apply now, they will be lost after this action."),
2160                                 1, 1, _("&Apply"), _("&Dismiss"));
2161                 if (ret == 0)
2162                         applyView();
2163         }
2164
2165         int idx = latexModule->classCO->currentIndex();
2166         string const classname = classes_model_.getIDString(idx);
2167         if (!bp_.setBaseClass(classname)) {
2168                 Alert::error(_("Error"), _("Unable to set document class."));
2169                 return;
2170         }
2171         bp_.useClassDefaults();
2172         paramsToDialog(bp_);
2173 }
2174
2175
2176 void GuiDocument::setLayoutComboByIDString(std::string const & idString)
2177 {
2178         int idx = classes_model_.findIDString(idString);
2179         if (idx < 0)
2180                 Alert::warning(_("Can't set layout!"), 
2181                         bformat(_("Unable to set layout for ID: %1$s"), from_utf8(idString)));
2182         else 
2183                 latexModule->classCO->setCurrentIndex(idx);
2184 }
2185
2186
2187 bool GuiDocument::isValid()
2188 {
2189         return validateListingsParameters().isEmpty()
2190                 && (textLayoutModule->skipCO->currentIndex() != 3
2191                         || !textLayoutModule->skipLE->text().isEmpty());
2192 }
2193
2194
2195 char const * const GuiDocument::fontfamilies[5] = {
2196         "default", "rmdefault", "sfdefault", "ttdefault", ""
2197 };
2198
2199
2200 char const * GuiDocument::fontfamilies_gui[5] = {
2201         N_("Default"), N_("Roman"), N_("Sans Serif"), N_("Typewriter"), ""
2202 };
2203
2204
2205 bool GuiDocument::initialiseParams(string const &)
2206 {
2207         BufferView * view = bufferview();
2208         if (!view) {
2209                 bp_ = BufferParams();
2210                 paramsToDialog(bp_);
2211                 return true;
2212         }
2213         bp_ = view->buffer().params();
2214         loadModuleInfo();
2215         updateAvailableModules();
2216         updateSelectedModules();
2217         //FIXME It'd be nice to make sure here that the selected
2218         //modules are consistent: That required modules are actually
2219         //selected, and that we don't have conflicts. If so, we could
2220         //at least pop up a warning.
2221         paramsToDialog(bp_);
2222         return true;
2223 }
2224
2225
2226 void GuiDocument::clearParams()
2227 {
2228         bp_ = BufferParams();
2229 }
2230
2231
2232 BufferId GuiDocument::id() const
2233 {
2234         BufferView const * const view = bufferview();
2235         return view? &view->buffer() : 0;
2236 }
2237
2238
2239 vector<GuiDocument::modInfoStruct> const & GuiDocument::getModuleInfo()
2240 {
2241         return moduleNames_;
2242 }
2243
2244
2245 vector<GuiDocument::modInfoStruct> const GuiDocument::getSelectedModules()
2246 {
2247         vector<string> const & mods = params().getModules();
2248         vector<string>::const_iterator it =  mods.begin();
2249         vector<string>::const_iterator end = mods.end();
2250         vector<modInfoStruct> mInfo;
2251         for (; it != end; ++it) {
2252                 modInfoStruct m;
2253                 m.id = *it;
2254                 LyXModule * mod = moduleList[*it];
2255                 if (mod)
2256                         m.name = qt_(mod->getName());
2257                 else 
2258                         m.name = toqstr(*it) + toqstr(" (") + qt_("Not Found") + toqstr(")");
2259                 mInfo.push_back(m);
2260         }
2261         return mInfo;
2262 }
2263
2264
2265 DocumentClass const & GuiDocument::documentClass() const
2266 {
2267         return bp_.documentClass();
2268 }
2269
2270
2271 static void dispatch_bufferparams(Dialog const & dialog,
2272         BufferParams const & bp, FuncCode lfun)
2273 {
2274         ostringstream ss;
2275         ss << "\\begin_header\n";
2276         bp.writeFile(ss);
2277         ss << "\\end_header\n";
2278         dialog.dispatch(FuncRequest(lfun, ss.str()));
2279 }
2280
2281
2282 void GuiDocument::dispatchParams()
2283 {
2284         // This must come first so that a language change is correctly noticed
2285         setLanguage();
2286
2287         // Apply the BufferParams. Note that this will set the base class
2288         // and then update the buffer's layout.
2289         dispatch_bufferparams(*this, params(), LFUN_BUFFER_PARAMS_APPLY);
2290
2291         if (!params().master.empty()) {
2292                 FileName const master_file = support::makeAbsPath(params().master,
2293                            support::onlyPath(buffer().absFileName()));
2294                 if (isLyXFilename(master_file.absFilename())) {
2295                         Buffer * master = checkAndLoadLyXFile(master_file);
2296                         buffer().setParent(master);
2297                 }
2298         }
2299
2300         // Generate the colours requested by each new branch.
2301         BranchList & branchlist = params().branchlist();
2302         if (!branchlist.empty()) {
2303                 BranchList::const_iterator it = branchlist.begin();
2304                 BranchList::const_iterator const end = branchlist.end();
2305                 for (; it != end; ++it) {
2306                         docstring const & current_branch = it->getBranch();
2307                         Branch const * branch = branchlist.find(current_branch);
2308                         string const x11hexname = X11hexname(branch->getColor());
2309                         // display the new color
2310                         docstring const str = current_branch + ' ' + from_ascii(x11hexname);
2311                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
2312                 }
2313
2314                 // Open insets of selected branches, close deselected ones
2315                 dispatch(FuncRequest(LFUN_ALL_INSETS_TOGGLE,
2316                         "assign branch"));
2317         }
2318         // FIXME: If we used an LFUN, we would not need those two lines:
2319         bufferview()->processUpdateFlags(Update::Force | Update::FitCursor);
2320 }
2321
2322
2323 void GuiDocument::setLanguage() const
2324 {
2325         Language const * const newL = bp_.language;
2326         if (buffer().params().language == newL)
2327                 return;
2328
2329         string const & lang_name = newL->lang();
2330         dispatch(FuncRequest(LFUN_BUFFER_LANGUAGE, lang_name));
2331 }
2332
2333
2334 void GuiDocument::saveAsDefault() const
2335 {
2336         dispatch_bufferparams(*this, params(), LFUN_BUFFER_SAVE_AS_DEFAULT);
2337 }
2338
2339
2340 bool GuiDocument::isFontAvailable(string const & font) const
2341 {
2342         if (font == "default" || font == "cmr"
2343             || font == "cmss" || font == "cmtt")
2344                 // these are standard
2345                 return true;
2346         if (font == "lmodern" || font == "lmss" || font == "lmtt")
2347                 return LaTeXFeatures::isAvailable("lmodern");
2348         if (font == "times" || font == "palatino"
2349                  || font == "helvet" || font == "courier")
2350                 return LaTeXFeatures::isAvailable("psnfss");
2351         if (font == "cmbr" || font == "cmtl")
2352                 return LaTeXFeatures::isAvailable("cmbright");
2353         if (font == "utopia")
2354                 return LaTeXFeatures::isAvailable("utopia")
2355                         || LaTeXFeatures::isAvailable("fourier");
2356         if (font == "beraserif" || font == "berasans"
2357                 || font == "beramono")
2358                 return LaTeXFeatures::isAvailable("bera");
2359         return LaTeXFeatures::isAvailable(font);
2360 }
2361
2362
2363 bool GuiDocument::providesOSF(string const & font) const
2364 {
2365         if (font == "cmr")
2366                 return isFontAvailable("eco");
2367         if (font == "palatino")
2368                 return isFontAvailable("mathpazo");
2369         return false;
2370 }
2371
2372
2373 bool GuiDocument::providesSC(string const & font) const
2374 {
2375         if (font == "palatino")
2376                 return isFontAvailable("mathpazo");
2377         if (font == "utopia")
2378                 return isFontAvailable("fourier");
2379         return false;
2380 }
2381
2382
2383 bool GuiDocument::providesScale(string const & font) const
2384 {
2385         return font == "helvet" || font == "luximono"
2386                 || font == "berasans"  || font == "beramono";
2387 }
2388
2389
2390 void GuiDocument::loadModuleInfo()
2391 {
2392         moduleNames_.clear();
2393         LyXModuleList::const_iterator it  = moduleList.begin();
2394         LyXModuleList::const_iterator end = moduleList.end();
2395         for (; it != end; ++it) {
2396                 modInfoStruct m;
2397                 m.id = it->getID();
2398                 m.name = qt_(it->getName());
2399                 // this is supposed to give us the first sentence of the description
2400                 QString desc = qt_(it->getDescription());
2401                 int const pos = desc.indexOf(".");
2402                 if (pos > 0)
2403                         desc.truncate(pos + 1);
2404                 m.description = desc;
2405                 moduleNames_.push_back(m);
2406         }
2407 }
2408
2409
2410 Dialog * createGuiDocument(GuiView & lv) { return new GuiDocument(lv); }
2411
2412
2413 } // namespace frontend
2414 } // namespace lyx
2415
2416 #include "GuiDocument_moc.cpp"