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