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