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