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