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