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