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