]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiDocument.cpp
GuiDocument.cpp: add linebreaks to error messages
[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, _("Document Class"));
987         docPS->addPanel(fontModule, _("Fonts"));
988         docPS->addPanel(textLayoutModule, _("Text Layout"));
989         docPS->addPanel(pageLayoutModule, _("Page Layout"));
990         docPS->addPanel(marginsModule, _("Page Margins"));
991         docPS->addPanel(langModule, _("Language"));
992         docPS->addPanel(numberingModule, _("Numbering & TOC"));
993         docPS->addPanel(biblioModule, _("Bibliography"));
994         docPS->addPanel(pdfSupportModule, _("PDF Properties"));
995         docPS->addPanel(mathsModule, _("Math Options"));
996         docPS->addPanel(floatModule, _("Float Placement"));
997         docPS->addPanel(bulletsModule, _("Bullets"));
998         docPS->addPanel(branchesModule, _("Branches"));
999         docPS->addPanel(embeddedFilesModule, _("Embedded Files"));
1000         docPS->addPanel(preambleModule, _("LaTeX Preamble"));
1001         docPS->setCurrentPanel(_("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(_("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         for (size_t i = 0; i != tclass.layoutCount(); ++i) {
1414                 Layout const & lt = *tclass.layout(i);
1415                 int const toclevel = lt.toclevel;
1416                 if (toclevel != Layout::NOT_IN_TOC && lt.labeltype == LABEL_COUNTER) {
1417                         item = new QTreeWidgetItem(numberingModule->tocTW);
1418                         item->setText(0, toqstr(translateIfPossible(lt.name())));
1419                         item->setText(1, (toclevel <= depth) ? yes : no);
1420                         item->setText(2, (toclevel <= toc) ? yes : no);
1421                 }
1422         }
1423
1424         numberingModule->tocTW->setUpdatesEnabled(true);
1425         numberingModule->tocTW->update();
1426 }
1427
1428
1429 void GuiDocument::apply(BufferParams & params)
1430 {
1431         // preamble
1432         preambleModule->apply(params);
1433
1434         // biblio
1435         params.setCiteEngine(biblio::ENGINE_BASIC);
1436
1437         if (biblioModule->citeNatbibRB->isChecked()) {
1438                 bool const use_numerical_citations =
1439                         biblioModule->citeStyleCO->currentIndex();
1440                 if (use_numerical_citations)
1441                         params.setCiteEngine(biblio::ENGINE_NATBIB_NUMERICAL);
1442                 else
1443                         params.setCiteEngine(biblio::ENGINE_NATBIB_AUTHORYEAR);
1444
1445         } else if (biblioModule->citeJurabibRB->isChecked())
1446                 params.setCiteEngine(biblio::ENGINE_JURABIB);
1447
1448         params.use_bibtopic =
1449                 biblioModule->bibtopicCB->isChecked();
1450
1451         // language & quotes
1452         if (langModule->defaultencodingRB->isChecked()) {
1453                 params.inputenc = "auto";
1454         } else {
1455                 int i = langModule->encodingCO->currentIndex();
1456                 if (i == 0)
1457                         params.inputenc = "default";
1458                 else
1459                         params.inputenc =
1460                                 fromqstr(langModule->encodingCO->currentText());
1461         }
1462
1463         InsetQuotes::quote_language lga = InsetQuotes::EnglishQ;
1464         switch (langModule->quoteStyleCO->currentIndex()) {
1465         case 0:
1466                 lga = InsetQuotes::EnglishQ;
1467                 break;
1468         case 1:
1469                 lga = InsetQuotes::SwedishQ;
1470                 break;
1471         case 2:
1472                 lga = InsetQuotes::GermanQ;
1473                 break;
1474         case 3:
1475                 lga = InsetQuotes::PolishQ;
1476                 break;
1477         case 4:
1478                 lga = InsetQuotes::FrenchQ;
1479                 break;
1480         case 5:
1481                 lga = InsetQuotes::DanishQ;
1482                 break;
1483         }
1484         params.quotes_language = lga;
1485
1486         int const pos = langModule->languageCO->currentIndex();
1487         params.language = lyx::languages.getLanguage(lang_[pos]);
1488
1489         // numbering
1490         if (params.documentClass().hasTocLevels()) {
1491                 params.tocdepth = numberingModule->tocSL->value();
1492                 params.secnumdepth = numberingModule->depthSL->value();
1493         }
1494
1495         // bullets
1496         params.user_defined_bullet(0) = bulletsModule->getBullet(0);
1497         params.user_defined_bullet(1) = bulletsModule->getBullet(1);
1498         params.user_defined_bullet(2) = bulletsModule->getBullet(2);
1499         params.user_defined_bullet(3) = bulletsModule->getBullet(3);
1500
1501         // packages
1502         params.graphicsDriver =
1503                 tex_graphics[latexModule->psdriverCO->currentIndex()];
1504         
1505         // text layout
1506         int idx = latexModule->classCO->currentIndex();
1507         if (idx >= 0) {
1508                 string const classname = classes_model_.getIDString(idx);
1509                 params.setBaseClass(classname);
1510         }
1511
1512         // Modules
1513         params.clearLayoutModules();
1514         int const srows = modules_sel_model_.rowCount();
1515         vector<string> selModList;
1516         for (int i = 0; i < srows; ++i)
1517                 params.addLayoutModule(modules_sel_model_.getIDString(i));
1518
1519         if (mathsModule->amsautoCB->isChecked()) {
1520                 params.use_amsmath = BufferParams::package_auto;
1521         } else {
1522                 if (mathsModule->amsCB->isChecked())
1523                         params.use_amsmath = BufferParams::package_on;
1524                 else
1525                         params.use_amsmath = BufferParams::package_off;
1526         }
1527
1528         if (mathsModule->esintautoCB->isChecked())
1529                 params.use_esint = BufferParams::package_auto;
1530         else {
1531                 if (mathsModule->esintCB->isChecked())
1532                         params.use_esint = BufferParams::package_on;
1533                 else
1534                         params.use_esint = BufferParams::package_off;
1535         }
1536
1537         if (pageLayoutModule->pagestyleCO->currentIndex() == 0)
1538                 params.pagestyle = "default";
1539         else {
1540                 docstring style_gui =
1541                         qstring_to_ucs4(pageLayoutModule->pagestyleCO->currentText());
1542                 for (size_t i = 0; i < pagestyles.size(); ++i)
1543                         if (pagestyles[i].second == style_gui)
1544                                 params.pagestyle = pagestyles[i].first;
1545         }
1546
1547         switch (textLayoutModule->lspacingCO->currentIndex()) {
1548         case 0:
1549                 params.spacing().set(Spacing::Single);
1550                 break;
1551         case 1:
1552                 params.spacing().set(Spacing::Onehalf);
1553                 break;
1554         case 2:
1555                 params.spacing().set(Spacing::Double);
1556                 break;
1557         case 3:
1558                 params.spacing().set(Spacing::Other,
1559                         fromqstr(textLayoutModule->lspacingLE->text()));
1560                 break;
1561         }
1562
1563         if (textLayoutModule->twoColumnCB->isChecked())
1564                 params.columns = 2;
1565         else
1566                 params.columns = 1;
1567
1568         // text should have passed validation
1569         params.listings_params =
1570                 InsetListingsParams(fromqstr(textLayoutModule->listingsED->toPlainText())).params();
1571
1572         if (textLayoutModule->indentRB->isChecked())
1573                 params.paragraph_separation = BufferParams::PARSEP_INDENT;
1574         else
1575                 params.paragraph_separation = BufferParams::PARSEP_SKIP;
1576
1577         switch (textLayoutModule->skipCO->currentIndex()) {
1578         case 0:
1579                 params.setDefSkip(VSpace(VSpace::SMALLSKIP));
1580                 break;
1581         case 1:
1582                 params.setDefSkip(VSpace(VSpace::MEDSKIP));
1583                 break;
1584         case 2:
1585                 params.setDefSkip(VSpace(VSpace::BIGSKIP));
1586                 break;
1587         case 3:
1588         {
1589                 VSpace vs = VSpace(
1590                         widgetsToLength(textLayoutModule->skipLE,
1591                                 textLayoutModule->skipLengthCO)
1592                         );
1593                 params.setDefSkip(vs);
1594                 break;
1595         }
1596         default:
1597                 // DocumentDefskipCB assures that this never happens
1598                 // so Assert then !!!  - jbl
1599                 params.setDefSkip(VSpace(VSpace::MEDSKIP));
1600                 break;
1601         }
1602
1603         params.options =
1604                 fromqstr(latexModule->optionsLE->text());
1605
1606         params.float_placement = floatModule->get();
1607
1608         // fonts
1609         params.fontsRoman =
1610                 tex_fonts_roman[fontModule->fontsRomanCO->currentIndex()];
1611
1612         params.fontsSans =
1613                 tex_fonts_sans[fontModule->fontsSansCO->currentIndex()];
1614
1615         params.fontsTypewriter =
1616                 tex_fonts_monospaced[fontModule->fontsTypewriterCO->currentIndex()];
1617
1618         params.fontsSansScale = fontModule->scaleSansSB->value();
1619
1620         params.fontsTypewriterScale = fontModule->scaleTypewriterSB->value();
1621
1622         params.fontsSC = fontModule->fontScCB->isChecked();
1623
1624         params.fontsOSF = fontModule->fontOsfCB->isChecked();
1625
1626         params.fontsDefaultFamily = GuiDocument::fontfamilies[
1627                 fontModule->fontsDefaultCO->currentIndex()];
1628
1629         if (fontModule->fontsizeCO->currentIndex() == 0)
1630                 params.fontsize = "default";
1631         else
1632                 params.fontsize =
1633                         fromqstr(fontModule->fontsizeCO->currentText());
1634
1635         // paper
1636         params.papersize = PAPER_SIZE(
1637                 pageLayoutModule->papersizeCO->currentIndex());
1638
1639         // custom, A3, B3 and B4 paper sizes need geometry
1640         int psize = pageLayoutModule->papersizeCO->currentIndex();
1641         bool geom_papersize = (psize == 1 || psize == 5 || psize == 8 || psize == 9);
1642
1643         params.paperwidth = widgetsToLength(pageLayoutModule->paperwidthLE,
1644                 pageLayoutModule->paperwidthUnitCO);
1645
1646         params.paperheight = widgetsToLength(pageLayoutModule->paperheightLE,
1647                 pageLayoutModule->paperheightUnitCO);
1648
1649         if (pageLayoutModule->facingPagesCB->isChecked())
1650                 params.sides = TwoSides;
1651         else
1652                 params.sides = OneSide;
1653
1654         if (pageLayoutModule->landscapeRB->isChecked())
1655                 params.orientation = ORIENTATION_LANDSCAPE;
1656         else
1657                 params.orientation = ORIENTATION_PORTRAIT;
1658
1659         // margins
1660         params.use_geometry =
1661                 (!marginsModule->marginCB->isChecked()
1662                 || geom_papersize);
1663
1664         Ui::MarginsUi const * m(marginsModule);
1665
1666         params.leftmargin = widgetsToLength(m->innerLE, m->innerUnit);
1667         params.topmargin = widgetsToLength(m->topLE, m->topUnit);
1668         params.rightmargin = widgetsToLength(m->outerLE, m->outerUnit);
1669         params.bottommargin = widgetsToLength(m->bottomLE, m->bottomUnit);
1670         params.headheight = widgetsToLength(m->headheightLE, m->headheightUnit);
1671         params.headsep = widgetsToLength(m->headsepLE, m->headsepUnit);
1672         params.footskip = widgetsToLength(m->footskipLE, m->footskipUnit);
1673         params.columnsep = widgetsToLength(m->columnsepLE, m->columnsepUnit);
1674
1675         branchesModule->apply(params);
1676
1677         // PDF support
1678         PDFOptions & pdf = params.pdfoptions();
1679         pdf.use_hyperref = pdfSupportModule->use_hyperrefGB->isChecked();
1680         pdf.title = fromqstr(pdfSupportModule->titleLE->text());
1681         pdf.author = fromqstr(pdfSupportModule->authorLE->text());
1682         pdf.subject = fromqstr(pdfSupportModule->subjectLE->text());
1683         pdf.keywords = fromqstr(pdfSupportModule->keywordsLE->text());
1684
1685         pdf.bookmarks = pdfSupportModule->bookmarksGB->isChecked();
1686         pdf.bookmarksnumbered = pdfSupportModule->bookmarksnumberedCB->isChecked();
1687         pdf.bookmarksopen = pdfSupportModule->bookmarksopenGB->isChecked();
1688         pdf.bookmarksopenlevel = pdfSupportModule->bookmarksopenlevelSB->value();
1689
1690         pdf.breaklinks = pdfSupportModule->breaklinksCB->isChecked();
1691         pdf.pdfborder = pdfSupportModule->pdfborderCB->isChecked();
1692         pdf.pdfusetitle = pdfSupportModule->pdfusetitleCB->isChecked();
1693         pdf.colorlinks = pdfSupportModule->colorlinksCB->isChecked();
1694         pdf.backref = pdfSupportModule->backrefCB->isChecked();
1695         pdf.pagebackref = pdfSupportModule->pagebackrefCB->isChecked();
1696         if (pdfSupportModule->fullscreenCB->isChecked())
1697                 pdf.pagemode = pdf.pagemode_fullscreen;
1698         else
1699                 pdf.pagemode.clear();
1700         pdf.quoted_options = fromqstr(pdfSupportModule->optionsLE->text());
1701
1702         // Embedded files
1703         // FIXME
1704 }
1705
1706
1707 /** Return the position of val in the vector if found.
1708     If not found, return 0.
1709  */
1710 template<class A>
1711 static size_t findPos(vector<A> const & vec, A const & val)
1712 {
1713         typename vector<A>::const_iterator it =
1714                 find(vec.begin(), vec.end(), val);
1715         if (it == vec.end())
1716                 return 0;
1717         return distance(vec.begin(), it);
1718 }
1719
1720
1721 void GuiDocument::updateParams()
1722 {
1723         updateParams(bp_);
1724 }
1725
1726
1727 void GuiDocument::updateParams(BufferParams const & params)
1728 {
1729         // set the default unit
1730         Length::UNIT defaultUnit = Length::CM;
1731         switch (lyxrc.default_papersize) {
1732                 case PAPER_DEFAULT: break;
1733
1734                 case PAPER_USLETTER:
1735                 case PAPER_USLEGAL:
1736                 case PAPER_USEXECUTIVE:
1737                         defaultUnit = Length::IN;
1738                         break;
1739
1740                 case PAPER_A3:
1741                 case PAPER_A4:
1742                 case PAPER_A5:
1743                 case PAPER_B3:
1744                 case PAPER_B4:
1745                 case PAPER_B5:
1746                         defaultUnit = Length::CM;
1747                         break;
1748                 case PAPER_CUSTOM:
1749                         break;
1750         }
1751
1752         // preamble
1753         preambleModule->update(params, id());
1754
1755         // biblio
1756         biblioModule->citeDefaultRB->setChecked(
1757                 params.getEngine() == biblio::ENGINE_BASIC);
1758
1759         biblioModule->citeNatbibRB->setChecked(
1760                 params.getEngine() == biblio::ENGINE_NATBIB_NUMERICAL ||
1761                 params.getEngine() == biblio::ENGINE_NATBIB_AUTHORYEAR);
1762
1763         biblioModule->citeStyleCO->setCurrentIndex(
1764                 params.getEngine() == biblio::ENGINE_NATBIB_NUMERICAL);
1765
1766         biblioModule->citeJurabibRB->setChecked(
1767                 params.getEngine() == biblio::ENGINE_JURABIB);
1768
1769         biblioModule->bibtopicCB->setChecked(
1770                 params.use_bibtopic);
1771
1772         // language & quotes
1773         int const pos = int(findPos(lang_,
1774                                     params.language->lang()));
1775         langModule->languageCO->setCurrentIndex(pos);
1776
1777         langModule->quoteStyleCO->setCurrentIndex(
1778                 params.quotes_language);
1779
1780         bool default_enc = true;
1781         if (params.inputenc != "auto") {
1782                 default_enc = false;
1783                 if (params.inputenc == "default") {
1784                         langModule->encodingCO->setCurrentIndex(0);
1785                 } else {
1786                         int const i = langModule->encodingCO->findText(
1787                                         toqstr(params.inputenc));
1788                         if (i >= 0)
1789                                 langModule->encodingCO->setCurrentIndex(i);
1790                         else
1791                                 // unknown encoding. Set to default.
1792                                 default_enc = true;
1793                 }
1794         }
1795         langModule->defaultencodingRB->setChecked(default_enc);
1796         langModule->otherencodingRB->setChecked(!default_enc);
1797
1798         // numbering
1799         int const min_toclevel = documentClass().min_toclevel();
1800         int const max_toclevel = documentClass().max_toclevel();
1801         if (documentClass().hasTocLevels()) {
1802                 numberingModule->setEnabled(true);
1803                 numberingModule->depthSL->setMinimum(min_toclevel - 1);
1804                 numberingModule->depthSL->setMaximum(max_toclevel);
1805                 numberingModule->depthSL->setValue(params.secnumdepth);
1806                 numberingModule->tocSL->setMaximum(min_toclevel - 1);
1807                 numberingModule->tocSL->setMaximum(max_toclevel);
1808                 numberingModule->tocSL->setValue(params.tocdepth);
1809                 updateNumbering();
1810         } else {
1811                 numberingModule->setEnabled(false);
1812                 numberingModule->tocTW->clear();
1813         }
1814
1815         // bullets
1816         bulletsModule->setBullet(0, params.user_defined_bullet(0));
1817         bulletsModule->setBullet(1, params.user_defined_bullet(1));
1818         bulletsModule->setBullet(2, params.user_defined_bullet(2));
1819         bulletsModule->setBullet(3, params.user_defined_bullet(3));
1820         bulletsModule->init();
1821
1822         // packages
1823         int nitem = findToken(tex_graphics, params.graphicsDriver);
1824         if (nitem >= 0)
1825                 latexModule->psdriverCO->setCurrentIndex(nitem);
1826         updateModuleInfo();
1827         
1828         mathsModule->amsCB->setChecked(
1829                 params.use_amsmath == BufferParams::package_on);
1830         mathsModule->amsautoCB->setChecked(
1831                 params.use_amsmath == BufferParams::package_auto);
1832
1833         mathsModule->esintCB->setChecked(
1834                 params.use_esint == BufferParams::package_on);
1835         mathsModule->esintautoCB->setChecked(
1836                 params.use_esint == BufferParams::package_auto);
1837
1838         switch (params.spacing().getSpace()) {
1839                 case Spacing::Other: nitem = 3; break;
1840                 case Spacing::Double: nitem = 2; break;
1841                 case Spacing::Onehalf: nitem = 1; break;
1842                 case Spacing::Default: case Spacing::Single: nitem = 0; break;
1843         }
1844
1845         // text layout
1846         string const & layoutID = params.baseClassID();
1847         setLayoutComboByIDString(layoutID);
1848
1849         updatePagestyle(documentClass().opt_pagestyle(),
1850                                  params.pagestyle);
1851
1852         textLayoutModule->lspacingCO->setCurrentIndex(nitem);
1853         if (params.spacing().getSpace() == Spacing::Other) {
1854                 textLayoutModule->lspacingLE->setText(
1855                         toqstr(params.spacing().getValueAsString()));
1856         }
1857         setLSpacing(nitem);
1858
1859         if (params.paragraph_separation == BufferParams::PARSEP_INDENT)
1860                 textLayoutModule->indentRB->setChecked(true);
1861         else
1862                 textLayoutModule->skipRB->setChecked(true);
1863
1864         int skip = 0;
1865         switch (params.getDefSkip().kind()) {
1866         case VSpace::SMALLSKIP:
1867                 skip = 0;
1868                 break;
1869         case VSpace::MEDSKIP:
1870                 skip = 1;
1871                 break;
1872         case VSpace::BIGSKIP:
1873                 skip = 2;
1874                 break;
1875         case VSpace::LENGTH:
1876         {
1877                 skip = 3;
1878                 string const length = params.getDefSkip().asLyXCommand();
1879                 lengthToWidgets(textLayoutModule->skipLE,
1880                         textLayoutModule->skipLengthCO,
1881                         length, defaultUnit);
1882                 break;
1883         }
1884         default:
1885                 skip = 0;
1886                 break;
1887         }
1888         textLayoutModule->skipCO->setCurrentIndex(skip);
1889         setSkip(skip);
1890
1891         textLayoutModule->twoColumnCB->setChecked(
1892                 params.columns == 2);
1893
1894         // break listings_params to multiple lines
1895         string lstparams =
1896                 InsetListingsParams(params.listings_params).separatedParams();
1897         textLayoutModule->listingsED->setPlainText(toqstr(lstparams));
1898
1899         if (!params.options.empty()) {
1900                 latexModule->optionsLE->setText(
1901                         toqstr(params.options));
1902         } else {
1903                 latexModule->optionsLE->setText(QString());
1904         }
1905
1906         floatModule->set(params.float_placement);
1907
1908         // Fonts
1909         updateFontsize(documentClass().opt_fontsize(),
1910                         params.fontsize);
1911
1912         int n = findToken(tex_fonts_roman, params.fontsRoman);
1913         if (n >= 0) {
1914                 fontModule->fontsRomanCO->setCurrentIndex(n);
1915                 romanChanged(n);
1916         }
1917
1918         n = findToken(tex_fonts_sans, params.fontsSans);
1919         if (n >= 0)     {
1920                 fontModule->fontsSansCO->setCurrentIndex(n);
1921                 sansChanged(n);
1922         }
1923
1924         n = findToken(tex_fonts_monospaced, params.fontsTypewriter);
1925         if (n >= 0) {
1926                 fontModule->fontsTypewriterCO->setCurrentIndex(n);
1927                 ttChanged(n);
1928         }
1929
1930         fontModule->fontScCB->setChecked(params.fontsSC);
1931         fontModule->fontOsfCB->setChecked(params.fontsOSF);
1932         fontModule->scaleSansSB->setValue(params.fontsSansScale);
1933         fontModule->scaleTypewriterSB->setValue(params.fontsTypewriterScale);
1934         n = findToken(GuiDocument::fontfamilies, params.fontsDefaultFamily);
1935         if (n >= 0)
1936                 fontModule->fontsDefaultCO->setCurrentIndex(n);
1937
1938         // paper
1939         int const psize = params.papersize;
1940         pageLayoutModule->papersizeCO->setCurrentIndex(psize);
1941         setCustomPapersize(psize);
1942
1943         bool const landscape =
1944                 params.orientation == ORIENTATION_LANDSCAPE;
1945         pageLayoutModule->landscapeRB->setChecked(landscape);
1946         pageLayoutModule->portraitRB->setChecked(!landscape);
1947
1948         pageLayoutModule->facingPagesCB->setChecked(
1949                 params.sides == TwoSides);
1950
1951
1952         lengthToWidgets(pageLayoutModule->paperwidthLE,
1953                 pageLayoutModule->paperwidthUnitCO, params.paperwidth, defaultUnit);
1954
1955         lengthToWidgets(pageLayoutModule->paperheightLE,
1956                 pageLayoutModule->paperheightUnitCO, params.paperheight, defaultUnit);
1957
1958         // margins
1959         Ui::MarginsUi * m = marginsModule;
1960
1961         setMargins(!params.use_geometry);
1962
1963         lengthToWidgets(m->topLE, m->topUnit,
1964                 params.topmargin, defaultUnit);
1965
1966         lengthToWidgets(m->bottomLE, m->bottomUnit,
1967                 params.bottommargin, defaultUnit);
1968
1969         lengthToWidgets(m->innerLE, m->innerUnit,
1970                 params.leftmargin, defaultUnit);
1971
1972         lengthToWidgets(m->outerLE, m->outerUnit,
1973                 params.rightmargin, defaultUnit);
1974
1975         lengthToWidgets(m->headheightLE, m->headheightUnit,
1976                 params.headheight, defaultUnit);
1977
1978         lengthToWidgets(m->headsepLE, m->headsepUnit,
1979                 params.headsep, defaultUnit);
1980
1981         lengthToWidgets(m->footskipLE, m->footskipUnit,
1982                 params.footskip, defaultUnit);
1983
1984         lengthToWidgets(m->columnsepLE, m->columnsepUnit,
1985                 params.columnsep, defaultUnit);
1986
1987         branchesModule->update(params);
1988
1989         // PDF support
1990         PDFOptions const & pdf = params.pdfoptions();
1991         pdfSupportModule->use_hyperrefGB->setChecked(pdf.use_hyperref);
1992         pdfSupportModule->titleLE->setText(toqstr(pdf.title));
1993         pdfSupportModule->authorLE->setText(toqstr(pdf.author));
1994         pdfSupportModule->subjectLE->setText(toqstr(pdf.subject));
1995         pdfSupportModule->keywordsLE->setText(toqstr(pdf.keywords));
1996
1997         pdfSupportModule->bookmarksGB->setChecked(pdf.bookmarks);
1998         pdfSupportModule->bookmarksnumberedCB->setChecked(pdf.bookmarksnumbered);
1999         pdfSupportModule->bookmarksopenGB->setChecked(pdf.bookmarksopen);
2000
2001         pdfSupportModule->bookmarksopenlevelSB->setValue(pdf.bookmarksopenlevel);
2002
2003         pdfSupportModule->breaklinksCB->setChecked(pdf.breaklinks);
2004         pdfSupportModule->pdfborderCB->setChecked(pdf.pdfborder);
2005         pdfSupportModule->pdfusetitleCB->setChecked(pdf.pdfusetitle);
2006         pdfSupportModule->colorlinksCB->setChecked(pdf.colorlinks);
2007         pdfSupportModule->backrefCB->setChecked(pdf.backref);
2008         pdfSupportModule->pagebackrefCB->setChecked(pdf.pagebackref);
2009         pdfSupportModule->fullscreenCB->setChecked
2010                 (pdf.pagemode == pdf.pagemode_fullscreen);
2011
2012         pdfSupportModule->optionsLE->setText(
2013                 toqstr(pdf.quoted_options));
2014
2015         // embedded files
2016         updateEmbeddedFileList();
2017 }
2018
2019
2020 void GuiDocument::applyView()
2021 {
2022         apply(params());
2023 }
2024
2025
2026 void GuiDocument::saveDocDefault()
2027 {
2028         // we have to apply the params first
2029         applyView();
2030         saveAsDefault();
2031 }
2032
2033
2034 void GuiDocument::updateAvailableModules() 
2035 {
2036         modules_av_model_.clear();
2037         vector<modInfoStruct> const modInfoList = getModuleInfo();
2038         int const mSize = modInfoList.size();
2039         for (int i = 0; i < mSize; ++i) {
2040                 modInfoStruct const & modInfo = modInfoList[i];
2041                 modules_av_model_.insertRow(i, qt_(modInfo.name), modInfo.id);
2042         }
2043 }
2044
2045
2046 void GuiDocument::updateSelectedModules() 
2047 {
2048         //and selected ones, too
2049         modules_sel_model_.clear();
2050         vector<modInfoStruct> const selModList = getSelectedModules();
2051         int const sSize = selModList.size();
2052         for (int i = 0; i < sSize; ++i) {
2053                 modInfoStruct const & modInfo = selModList[i];
2054                 modules_sel_model_.insertRow(i, qt_(modInfo.name), modInfo.id);
2055         }
2056 }
2057
2058
2059 void GuiDocument::updateContents()
2060 {
2061         if (id() == current_id_)
2062                 return;
2063
2064         updateAvailableModules();
2065         updateSelectedModules();
2066         
2067         //FIXME It'd be nice to make sure here that the selected
2068         //modules are consistent: That required modules are actually
2069         //selected, and that we don't have conflicts. If so, we could
2070         //at least pop up a warning.
2071         updateParams(bp_);
2072         current_id_ = id();
2073 }
2074
2075
2076 void GuiDocument::forceUpdate()
2077 {
2078         // reset to force dialog update
2079         current_id_ = 0;
2080         updateContents();
2081 }
2082
2083
2084 void GuiDocument::useClassDefaults()
2085 {
2086         if (applyPB->isEnabled()) {
2087                 int const ret = Alert::prompt(_("Unapplied changes"),
2088                                 _("Some changes in the dialog were not yet applied."
2089                                   "If you do not apply now, they will be lost after this action."),
2090                                 1, 1, _("&Apply"), _("&Dismiss"));
2091                 if (ret == 0)
2092                         applyView();
2093         }
2094
2095         int idx = latexModule->classCO->currentIndex();
2096         string const classname = classes_model_.getIDString(idx);
2097         if (!bp_.setBaseClass(classname)) {
2098                 Alert::error(_("Error"), _("Unable to set document class."));
2099                 return;
2100         }
2101         bp_.useClassDefaults();
2102         forceUpdate();
2103 }
2104
2105
2106 void GuiDocument::setLayoutComboByIDString(std::string const & idString)
2107 {
2108         int idx = classes_model_.findIDString(idString);
2109         if (idx < 0)
2110                 Alert::warning(_("Can't set layout!"), 
2111                         bformat(_("Unable to set layout for ID: %1$s"), from_utf8(idString)));
2112         else 
2113                 latexModule->classCO->setCurrentIndex(idx);
2114 }
2115
2116
2117 bool GuiDocument::isValid()
2118 {
2119         return (validate_listings_params().empty() &&
2120                 (textLayoutModule->skipCO->currentIndex() != 3 ||
2121                  !textLayoutModule->skipLE->text().isEmpty()));
2122 }
2123
2124
2125 char const * const GuiDocument::fontfamilies[5] = {
2126         "default", "rmdefault", "sfdefault", "ttdefault", ""
2127 };
2128
2129
2130 char const * GuiDocument::fontfamilies_gui[5] = {
2131         N_("Default"), N_("Roman"), N_("Sans Serif"), N_("Typewriter"), ""
2132 };
2133
2134
2135 bool GuiDocument::initialiseParams(string const &)
2136 {
2137         bp_ = buffer().params();
2138         loadModuleInfo();
2139         return true;
2140 }
2141
2142
2143 void GuiDocument::clearParams()
2144 {
2145         bp_ = BufferParams();
2146 }
2147
2148
2149 BufferId GuiDocument::id() const
2150 {
2151         return &buffer();
2152 }
2153
2154
2155 vector<GuiDocument::modInfoStruct> const & GuiDocument::getModuleInfo()
2156 {
2157         return moduleNames_;
2158 }
2159
2160
2161 vector<GuiDocument::modInfoStruct> const GuiDocument::getSelectedModules()
2162 {
2163         vector<string> const & mods = params().getModules();
2164         vector<string>::const_iterator it =  mods.begin();
2165         vector<string>::const_iterator end = mods.end();
2166         vector<modInfoStruct> mInfo;
2167         for (; it != end; ++it) {
2168                 modInfoStruct m;
2169                 m.id = *it;
2170                 LyXModule * mod = moduleList[*it];
2171                 if (mod)
2172                         m.name = mod->getName();
2173                 else 
2174                         m.name = *it + " (Not Found)";
2175                 mInfo.push_back(m);
2176         }
2177         return mInfo;
2178 }
2179
2180
2181 DocumentClass const & GuiDocument::documentClass() const
2182 {
2183         return bp_.documentClass();
2184 }
2185
2186
2187 static void dispatch_bufferparams(Dialog const & dialog,
2188         BufferParams const & bp, kb_action lfun)
2189 {
2190         ostringstream ss;
2191         ss << "\\begin_header\n";
2192         bp.writeFile(ss);
2193         ss << "\\end_header\n";
2194         dialog.dispatch(FuncRequest(lfun, ss.str()));
2195 }
2196
2197
2198 void GuiDocument::dispatchParams()
2199 {
2200         // This must come first so that a language change is correctly noticed
2201         setLanguage();
2202
2203         // Apply the BufferParams. Note that this will set the base class
2204         // and then update the buffer's layout.
2205         dispatch_bufferparams(*this, params(), LFUN_BUFFER_PARAMS_APPLY);
2206
2207         // Generate the colours requested by each new branch.
2208         BranchList & branchlist = params().branchlist();
2209         if (!branchlist.empty()) {
2210                 BranchList::const_iterator it = branchlist.begin();
2211                 BranchList::const_iterator const end = branchlist.end();
2212                 for (; it != end; ++it) {
2213                         docstring const & current_branch = it->getBranch();
2214                         Branch const * branch = branchlist.find(current_branch);
2215                         string const x11hexname = X11hexname(branch->getColor());
2216                         // display the new color
2217                         docstring const str = current_branch + ' ' + from_ascii(x11hexname);
2218                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
2219                 }
2220
2221                 // Open insets of selected branches, close deselected ones
2222                 dispatch(FuncRequest(LFUN_ALL_INSETS_TOGGLE,
2223                         "assign branch"));
2224         }
2225         // FIXME: If we used an LFUN, we would not need those two lines:
2226         bufferview()->processUpdateFlags(Update::Force | Update::FitCursor);
2227 }
2228
2229
2230 void GuiDocument::setLanguage() const
2231 {
2232         Language const * const newL = bp_.language;
2233         if (buffer().params().language == newL)
2234                 return;
2235
2236         string const & lang_name = newL->lang();
2237         dispatch(FuncRequest(LFUN_BUFFER_LANGUAGE, lang_name));
2238 }
2239
2240
2241 void GuiDocument::saveAsDefault() const
2242 {
2243         dispatch_bufferparams(*this, params(), LFUN_BUFFER_SAVE_AS_DEFAULT);
2244 }
2245
2246
2247 bool GuiDocument::isFontAvailable(string const & font) const
2248 {
2249         if (font == "default" || font == "cmr"
2250             || font == "cmss" || font == "cmtt")
2251                 // these are standard
2252                 return true;
2253         if (font == "lmodern" || font == "lmss" || font == "lmtt")
2254                 return LaTeXFeatures::isAvailable("lmodern");
2255         if (font == "times" || font == "palatino"
2256                  || font == "helvet" || font == "courier")
2257                 return LaTeXFeatures::isAvailable("psnfss");
2258         if (font == "cmbr" || font == "cmtl")
2259                 return LaTeXFeatures::isAvailable("cmbright");
2260         if (font == "utopia")
2261                 return LaTeXFeatures::isAvailable("utopia")
2262                         || LaTeXFeatures::isAvailable("fourier");
2263         if (font == "beraserif" || font == "berasans"
2264                 || font == "beramono")
2265                 return LaTeXFeatures::isAvailable("bera");
2266         return LaTeXFeatures::isAvailable(font);
2267 }
2268
2269
2270 bool GuiDocument::providesOSF(string const & font) const
2271 {
2272         if (font == "cmr")
2273                 return isFontAvailable("eco");
2274         if (font == "palatino")
2275                 return isFontAvailable("mathpazo");
2276         return false;
2277 }
2278
2279
2280 bool GuiDocument::providesSC(string const & font) const
2281 {
2282         if (font == "palatino")
2283                 return isFontAvailable("mathpazo");
2284         if (font == "utopia")
2285                 return isFontAvailable("fourier");
2286         return false;
2287 }
2288
2289
2290 bool GuiDocument::providesScale(string const & font) const
2291 {
2292         return font == "helvet" || font == "luximono"
2293                 || font == "berasans"  || font == "beramono";
2294 }
2295
2296
2297 void GuiDocument::loadModuleInfo()
2298 {
2299         moduleNames_.clear();
2300         LyXModuleList::const_iterator it  = moduleList.begin();
2301         LyXModuleList::const_iterator end = moduleList.end();
2302         for (; it != end; ++it) {
2303                 modInfoStruct m;
2304                 m.id = it->getID();
2305                 m.name = it->getName();
2306                 moduleNames_.push_back(m);
2307         }
2308 }
2309
2310
2311 Dialog * createGuiDocument(GuiView & lv) { return new GuiDocument(lv); }
2312
2313
2314 } // namespace frontend
2315 } // namespace lyx
2316
2317 #include "GuiDocument_moc.cpp"