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