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