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