]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiDocument.cpp
BaseClassList --> LayoutFileList
[lyx.git] / src / frontends / qt4 / GuiDocument.cpp
1 /**
2  * \file GuiDocument.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Edwin Leuven
7  * \author Richard Heck (modules)
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "GuiDocument.h"
15
16 #include "LayoutFile.h"
17 #include "BranchList.h"
18 #include "buffer_funcs.h"
19 #include "Buffer.h"
20 #include "BufferParams.h"
21 #include "BufferView.h"
22 #include "Color.h"
23 #include "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 = LayoutFileList::get()[lhs];
156                 LayoutFile const & tc2 = LayoutFileList::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         LayoutFileList const & bcl = LayoutFileList::get();
906         vector<LayoutFileIndex> classList = bcl.classList();
907         sort(classList.begin(), classList.end(), less_textclass_avail_desc());
908
909         vector<LayoutFileIndex>::const_iterator cit  = classList.begin();
910         vector<LayoutFileIndex>::const_iterator cen = classList.end();
911         for (int i = 0; cit != cen; ++cit, ++i) {
912                 LayoutFile const & tc = bcl[*cit];
913                 docstring item = (tc.isTeXClassAvailable()) ?
914                         from_utf8(tc.description()) :
915                         bformat(_("Unavailable: %1$s"), from_utf8(tc.description()));
916                 classes_model_.insertRow(i, toqstr(item), *cit);
917         }
918
919         // branches
920         branchesModule = new GuiBranches;
921         connect(branchesModule, SIGNAL(changed()),
922                 this, SLOT(change_adaptor()));
923
924         // preamble
925         preambleModule = new PreambleModule;
926         connect(preambleModule, SIGNAL(changed()),
927                 this, SLOT(change_adaptor()));
928
929         // bullets
930         bulletsModule = new BulletsModule;
931         connect(bulletsModule, SIGNAL(changed()),
932                 this, SLOT(change_adaptor()));
933
934         // embedded files
935         embeddedFilesModule = new UiWidget<Ui::EmbeddedFilesUi>;
936         connect(embeddedFilesModule->bundleCB, SIGNAL(toggled(bool)),
937                 this, SLOT(change_adaptor()));
938         connect(embeddedFilesModule->addPB, SIGNAL(clicked()),
939                 this, SLOT(change_adaptor()));
940         connect(embeddedFilesModule->removePB, SIGNAL(clicked()),
941                 this, SLOT(change_adaptor()));
942
943         // PDF support
944         pdfSupportModule = new UiWidget<Ui::PDFSupportUi>;
945
946         connect(pdfSupportModule->use_hyperrefGB, SIGNAL(toggled(bool)),
947                 this, SLOT(change_adaptor()));
948         connect(pdfSupportModule->titleLE, SIGNAL(textChanged(const QString &)),
949                 this, SLOT(change_adaptor()));
950         connect(pdfSupportModule->authorLE, SIGNAL(textChanged(const QString &)),
951                 this, SLOT(change_adaptor()));
952         connect(pdfSupportModule->subjectLE, SIGNAL(textChanged(const QString &)),
953                 this, SLOT(change_adaptor()));
954         connect(pdfSupportModule->keywordsLE, SIGNAL(textChanged(const QString &)),
955                 this, SLOT(change_adaptor()));
956         connect(pdfSupportModule->bookmarksGB, SIGNAL(toggled(bool)),
957                 this, SLOT(change_adaptor()));
958         connect(pdfSupportModule->bookmarksnumberedCB, SIGNAL(toggled(bool)),
959                 this, SLOT(change_adaptor()));
960         connect(pdfSupportModule->bookmarksopenGB, SIGNAL(toggled(bool)),
961                 this, SLOT(change_adaptor()));
962         connect(pdfSupportModule->bookmarksopenlevelSB, SIGNAL(valueChanged(int)),
963                 this, SLOT(change_adaptor()));
964         connect(pdfSupportModule->breaklinksCB, SIGNAL(toggled(bool)),
965                 this, SLOT(change_adaptor()));
966         connect(pdfSupportModule->pdfborderCB, SIGNAL(toggled(bool)),
967                 this, SLOT(change_adaptor()));
968         connect(pdfSupportModule->colorlinksCB, SIGNAL(toggled(bool)),
969                 this, SLOT(change_adaptor()));
970         connect(pdfSupportModule->backrefCB, SIGNAL(toggled(bool)),
971                 this, SLOT(change_adaptor()));
972         connect(pdfSupportModule->pdfusetitleCB, SIGNAL(toggled(bool)),
973                 this, SLOT(change_adaptor()));
974         connect(pdfSupportModule->pagebackrefCB, SIGNAL(toggled(bool)),
975                 this, SLOT(change_adaptor()));
976         connect(pdfSupportModule->fullscreenCB, SIGNAL(toggled(bool)),
977                 this, SLOT(change_adaptor()));
978         connect(pdfSupportModule->optionsLE, SIGNAL(textChanged(const QString &)),
979                 this, SLOT(change_adaptor()));
980
981         // float
982         floatModule = new FloatPlacement;
983         connect(floatModule, SIGNAL(changed()),
984                 this, SLOT(change_adaptor()));
985
986         docPS->addPanel(latexModule, qt_("Document Class"));
987         docPS->addPanel(fontModule, qt_("Fonts"));
988         docPS->addPanel(textLayoutModule, qt_("Text Layout"));
989         docPS->addPanel(pageLayoutModule, qt_("Page Layout"));
990         docPS->addPanel(marginsModule, qt_("Page Margins"));
991         docPS->addPanel(langModule, qt_("Language"));
992         docPS->addPanel(numberingModule, qt_("Numbering & TOC"));
993         docPS->addPanel(biblioModule, qt_("Bibliography"));
994         docPS->addPanel(pdfSupportModule, qt_("PDF Properties"));
995         docPS->addPanel(mathsModule, qt_("Math Options"));
996         docPS->addPanel(floatModule, qt_("Float Placement"));
997         docPS->addPanel(bulletsModule, qt_("Bullets"));
998         docPS->addPanel(branchesModule, qt_("Branches"));
999         docPS->addPanel(embeddedFilesModule, qt_("Embedded Files"));
1000         docPS->addPanel(preambleModule, qt_("LaTeX Preamble"));
1001         docPS->setCurrentPanel(qt_("Document Class"));
1002 // FIXME: hack to work around resizing bug in Qt >= 4.2
1003 // bug verified with Qt 4.2.{0-3} (JSpitzm)
1004 #if QT_VERSION >= 0x040200
1005         docPS->updateGeometry();
1006 #endif
1007 }
1008
1009
1010 void GuiDocument::showPreamble()
1011 {
1012         docPS->setCurrentPanel(qt_("LaTeX Preamble"));
1013 }
1014
1015
1016 void GuiDocument::saveDefaultClicked()
1017 {
1018         saveDocDefault();
1019 }
1020
1021
1022 void GuiDocument::useDefaultsClicked()
1023 {
1024         useClassDefaults();
1025 }
1026
1027
1028 void GuiDocument::change_adaptor()
1029 {
1030         changed();
1031 }
1032
1033
1034 docstring GuiDocument::validate_listings_params()
1035 {
1036         // use a cache here to avoid repeated validation
1037         // of the same parameters
1038         static string param_cache = string();
1039         static docstring msg_cache = docstring();
1040         
1041         if (textLayoutModule->bypassCB->isChecked())
1042                 return docstring();
1043
1044         string params = fromqstr(textLayoutModule->listingsED->toPlainText());
1045         if (params != param_cache) {
1046                 param_cache = params;
1047                 msg_cache = InsetListingsParams(params).validate();
1048         }
1049         return msg_cache;
1050 }
1051
1052
1053 void GuiDocument::set_listings_msg()
1054 {
1055         static bool isOK = true;
1056         docstring msg = validate_listings_params();
1057         if (msg.empty()) {
1058                 if (isOK)
1059                         return;
1060                 isOK = true;
1061                 // listingsTB->setTextColor("black");
1062                 textLayoutModule->listingsTB->setPlainText(
1063                         qt_("Input listings parameters on the right. Enter ? for a list of parameters."));
1064         } else {
1065                 isOK = false;
1066                 // listingsTB->setTextColor("red");
1067                 textLayoutModule->listingsTB->setPlainText(toqstr(msg));
1068         }
1069 }
1070
1071
1072 void GuiDocument::setLSpacing(int item)
1073 {
1074         textLayoutModule->lspacingLE->setEnabled(item == 3);
1075 }
1076
1077
1078 void GuiDocument::setSkip(int item)
1079 {
1080         bool const enable = (item == 3);
1081         textLayoutModule->skipLE->setEnabled(enable);
1082         textLayoutModule->skipLengthCO->setEnabled(enable);
1083 }
1084
1085
1086 void GuiDocument::enableSkip(bool skip)
1087 {
1088         textLayoutModule->skipCO->setEnabled(skip);
1089         textLayoutModule->skipLE->setEnabled(skip);
1090         textLayoutModule->skipLengthCO->setEnabled(skip);
1091         if (skip)
1092                 setSkip(textLayoutModule->skipCO->currentIndex());
1093 }
1094
1095 void GuiDocument::portraitChanged()
1096 {
1097         setMargins(pageLayoutModule->papersizeCO->currentIndex());
1098 }
1099
1100 void GuiDocument::setMargins(bool custom)
1101 {
1102         marginsModule->marginCB->setChecked(custom);
1103         setCustomMargins(custom);
1104 }
1105
1106
1107 void GuiDocument::setCustomPapersize(int papersize)
1108 {
1109         bool const custom = (papersize == 1);
1110
1111         pageLayoutModule->paperwidthL->setEnabled(custom);
1112         pageLayoutModule->paperwidthLE->setEnabled(custom);
1113         pageLayoutModule->paperwidthUnitCO->setEnabled(custom);
1114         pageLayoutModule->paperheightL->setEnabled(custom);
1115         pageLayoutModule->paperheightLE->setEnabled(custom);
1116         pageLayoutModule->paperheightLE->setFocus();
1117         pageLayoutModule->paperheightUnitCO->setEnabled(custom);
1118 }
1119
1120
1121 void GuiDocument::setColSep()
1122 {
1123         setCustomMargins(marginsModule->marginCB->checkState() == Qt::Checked);
1124 }
1125
1126
1127 void GuiDocument::setCustomMargins(bool custom)
1128 {
1129         marginsModule->topL->setEnabled(!custom);
1130         marginsModule->topLE->setEnabled(!custom);
1131         marginsModule->topUnit->setEnabled(!custom);
1132
1133         marginsModule->bottomL->setEnabled(!custom);
1134         marginsModule->bottomLE->setEnabled(!custom);
1135         marginsModule->bottomUnit->setEnabled(!custom);
1136
1137         marginsModule->innerL->setEnabled(!custom);
1138         marginsModule->innerLE->setEnabled(!custom);
1139         marginsModule->innerUnit->setEnabled(!custom);
1140
1141         marginsModule->outerL->setEnabled(!custom);
1142         marginsModule->outerLE->setEnabled(!custom);
1143         marginsModule->outerUnit->setEnabled(!custom);
1144
1145         marginsModule->headheightL->setEnabled(!custom);
1146         marginsModule->headheightLE->setEnabled(!custom);
1147         marginsModule->headheightUnit->setEnabled(!custom);
1148
1149         marginsModule->headsepL->setEnabled(!custom);
1150         marginsModule->headsepLE->setEnabled(!custom);
1151         marginsModule->headsepUnit->setEnabled(!custom);
1152
1153         marginsModule->footskipL->setEnabled(!custom);
1154         marginsModule->footskipLE->setEnabled(!custom);
1155         marginsModule->footskipUnit->setEnabled(!custom);
1156
1157         bool const enableColSep = !custom && 
1158                         textLayoutModule->twoColumnCB->checkState() == Qt::Checked;
1159         marginsModule->columnsepL->setEnabled(enableColSep);
1160         marginsModule->columnsepLE->setEnabled(enableColSep);
1161         marginsModule->columnsepUnit->setEnabled(enableColSep);
1162 }
1163
1164
1165 void GuiDocument::updateFontsize(string const & items, string const & sel)
1166 {
1167         fontModule->fontsizeCO->clear();
1168         fontModule->fontsizeCO->addItem(qt_("Default"));
1169
1170         for (int n = 0; !token(items,'|',n).empty(); ++n)
1171                 fontModule->fontsizeCO->
1172                         addItem(toqstr(token(items,'|',n)));
1173
1174         for (int n = 0; n < fontModule->fontsizeCO->count(); ++n) {
1175                 if (fromqstr(fontModule->fontsizeCO->itemText(n)) == sel) {
1176                         fontModule->fontsizeCO->setCurrentIndex(n);
1177                         break;
1178                 }
1179         }
1180 }
1181
1182
1183 void GuiDocument::romanChanged(int item)
1184 {
1185         string const font = tex_fonts_roman[item];
1186         fontModule->fontScCB->setEnabled(providesSC(font));
1187         fontModule->fontOsfCB->setEnabled(providesOSF(font));
1188 }
1189
1190
1191 void GuiDocument::sansChanged(int item)
1192 {
1193         string const font = tex_fonts_sans[item];
1194         bool scaleable = providesScale(font);
1195         fontModule->scaleSansSB->setEnabled(scaleable);
1196         fontModule->scaleSansLA->setEnabled(scaleable);
1197 }
1198
1199
1200 void GuiDocument::ttChanged(int item)
1201 {
1202         string const font = tex_fonts_monospaced[item];
1203         bool scaleable = providesScale(font);
1204         fontModule->scaleTypewriterSB->setEnabled(scaleable);
1205         fontModule->scaleTypewriterLA->setEnabled(scaleable);
1206 }
1207
1208
1209 void GuiDocument::updatePagestyle(string const & items, string const & sel)
1210 {
1211         pagestyles.clear();
1212         pageLayoutModule->pagestyleCO->clear();
1213         pageLayoutModule->pagestyleCO->addItem(qt_("Default"));
1214
1215         for (int n = 0; !token(items,'|',n).empty(); ++n) {
1216                 string style = token(items, '|', n);
1217                 docstring style_gui = _(style);
1218                 pagestyles.push_back(pair<string, docstring>(style, style_gui));
1219                 pageLayoutModule->pagestyleCO->addItem(toqstr(style_gui));
1220         }
1221
1222         if (sel == "default") {
1223                 pageLayoutModule->pagestyleCO->setCurrentIndex(0);
1224                 return;
1225         }
1226
1227         int nn = 0;
1228
1229         for (size_t i = 0; i < pagestyles.size(); ++i)
1230                 if (pagestyles[i].first == sel)
1231                         nn = pageLayoutModule->pagestyleCO->findText(
1232                                         toqstr(pagestyles[i].second));
1233
1234         if (nn > 0)
1235                 pageLayoutModule->pagestyleCO->setCurrentIndex(nn);
1236 }
1237
1238
1239 void GuiDocument::classChanged()
1240 {
1241         int idx = latexModule->classCO->currentIndex();
1242         if (idx < 0) 
1243                 return;
1244         string const classname = classes_model_.getIDString(idx);
1245         // check if this is a local layout file
1246         if (prefixIs(classname, LayoutFileList::localPrefix)) {
1247                 int const ret = Alert::prompt(_("Local layout file"),
1248                                 _("The layout file you have selected is a local layout\n"
1249                                   "file, not one in the system or user directory. Your\n"
1250                                   "document may not work with this layout if you do not\n"
1251                                   "keep the layout file in the same directory."),
1252                                   1, 1, _("&Set Layout"), _("&Cancel"));
1253                 if (ret == 1) {
1254                         // try to reset the layout combo
1255                         setLayoutComboByIDString(bp_.baseClassID());
1256                         return;
1257                 }
1258         }
1259         if (!bp_.setBaseClass(classname)) {
1260                 Alert::error(_("Error"), _("Unable to set document class."));
1261                 return;
1262         }
1263         if (lyxrc.auto_reset_options) {
1264                 if (applyPB->isEnabled()) {
1265                         int const ret = Alert::prompt(_("Unapplied changes"),
1266                                         _("Some changes in the dialog were not yet applied.\n"
1267                                         "If you do not apply now, they will be lost after this action."),
1268                                         1, 1, _("&Apply"), _("&Dismiss"));
1269                         if (ret == 0)
1270                                 applyView();
1271                 }
1272                 bp_.useClassDefaults();
1273                 forceUpdate();
1274         }
1275 }
1276
1277
1278 namespace {
1279         // This is an insanely complicated attempt to make this sort of thing
1280         // work with RTL languages.
1281         docstring formatStrVec(vector<string> const & v, docstring const & s) 
1282         {
1283                 //this mess formats the list as "v[0], v[1], ..., [s] v[n]"
1284                 int const vSize = v.size();
1285                 if (v.size() == 0)
1286                         return docstring();
1287                 else if (v.size() == 1) 
1288                         return from_ascii(v[0]);
1289                 else if (v.size() == 2) {
1290                         docstring retval = _("%1$s and %2$s");
1291                         retval = subst(retval, _("and"), s);
1292                         return bformat(retval, from_ascii(v[0]), from_ascii(v[1]));
1293                 }
1294                 //The idea here is to format all but the last two items...
1295                 docstring t2 = _("%1$s, %2$s");
1296                 docstring retval = from_ascii(v[0]);
1297                 for (int i = 1; i < vSize - 2; ++i)
1298                         retval = bformat(t2, retval, from_ascii(v[i])); 
1299                 //...and then to  plug them, and the last two, into this schema
1300                 docstring t = _("%1$s, %2$s, and %3$s");
1301                 t = subst(t, _("and"), s);
1302                 return bformat(t, retval, from_ascii(v[vSize - 2]), from_ascii(v[vSize - 1]));
1303         }
1304         
1305         vector<string> idsToNames(vector<string> const & idList)
1306         {
1307                 vector<string> retval;
1308                 vector<string>::const_iterator it  = idList.begin();
1309                 vector<string>::const_iterator end = idList.end();
1310                 for (; it != end; ++it) {
1311                         LyXModule const * const mod = moduleList[*it];
1312                         if (!mod)
1313                                 retval.push_back(*it + " (Unavailable)");
1314                         else
1315                                 retval.push_back(mod->getName());
1316                 }
1317                 return retval;
1318         }
1319 }
1320
1321
1322 void GuiDocument::updateModuleInfo()
1323 {
1324         selectionManager->update();
1325         
1326         //Module description
1327         bool const focusOnSelected = selectionManager->selectedFocused();
1328         QListView const * const lv = 
1329                         focusOnSelected ? latexModule->selectedLV : latexModule->availableLV;
1330         if (lv->selectionModel()->selectedIndexes().isEmpty()) {
1331                 latexModule->infoML->document()->clear();
1332                 return;
1333         }
1334         QModelIndex const & idx = lv->selectionModel()->currentIndex();
1335         GuiIdListModel const & idModel = 
1336                         focusOnSelected  ? modules_sel_model_ : modules_av_model_;
1337         string const modName = idModel.getIDString(idx.row());
1338         docstring desc = getModuleDescription(modName);
1339
1340         vector<string> pkgList = getPackageList(modName);
1341         docstring pkgdesc = formatStrVec(pkgList, _("and"));
1342         if (!pkgdesc.empty()) {
1343                 if (!desc.empty())
1344                         desc += "\n";
1345                 desc += bformat(_("Package(s) required: %1$s."), pkgdesc);
1346         }
1347
1348         pkgList = getRequiredList(modName);
1349         if (!pkgList.empty()) {
1350                 vector<string> const reqDescs = idsToNames(pkgList);
1351                 pkgdesc = formatStrVec(reqDescs, _("or"));
1352                 if (!desc.empty())
1353                         desc += "\n";
1354                 desc += bformat(_("Module required: %1$s."), pkgdesc);
1355         }
1356
1357         pkgList = getExcludedList(modName);
1358         if (!pkgList.empty()) {
1359                 vector<string> const reqDescs = idsToNames(pkgList);
1360                 pkgdesc = formatStrVec(reqDescs, _( "and"));
1361                 if (!desc.empty())
1362                         desc += "\n";
1363                 desc += bformat(_("Modules excluded: %1$s."), pkgdesc);
1364         }
1365
1366         if (!isModuleAvailable(modName)) {
1367                 if (!desc.empty())
1368                         desc += "\n";
1369                 desc += _("WARNING: Some packages are unavailable!");
1370         }
1371
1372         latexModule->infoML->document()->setPlainText(toqstr(desc));
1373 }
1374
1375
1376 void GuiDocument::updateEmbeddedFileList()
1377 {
1378         embeddedFilesModule->filesLW->clear();
1379         // add current embedded files
1380         EmbeddedFileList & files = buffer().embeddedFiles();
1381         files.update(buffer());
1382         EmbeddedFileList::iterator fit = files.begin();
1383         EmbeddedFileList::iterator fit_end = files.end();
1384         for (; fit != fit_end; ++fit) {
1385                 QString label = toqstr(fit->relFilename(buffer().filePath()));
1386                 if (fit->refCount() > 1)
1387                         label += " (" + QString::number(fit->refCount()) + ")";
1388                 QListWidgetItem * item = new QListWidgetItem(label);
1389                 item->setFlags(item->flags() | Qt::ItemIsSelectable
1390                         | Qt::ItemIsUserCheckable);
1391                 if(fit->embedded())
1392                         item->setCheckState(Qt::Checked);
1393                 else
1394                         item->setCheckState(Qt::Unchecked);
1395                 // index of the currently used ParConstIterator
1396                 embeddedFilesModule->filesLW->addItem(item);
1397         }
1398 }
1399
1400
1401 void GuiDocument::updateNumbering()
1402 {
1403         DocumentClass const & tclass = bp_.documentClass();
1404
1405         numberingModule->tocTW->setUpdatesEnabled(false);
1406         numberingModule->tocTW->clear();
1407
1408         int const depth = numberingModule->depthSL->value();
1409         int const toc = numberingModule->tocSL->value();
1410         QString const no = qt_("No");
1411         QString const yes = qt_("Yes");
1412         QTreeWidgetItem * item = 0;
1413
1414         DocumentClass::const_iterator lit = tclass.begin();
1415         DocumentClass::const_iterator len = tclass.end();
1416         for (; lit != len; ++lit) {
1417                 int const toclevel = lit->toclevel;
1418                 if (toclevel != Layout::NOT_IN_TOC && lit->labeltype == LABEL_COUNTER) {
1419                         item = new QTreeWidgetItem(numberingModule->tocTW);
1420                         item->setText(0, toqstr(translateIfPossible(lit->name())));
1421                         item->setText(1, (toclevel <= depth) ? yes : no);
1422                         item->setText(2, (toclevel <= toc) ? yes : no);
1423                 }
1424         }
1425
1426         numberingModule->tocTW->setUpdatesEnabled(true);
1427         numberingModule->tocTW->update();
1428 }
1429
1430
1431 void GuiDocument::apply(BufferParams & params)
1432 {
1433         // preamble
1434         preambleModule->apply(params);
1435
1436         // biblio
1437         params.setCiteEngine(biblio::ENGINE_BASIC);
1438
1439         if (biblioModule->citeNatbibRB->isChecked()) {
1440                 bool const use_numerical_citations =
1441                         biblioModule->citeStyleCO->currentIndex();
1442                 if (use_numerical_citations)
1443                         params.setCiteEngine(biblio::ENGINE_NATBIB_NUMERICAL);
1444                 else
1445                         params.setCiteEngine(biblio::ENGINE_NATBIB_AUTHORYEAR);
1446
1447         } else if (biblioModule->citeJurabibRB->isChecked())
1448                 params.setCiteEngine(biblio::ENGINE_JURABIB);
1449
1450         params.use_bibtopic =
1451                 biblioModule->bibtopicCB->isChecked();
1452
1453         // language & quotes
1454         if (langModule->defaultencodingRB->isChecked()) {
1455                 params.inputenc = "auto";
1456         } else {
1457                 int i = langModule->encodingCO->currentIndex();
1458                 if (i == 0)
1459                         params.inputenc = "default";
1460                 else
1461                         params.inputenc =
1462                                 fromqstr(langModule->encodingCO->currentText());
1463         }
1464
1465         InsetQuotes::quote_language lga = InsetQuotes::EnglishQ;
1466         switch (langModule->quoteStyleCO->currentIndex()) {
1467         case 0:
1468                 lga = InsetQuotes::EnglishQ;
1469                 break;
1470         case 1:
1471                 lga = InsetQuotes::SwedishQ;
1472                 break;
1473         case 2:
1474                 lga = InsetQuotes::GermanQ;
1475                 break;
1476         case 3:
1477                 lga = InsetQuotes::PolishQ;
1478                 break;
1479         case 4:
1480                 lga = InsetQuotes::FrenchQ;
1481                 break;
1482         case 5:
1483                 lga = InsetQuotes::DanishQ;
1484                 break;
1485         }
1486         params.quotes_language = lga;
1487
1488         int const pos = langModule->languageCO->currentIndex();
1489         params.language = lyx::languages.getLanguage(lang_[pos]);
1490
1491         // numbering
1492         if (params.documentClass().hasTocLevels()) {
1493                 params.tocdepth = numberingModule->tocSL->value();
1494                 params.secnumdepth = numberingModule->depthSL->value();
1495         }
1496
1497         // bullets
1498         params.user_defined_bullet(0) = bulletsModule->getBullet(0);
1499         params.user_defined_bullet(1) = bulletsModule->getBullet(1);
1500         params.user_defined_bullet(2) = bulletsModule->getBullet(2);
1501         params.user_defined_bullet(3) = bulletsModule->getBullet(3);
1502
1503         // packages
1504         params.graphicsDriver =
1505                 tex_graphics[latexModule->psdriverCO->currentIndex()];
1506         
1507         // text layout
1508         int idx = latexModule->classCO->currentIndex();
1509         if (idx >= 0) {
1510                 string const classname = classes_model_.getIDString(idx);
1511                 params.setBaseClass(classname);
1512         }
1513
1514         // Modules
1515         params.clearLayoutModules();
1516         int const srows = modules_sel_model_.rowCount();
1517         vector<string> selModList;
1518         for (int i = 0; i < srows; ++i)
1519                 params.addLayoutModule(modules_sel_model_.getIDString(i));
1520
1521         if (mathsModule->amsautoCB->isChecked()) {
1522                 params.use_amsmath = BufferParams::package_auto;
1523         } else {
1524                 if (mathsModule->amsCB->isChecked())
1525                         params.use_amsmath = BufferParams::package_on;
1526                 else
1527                         params.use_amsmath = BufferParams::package_off;
1528         }
1529
1530         if (mathsModule->esintautoCB->isChecked())
1531                 params.use_esint = BufferParams::package_auto;
1532         else {
1533                 if (mathsModule->esintCB->isChecked())
1534                         params.use_esint = BufferParams::package_on;
1535                 else
1536                         params.use_esint = BufferParams::package_off;
1537         }
1538
1539         if (pageLayoutModule->pagestyleCO->currentIndex() == 0)
1540                 params.pagestyle = "default";
1541         else {
1542                 docstring style_gui =
1543                         qstring_to_ucs4(pageLayoutModule->pagestyleCO->currentText());
1544                 for (size_t i = 0; i < pagestyles.size(); ++i)
1545                         if (pagestyles[i].second == style_gui)
1546                                 params.pagestyle = pagestyles[i].first;
1547         }
1548
1549         switch (textLayoutModule->lspacingCO->currentIndex()) {
1550         case 0:
1551                 params.spacing().set(Spacing::Single);
1552                 break;
1553         case 1:
1554                 params.spacing().set(Spacing::Onehalf);
1555                 break;
1556         case 2:
1557                 params.spacing().set(Spacing::Double);
1558                 break;
1559         case 3:
1560                 params.spacing().set(Spacing::Other,
1561                         fromqstr(textLayoutModule->lspacingLE->text()));
1562                 break;
1563         }
1564
1565         if (textLayoutModule->twoColumnCB->isChecked())
1566                 params.columns = 2;
1567         else
1568                 params.columns = 1;
1569
1570         // text should have passed validation
1571         params.listings_params =
1572                 InsetListingsParams(fromqstr(textLayoutModule->listingsED->toPlainText())).params();
1573
1574         if (textLayoutModule->indentRB->isChecked())
1575                 params.paragraph_separation = BufferParams::PARSEP_INDENT;
1576         else
1577                 params.paragraph_separation = BufferParams::PARSEP_SKIP;
1578
1579         switch (textLayoutModule->skipCO->currentIndex()) {
1580         case 0:
1581                 params.setDefSkip(VSpace(VSpace::SMALLSKIP));
1582                 break;
1583         case 1:
1584                 params.setDefSkip(VSpace(VSpace::MEDSKIP));
1585                 break;
1586         case 2:
1587                 params.setDefSkip(VSpace(VSpace::BIGSKIP));
1588                 break;
1589         case 3:
1590         {
1591                 VSpace vs = VSpace(
1592                         widgetsToLength(textLayoutModule->skipLE,
1593                                 textLayoutModule->skipLengthCO)
1594                         );
1595                 params.setDefSkip(vs);
1596                 break;
1597         }
1598         default:
1599                 // DocumentDefskipCB assures that this never happens
1600                 // so Assert then !!!  - jbl
1601                 params.setDefSkip(VSpace(VSpace::MEDSKIP));
1602                 break;
1603         }
1604
1605         params.options =
1606                 fromqstr(latexModule->optionsLE->text());
1607
1608         params.float_placement = floatModule->get();
1609
1610         // fonts
1611         params.fontsRoman =
1612                 tex_fonts_roman[fontModule->fontsRomanCO->currentIndex()];
1613
1614         params.fontsSans =
1615                 tex_fonts_sans[fontModule->fontsSansCO->currentIndex()];
1616
1617         params.fontsTypewriter =
1618                 tex_fonts_monospaced[fontModule->fontsTypewriterCO->currentIndex()];
1619
1620         params.fontsSansScale = fontModule->scaleSansSB->value();
1621
1622         params.fontsTypewriterScale = fontModule->scaleTypewriterSB->value();
1623
1624         params.fontsSC = fontModule->fontScCB->isChecked();
1625
1626         params.fontsOSF = fontModule->fontOsfCB->isChecked();
1627
1628         params.fontsDefaultFamily = GuiDocument::fontfamilies[
1629                 fontModule->fontsDefaultCO->currentIndex()];
1630
1631         if (fontModule->fontsizeCO->currentIndex() == 0)
1632                 params.fontsize = "default";
1633         else
1634                 params.fontsize =
1635                         fromqstr(fontModule->fontsizeCO->currentText());
1636
1637         // paper
1638         params.papersize = PAPER_SIZE(
1639                 pageLayoutModule->papersizeCO->currentIndex());
1640
1641         // custom, A3, B3 and B4 paper sizes need geometry
1642         int psize = pageLayoutModule->papersizeCO->currentIndex();
1643         bool geom_papersize = (psize == 1 || psize == 5 || psize == 8 || psize == 9);
1644
1645         params.paperwidth = widgetsToLength(pageLayoutModule->paperwidthLE,
1646                 pageLayoutModule->paperwidthUnitCO);
1647
1648         params.paperheight = widgetsToLength(pageLayoutModule->paperheightLE,
1649                 pageLayoutModule->paperheightUnitCO);
1650
1651         if (pageLayoutModule->facingPagesCB->isChecked())
1652                 params.sides = TwoSides;
1653         else
1654                 params.sides = OneSide;
1655
1656         if (pageLayoutModule->landscapeRB->isChecked())
1657                 params.orientation = ORIENTATION_LANDSCAPE;
1658         else
1659                 params.orientation = ORIENTATION_PORTRAIT;
1660
1661         // margins
1662         params.use_geometry =
1663                 (!marginsModule->marginCB->isChecked()
1664                 || geom_papersize);
1665
1666         Ui::MarginsUi const * m(marginsModule);
1667
1668         params.leftmargin = widgetsToLength(m->innerLE, m->innerUnit);
1669         params.topmargin = widgetsToLength(m->topLE, m->topUnit);
1670         params.rightmargin = widgetsToLength(m->outerLE, m->outerUnit);
1671         params.bottommargin = widgetsToLength(m->bottomLE, m->bottomUnit);
1672         params.headheight = widgetsToLength(m->headheightLE, m->headheightUnit);
1673         params.headsep = widgetsToLength(m->headsepLE, m->headsepUnit);
1674         params.footskip = widgetsToLength(m->footskipLE, m->footskipUnit);
1675         params.columnsep = widgetsToLength(m->columnsepLE, m->columnsepUnit);
1676
1677         branchesModule->apply(params);
1678
1679         // PDF support
1680         PDFOptions & pdf = params.pdfoptions();
1681         pdf.use_hyperref = pdfSupportModule->use_hyperrefGB->isChecked();
1682         pdf.title = fromqstr(pdfSupportModule->titleLE->text());
1683         pdf.author = fromqstr(pdfSupportModule->authorLE->text());
1684         pdf.subject = fromqstr(pdfSupportModule->subjectLE->text());
1685         pdf.keywords = fromqstr(pdfSupportModule->keywordsLE->text());
1686
1687         pdf.bookmarks = pdfSupportModule->bookmarksGB->isChecked();
1688         pdf.bookmarksnumbered = pdfSupportModule->bookmarksnumberedCB->isChecked();
1689         pdf.bookmarksopen = pdfSupportModule->bookmarksopenGB->isChecked();
1690         pdf.bookmarksopenlevel = pdfSupportModule->bookmarksopenlevelSB->value();
1691
1692         pdf.breaklinks = pdfSupportModule->breaklinksCB->isChecked();
1693         pdf.pdfborder = pdfSupportModule->pdfborderCB->isChecked();
1694         pdf.pdfusetitle = pdfSupportModule->pdfusetitleCB->isChecked();
1695         pdf.colorlinks = pdfSupportModule->colorlinksCB->isChecked();
1696         pdf.backref = pdfSupportModule->backrefCB->isChecked();
1697         pdf.pagebackref = pdfSupportModule->pagebackrefCB->isChecked();
1698         if (pdfSupportModule->fullscreenCB->isChecked())
1699                 pdf.pagemode = pdf.pagemode_fullscreen;
1700         else
1701                 pdf.pagemode.clear();
1702         pdf.quoted_options = pdf.quoted_options_check(
1703                                 fromqstr(pdfSupportModule->optionsLE->text()));
1704
1705         // Embedded files
1706         // FIXME
1707 }
1708
1709
1710 /** Return the position of val in the vector if found.
1711     If not found, return 0.
1712  */
1713 template<class A>
1714 static size_t findPos(vector<A> const & vec, A const & val)
1715 {
1716         typename vector<A>::const_iterator it =
1717                 find(vec.begin(), vec.end(), val);
1718         if (it == vec.end())
1719                 return 0;
1720         return distance(vec.begin(), it);
1721 }
1722
1723
1724 void GuiDocument::updateParams()
1725 {
1726         updateParams(bp_);
1727 }
1728
1729
1730 void GuiDocument::updateParams(BufferParams const & params)
1731 {
1732         // set the default unit
1733         Length::UNIT defaultUnit = Length::CM;
1734         switch (lyxrc.default_papersize) {
1735                 case PAPER_DEFAULT: break;
1736
1737                 case PAPER_USLETTER:
1738                 case PAPER_USLEGAL:
1739                 case PAPER_USEXECUTIVE:
1740                         defaultUnit = Length::IN;
1741                         break;
1742
1743                 case PAPER_A3:
1744                 case PAPER_A4:
1745                 case PAPER_A5:
1746                 case PAPER_B3:
1747                 case PAPER_B4:
1748                 case PAPER_B5:
1749                         defaultUnit = Length::CM;
1750                         break;
1751                 case PAPER_CUSTOM:
1752                         break;
1753         }
1754
1755         // preamble
1756         preambleModule->update(params, id());
1757
1758         // biblio
1759         biblioModule->citeDefaultRB->setChecked(
1760                 params.getEngine() == biblio::ENGINE_BASIC);
1761
1762         biblioModule->citeNatbibRB->setChecked(
1763                 params.getEngine() == biblio::ENGINE_NATBIB_NUMERICAL ||
1764                 params.getEngine() == biblio::ENGINE_NATBIB_AUTHORYEAR);
1765
1766         biblioModule->citeStyleCO->setCurrentIndex(
1767                 params.getEngine() == biblio::ENGINE_NATBIB_NUMERICAL);
1768
1769         biblioModule->citeJurabibRB->setChecked(
1770                 params.getEngine() == biblio::ENGINE_JURABIB);
1771
1772         biblioModule->bibtopicCB->setChecked(
1773                 params.use_bibtopic);
1774
1775         // language & quotes
1776         int const pos = int(findPos(lang_,
1777                                     params.language->lang()));
1778         langModule->languageCO->setCurrentIndex(pos);
1779
1780         langModule->quoteStyleCO->setCurrentIndex(
1781                 params.quotes_language);
1782
1783         bool default_enc = true;
1784         if (params.inputenc != "auto") {
1785                 default_enc = false;
1786                 if (params.inputenc == "default") {
1787                         langModule->encodingCO->setCurrentIndex(0);
1788                 } else {
1789                         int const i = langModule->encodingCO->findText(
1790                                         toqstr(params.inputenc));
1791                         if (i >= 0)
1792                                 langModule->encodingCO->setCurrentIndex(i);
1793                         else
1794                                 // unknown encoding. Set to default.
1795                                 default_enc = true;
1796                 }
1797         }
1798         langModule->defaultencodingRB->setChecked(default_enc);
1799         langModule->otherencodingRB->setChecked(!default_enc);
1800
1801         // numbering
1802         int const min_toclevel = documentClass().min_toclevel();
1803         int const max_toclevel = documentClass().max_toclevel();
1804         if (documentClass().hasTocLevels()) {
1805                 numberingModule->setEnabled(true);
1806                 numberingModule->depthSL->setMinimum(min_toclevel - 1);
1807                 numberingModule->depthSL->setMaximum(max_toclevel);
1808                 numberingModule->depthSL->setValue(params.secnumdepth);
1809                 numberingModule->tocSL->setMaximum(min_toclevel - 1);
1810                 numberingModule->tocSL->setMaximum(max_toclevel);
1811                 numberingModule->tocSL->setValue(params.tocdepth);
1812                 updateNumbering();
1813         } else {
1814                 numberingModule->setEnabled(false);
1815                 numberingModule->tocTW->clear();
1816         }
1817
1818         // bullets
1819         bulletsModule->setBullet(0, params.user_defined_bullet(0));
1820         bulletsModule->setBullet(1, params.user_defined_bullet(1));
1821         bulletsModule->setBullet(2, params.user_defined_bullet(2));
1822         bulletsModule->setBullet(3, params.user_defined_bullet(3));
1823         bulletsModule->init();
1824
1825         // packages
1826         int nitem = findToken(tex_graphics, params.graphicsDriver);
1827         if (nitem >= 0)
1828                 latexModule->psdriverCO->setCurrentIndex(nitem);
1829         updateModuleInfo();
1830         
1831         mathsModule->amsCB->setChecked(
1832                 params.use_amsmath == BufferParams::package_on);
1833         mathsModule->amsautoCB->setChecked(
1834                 params.use_amsmath == BufferParams::package_auto);
1835
1836         mathsModule->esintCB->setChecked(
1837                 params.use_esint == BufferParams::package_on);
1838         mathsModule->esintautoCB->setChecked(
1839                 params.use_esint == BufferParams::package_auto);
1840
1841         switch (params.spacing().getSpace()) {
1842                 case Spacing::Other: nitem = 3; break;
1843                 case Spacing::Double: nitem = 2; break;
1844                 case Spacing::Onehalf: nitem = 1; break;
1845                 case Spacing::Default: case Spacing::Single: nitem = 0; break;
1846         }
1847
1848         // text layout
1849         string const & layoutID = params.baseClassID();
1850         setLayoutComboByIDString(layoutID);
1851
1852         updatePagestyle(documentClass().opt_pagestyle(),
1853                                  params.pagestyle);
1854
1855         textLayoutModule->lspacingCO->setCurrentIndex(nitem);
1856         if (params.spacing().getSpace() == Spacing::Other) {
1857                 textLayoutModule->lspacingLE->setText(
1858                         toqstr(params.spacing().getValueAsString()));
1859         }
1860         setLSpacing(nitem);
1861
1862         if (params.paragraph_separation == BufferParams::PARSEP_INDENT)
1863                 textLayoutModule->indentRB->setChecked(true);
1864         else
1865                 textLayoutModule->skipRB->setChecked(true);
1866
1867         int skip = 0;
1868         switch (params.getDefSkip().kind()) {
1869         case VSpace::SMALLSKIP:
1870                 skip = 0;
1871                 break;
1872         case VSpace::MEDSKIP:
1873                 skip = 1;
1874                 break;
1875         case VSpace::BIGSKIP:
1876                 skip = 2;
1877                 break;
1878         case VSpace::LENGTH:
1879         {
1880                 skip = 3;
1881                 string const length = params.getDefSkip().asLyXCommand();
1882                 lengthToWidgets(textLayoutModule->skipLE,
1883                         textLayoutModule->skipLengthCO,
1884                         length, defaultUnit);
1885                 break;
1886         }
1887         default:
1888                 skip = 0;
1889                 break;
1890         }
1891         textLayoutModule->skipCO->setCurrentIndex(skip);
1892         setSkip(skip);
1893
1894         textLayoutModule->twoColumnCB->setChecked(
1895                 params.columns == 2);
1896
1897         // break listings_params to multiple lines
1898         string lstparams =
1899                 InsetListingsParams(params.listings_params).separatedParams();
1900         textLayoutModule->listingsED->setPlainText(toqstr(lstparams));
1901
1902         if (!params.options.empty()) {
1903                 latexModule->optionsLE->setText(
1904                         toqstr(params.options));
1905         } else {
1906                 latexModule->optionsLE->setText(QString());
1907         }
1908
1909         floatModule->set(params.float_placement);
1910
1911         // Fonts
1912         updateFontsize(documentClass().opt_fontsize(),
1913                         params.fontsize);
1914
1915         int n = findToken(tex_fonts_roman, params.fontsRoman);
1916         if (n >= 0) {
1917                 fontModule->fontsRomanCO->setCurrentIndex(n);
1918                 romanChanged(n);
1919         }
1920
1921         n = findToken(tex_fonts_sans, params.fontsSans);
1922         if (n >= 0)     {
1923                 fontModule->fontsSansCO->setCurrentIndex(n);
1924                 sansChanged(n);
1925         }
1926
1927         n = findToken(tex_fonts_monospaced, params.fontsTypewriter);
1928         if (n >= 0) {
1929                 fontModule->fontsTypewriterCO->setCurrentIndex(n);
1930                 ttChanged(n);
1931         }
1932
1933         fontModule->fontScCB->setChecked(params.fontsSC);
1934         fontModule->fontOsfCB->setChecked(params.fontsOSF);
1935         fontModule->scaleSansSB->setValue(params.fontsSansScale);
1936         fontModule->scaleTypewriterSB->setValue(params.fontsTypewriterScale);
1937         n = findToken(GuiDocument::fontfamilies, params.fontsDefaultFamily);
1938         if (n >= 0)
1939                 fontModule->fontsDefaultCO->setCurrentIndex(n);
1940
1941         // paper
1942         int const psize = params.papersize;
1943         pageLayoutModule->papersizeCO->setCurrentIndex(psize);
1944         setCustomPapersize(psize);
1945
1946         bool const landscape =
1947                 params.orientation == ORIENTATION_LANDSCAPE;
1948         pageLayoutModule->landscapeRB->setChecked(landscape);
1949         pageLayoutModule->portraitRB->setChecked(!landscape);
1950
1951         pageLayoutModule->facingPagesCB->setChecked(
1952                 params.sides == TwoSides);
1953
1954
1955         lengthToWidgets(pageLayoutModule->paperwidthLE,
1956                 pageLayoutModule->paperwidthUnitCO, params.paperwidth, defaultUnit);
1957
1958         lengthToWidgets(pageLayoutModule->paperheightLE,
1959                 pageLayoutModule->paperheightUnitCO, params.paperheight, defaultUnit);
1960
1961         // margins
1962         Ui::MarginsUi * m = marginsModule;
1963
1964         setMargins(!params.use_geometry);
1965
1966         lengthToWidgets(m->topLE, m->topUnit,
1967                 params.topmargin, defaultUnit);
1968
1969         lengthToWidgets(m->bottomLE, m->bottomUnit,
1970                 params.bottommargin, defaultUnit);
1971
1972         lengthToWidgets(m->innerLE, m->innerUnit,
1973                 params.leftmargin, defaultUnit);
1974
1975         lengthToWidgets(m->outerLE, m->outerUnit,
1976                 params.rightmargin, defaultUnit);
1977
1978         lengthToWidgets(m->headheightLE, m->headheightUnit,
1979                 params.headheight, defaultUnit);
1980
1981         lengthToWidgets(m->headsepLE, m->headsepUnit,
1982                 params.headsep, defaultUnit);
1983
1984         lengthToWidgets(m->footskipLE, m->footskipUnit,
1985                 params.footskip, defaultUnit);
1986
1987         lengthToWidgets(m->columnsepLE, m->columnsepUnit,
1988                 params.columnsep, defaultUnit);
1989
1990         branchesModule->update(params);
1991
1992         // PDF support
1993         PDFOptions const & pdf = params.pdfoptions();
1994         pdfSupportModule->use_hyperrefGB->setChecked(pdf.use_hyperref);
1995         pdfSupportModule->titleLE->setText(toqstr(pdf.title));
1996         pdfSupportModule->authorLE->setText(toqstr(pdf.author));
1997         pdfSupportModule->subjectLE->setText(toqstr(pdf.subject));
1998         pdfSupportModule->keywordsLE->setText(toqstr(pdf.keywords));
1999
2000         pdfSupportModule->bookmarksGB->setChecked(pdf.bookmarks);
2001         pdfSupportModule->bookmarksnumberedCB->setChecked(pdf.bookmarksnumbered);
2002         pdfSupportModule->bookmarksopenGB->setChecked(pdf.bookmarksopen);
2003
2004         pdfSupportModule->bookmarksopenlevelSB->setValue(pdf.bookmarksopenlevel);
2005
2006         pdfSupportModule->breaklinksCB->setChecked(pdf.breaklinks);
2007         pdfSupportModule->pdfborderCB->setChecked(pdf.pdfborder);
2008         pdfSupportModule->pdfusetitleCB->setChecked(pdf.pdfusetitle);
2009         pdfSupportModule->colorlinksCB->setChecked(pdf.colorlinks);
2010         pdfSupportModule->backrefCB->setChecked(pdf.backref);
2011         pdfSupportModule->pagebackrefCB->setChecked(pdf.pagebackref);
2012         pdfSupportModule->fullscreenCB->setChecked
2013                 (pdf.pagemode == pdf.pagemode_fullscreen);
2014
2015         pdfSupportModule->optionsLE->setText(
2016                 toqstr(pdf.quoted_options));
2017
2018         // embedded files
2019         updateEmbeddedFileList();
2020 }
2021
2022
2023 void GuiDocument::applyView()
2024 {
2025         apply(params());
2026 }
2027
2028
2029 void GuiDocument::saveDocDefault()
2030 {
2031         // we have to apply the params first
2032         applyView();
2033         saveAsDefault();
2034 }
2035
2036
2037 void GuiDocument::updateAvailableModules() 
2038 {
2039         modules_av_model_.clear();
2040         vector<modInfoStruct> const modInfoList = getModuleInfo();
2041         int const mSize = modInfoList.size();
2042         for (int i = 0; i < mSize; ++i) {
2043                 modInfoStruct const & modInfo = modInfoList[i];
2044                 modules_av_model_.insertRow(i, qt_(modInfo.name), modInfo.id);
2045         }
2046 }
2047
2048
2049 void GuiDocument::updateSelectedModules() 
2050 {
2051         //and selected ones, too
2052         modules_sel_model_.clear();
2053         vector<modInfoStruct> const selModList = getSelectedModules();
2054         int const sSize = selModList.size();
2055         for (int i = 0; i < sSize; ++i) {
2056                 modInfoStruct const & modInfo = selModList[i];
2057                 modules_sel_model_.insertRow(i, qt_(modInfo.name), modInfo.id);
2058         }
2059 }
2060
2061
2062 void GuiDocument::updateContents()
2063 {
2064         if (id() == current_id_)
2065                 return;
2066
2067         updateAvailableModules();
2068         updateSelectedModules();
2069         
2070         //FIXME It'd be nice to make sure here that the selected
2071         //modules are consistent: That required modules are actually
2072         //selected, and that we don't have conflicts. If so, we could
2073         //at least pop up a warning.
2074         updateParams(bp_);
2075         current_id_ = id();
2076 }
2077
2078
2079 void GuiDocument::forceUpdate()
2080 {
2081         // reset to force dialog update
2082         current_id_ = 0;
2083         updateContents();
2084 }
2085
2086
2087 void GuiDocument::useClassDefaults()
2088 {
2089         if (applyPB->isEnabled()) {
2090                 int const ret = Alert::prompt(_("Unapplied changes"),
2091                                 _("Some changes in the dialog were not yet applied."
2092                                   "If you do not apply now, they will be lost after this action."),
2093                                 1, 1, _("&Apply"), _("&Dismiss"));
2094                 if (ret == 0)
2095                         applyView();
2096         }
2097
2098         int idx = latexModule->classCO->currentIndex();
2099         string const classname = classes_model_.getIDString(idx);
2100         if (!bp_.setBaseClass(classname)) {
2101                 Alert::error(_("Error"), _("Unable to set document class."));
2102                 return;
2103         }
2104         bp_.useClassDefaults();
2105         forceUpdate();
2106 }
2107
2108
2109 void GuiDocument::setLayoutComboByIDString(std::string const & idString)
2110 {
2111         int idx = classes_model_.findIDString(idString);
2112         if (idx < 0)
2113                 Alert::warning(_("Can't set layout!"), 
2114                         bformat(_("Unable to set layout for ID: %1$s"), from_utf8(idString)));
2115         else 
2116                 latexModule->classCO->setCurrentIndex(idx);
2117 }
2118
2119
2120 bool GuiDocument::isValid()
2121 {
2122         return (validate_listings_params().empty() &&
2123                 (textLayoutModule->skipCO->currentIndex() != 3 ||
2124                  !textLayoutModule->skipLE->text().isEmpty()));
2125 }
2126
2127
2128 char const * const GuiDocument::fontfamilies[5] = {
2129         "default", "rmdefault", "sfdefault", "ttdefault", ""
2130 };
2131
2132
2133 char const * GuiDocument::fontfamilies_gui[5] = {
2134         N_("Default"), N_("Roman"), N_("Sans Serif"), N_("Typewriter"), ""
2135 };
2136
2137
2138 bool GuiDocument::initialiseParams(string const &)
2139 {
2140         bp_ = buffer().params();
2141         loadModuleInfo();
2142         return true;
2143 }
2144
2145
2146 void GuiDocument::clearParams()
2147 {
2148         bp_ = BufferParams();
2149 }
2150
2151
2152 BufferId GuiDocument::id() const
2153 {
2154         return &buffer();
2155 }
2156
2157
2158 vector<GuiDocument::modInfoStruct> const & GuiDocument::getModuleInfo()
2159 {
2160         return moduleNames_;
2161 }
2162
2163
2164 vector<GuiDocument::modInfoStruct> const GuiDocument::getSelectedModules()
2165 {
2166         vector<string> const & mods = params().getModules();
2167         vector<string>::const_iterator it =  mods.begin();
2168         vector<string>::const_iterator end = mods.end();
2169         vector<modInfoStruct> mInfo;
2170         for (; it != end; ++it) {
2171                 modInfoStruct m;
2172                 m.id = *it;
2173                 LyXModule * mod = moduleList[*it];
2174                 if (mod)
2175                         m.name = mod->getName();
2176                 else 
2177                         m.name = *it + " (Not Found)";
2178                 mInfo.push_back(m);
2179         }
2180         return mInfo;
2181 }
2182
2183
2184 DocumentClass const & GuiDocument::documentClass() const
2185 {
2186         return bp_.documentClass();
2187 }
2188
2189
2190 static void dispatch_bufferparams(Dialog const & dialog,
2191         BufferParams const & bp, kb_action lfun)
2192 {
2193         ostringstream ss;
2194         ss << "\\begin_header\n";
2195         bp.writeFile(ss);
2196         ss << "\\end_header\n";
2197         dialog.dispatch(FuncRequest(lfun, ss.str()));
2198 }
2199
2200
2201 void GuiDocument::dispatchParams()
2202 {
2203         // This must come first so that a language change is correctly noticed
2204         setLanguage();
2205
2206         // Apply the BufferParams. Note that this will set the base class
2207         // and then update the buffer's layout.
2208         dispatch_bufferparams(*this, params(), LFUN_BUFFER_PARAMS_APPLY);
2209
2210         // Generate the colours requested by each new branch.
2211         BranchList & branchlist = params().branchlist();
2212         if (!branchlist.empty()) {
2213                 BranchList::const_iterator it = branchlist.begin();
2214                 BranchList::const_iterator const end = branchlist.end();
2215                 for (; it != end; ++it) {
2216                         docstring const & current_branch = it->getBranch();
2217                         Branch const * branch = branchlist.find(current_branch);
2218                         string const x11hexname = X11hexname(branch->getColor());
2219                         // display the new color
2220                         docstring const str = current_branch + ' ' + from_ascii(x11hexname);
2221                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
2222                 }
2223
2224                 // Open insets of selected branches, close deselected ones
2225                 dispatch(FuncRequest(LFUN_ALL_INSETS_TOGGLE,
2226                         "assign branch"));
2227         }
2228         // FIXME: If we used an LFUN, we would not need those two lines:
2229         bufferview()->processUpdateFlags(Update::Force | Update::FitCursor);
2230 }
2231
2232
2233 void GuiDocument::setLanguage() const
2234 {
2235         Language const * const newL = bp_.language;
2236         if (buffer().params().language == newL)
2237                 return;
2238
2239         string const & lang_name = newL->lang();
2240         dispatch(FuncRequest(LFUN_BUFFER_LANGUAGE, lang_name));
2241 }
2242
2243
2244 void GuiDocument::saveAsDefault() const
2245 {
2246         dispatch_bufferparams(*this, params(), LFUN_BUFFER_SAVE_AS_DEFAULT);
2247 }
2248
2249
2250 bool GuiDocument::isFontAvailable(string const & font) const
2251 {
2252         if (font == "default" || font == "cmr"
2253             || font == "cmss" || font == "cmtt")
2254                 // these are standard
2255                 return true;
2256         if (font == "lmodern" || font == "lmss" || font == "lmtt")
2257                 return LaTeXFeatures::isAvailable("lmodern");
2258         if (font == "times" || font == "palatino"
2259                  || font == "helvet" || font == "courier")
2260                 return LaTeXFeatures::isAvailable("psnfss");
2261         if (font == "cmbr" || font == "cmtl")
2262                 return LaTeXFeatures::isAvailable("cmbright");
2263         if (font == "utopia")
2264                 return LaTeXFeatures::isAvailable("utopia")
2265                         || LaTeXFeatures::isAvailable("fourier");
2266         if (font == "beraserif" || font == "berasans"
2267                 || font == "beramono")
2268                 return LaTeXFeatures::isAvailable("bera");
2269         return LaTeXFeatures::isAvailable(font);
2270 }
2271
2272
2273 bool GuiDocument::providesOSF(string const & font) const
2274 {
2275         if (font == "cmr")
2276                 return isFontAvailable("eco");
2277         if (font == "palatino")
2278                 return isFontAvailable("mathpazo");
2279         return false;
2280 }
2281
2282
2283 bool GuiDocument::providesSC(string const & font) const
2284 {
2285         if (font == "palatino")
2286                 return isFontAvailable("mathpazo");
2287         if (font == "utopia")
2288                 return isFontAvailable("fourier");
2289         return false;
2290 }
2291
2292
2293 bool GuiDocument::providesScale(string const & font) const
2294 {
2295         return font == "helvet" || font == "luximono"
2296                 || font == "berasans"  || font == "beramono";
2297 }
2298
2299
2300 void GuiDocument::loadModuleInfo()
2301 {
2302         moduleNames_.clear();
2303         LyXModuleList::const_iterator it  = moduleList.begin();
2304         LyXModuleList::const_iterator end = moduleList.end();
2305         for (; it != end; ++it) {
2306                 modInfoStruct m;
2307                 m.id = it->getID();
2308                 m.name = it->getName();
2309                 moduleNames_.push_back(m);
2310         }
2311 }
2312
2313
2314 Dialog * createGuiDocument(GuiView & lv) { return new GuiDocument(lv); }
2315
2316
2317 } // namespace frontend
2318 } // namespace lyx
2319
2320 #include "GuiDocument_moc.cpp"