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