]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiDocument.cpp
51399bd4c54b44f9d0d71a282dcc8724510178da
[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_("Language Default (no inputenc)"));
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         // FIXME There's a little bug here connected with auto_reset, namely,
1327         // that, if the preceding is skipped and the user has changed the
1328         // modules before changing the class, those changes will be lost on
1329         // update. But maybe that's what we want?
1330         updateSelectedModules();
1331 }
1332
1333
1334 namespace {
1335         // This is an insanely complicated attempt to make this sort of thing
1336         // work with RTL languages.
1337         docstring formatStrVec(vector<string> const & v, docstring const & s) 
1338         {
1339                 //this mess formats the list as "v[0], v[1], ..., [s] v[n]"
1340                 int const vSize = v.size();
1341                 if (v.size() == 0)
1342                         return docstring();
1343                 else if (v.size() == 1) 
1344                         return from_ascii(v[0]);
1345                 else if (v.size() == 2) {
1346                         docstring retval = _("%1$s and %2$s");
1347                         retval = subst(retval, _("and"), s);
1348                         return bformat(retval, from_ascii(v[0]), from_ascii(v[1]));
1349                 }
1350                 //The idea here is to format all but the last two items...
1351                 docstring t2 = _("%1$s, %2$s");
1352                 docstring retval = from_ascii(v[0]);
1353                 for (int i = 1; i < vSize - 2; ++i)
1354                         retval = bformat(t2, retval, from_ascii(v[i])); 
1355                 //...and then to  plug them, and the last two, into this schema
1356                 docstring t = _("%1$s, %2$s, and %3$s");
1357                 t = subst(t, _("and"), s);
1358                 return bformat(t, retval, from_ascii(v[vSize - 2]), from_ascii(v[vSize - 1]));
1359         }
1360         
1361         vector<string> idsToNames(vector<string> const & idList)
1362         {
1363                 vector<string> retval;
1364                 vector<string>::const_iterator it  = idList.begin();
1365                 vector<string>::const_iterator end = idList.end();
1366                 for (; it != end; ++it) {
1367                         LyXModule const * const mod = moduleList[*it];
1368                         if (!mod)
1369                                 retval.push_back(*it + " (Unavailable)");
1370                         else
1371                                 retval.push_back(mod->getName());
1372                 }
1373                 return retval;
1374         }
1375 }
1376
1377
1378 void GuiDocument::updateModuleInfo()
1379 {
1380         selectionManager->update();
1381         
1382         //Module description
1383         bool const focusOnSelected = selectionManager->selectedFocused();
1384         QListView const * const lv = 
1385                         focusOnSelected ? latexModule->selectedLV : latexModule->availableLV;
1386         if (lv->selectionModel()->selectedIndexes().isEmpty()) {
1387                 latexModule->infoML->document()->clear();
1388                 return;
1389         }
1390         QModelIndex const & idx = lv->selectionModel()->currentIndex();
1391         GuiIdListModel const & idModel = 
1392                         focusOnSelected  ? modules_sel_model_ : modules_av_model_;
1393         string const modName = idModel.getIDString(idx.row());
1394         docstring desc = getModuleDescription(modName);
1395
1396         vector<string> pkgList = getPackageList(modName);
1397         docstring pkgdesc = formatStrVec(pkgList, _("and"));
1398         if (!pkgdesc.empty()) {
1399                 if (!desc.empty())
1400                         desc += "\n";
1401                 desc += bformat(_("Package(s) required: %1$s."), pkgdesc);
1402         }
1403
1404         pkgList = getRequiredList(modName);
1405         if (!pkgList.empty()) {
1406                 vector<string> const reqDescs = idsToNames(pkgList);
1407                 pkgdesc = formatStrVec(reqDescs, _("or"));
1408                 if (!desc.empty())
1409                         desc += "\n";
1410                 desc += bformat(_("Module required: %1$s."), pkgdesc);
1411         }
1412
1413         pkgList = getExcludedList(modName);
1414         if (!pkgList.empty()) {
1415                 vector<string> const reqDescs = idsToNames(pkgList);
1416                 pkgdesc = formatStrVec(reqDescs, _( "and"));
1417                 if (!desc.empty())
1418                         desc += "\n";
1419                 desc += bformat(_("Modules excluded: %1$s."), pkgdesc);
1420         }
1421
1422         if (!isModuleAvailable(modName)) {
1423                 if (!desc.empty())
1424                         desc += "\n";
1425                 desc += _("WARNING: Some packages are unavailable!");
1426         }
1427
1428         latexModule->infoML->document()->setPlainText(toqstr(desc));
1429 }
1430
1431
1432 void GuiDocument::updateNumbering()
1433 {
1434         DocumentClass const & tclass = bp_.documentClass();
1435
1436         numberingModule->tocTW->setUpdatesEnabled(false);
1437         numberingModule->tocTW->clear();
1438
1439         int const depth = numberingModule->depthSL->value();
1440         int const toc = numberingModule->tocSL->value();
1441         QString const no = qt_("No");
1442         QString const yes = qt_("Yes");
1443         QTreeWidgetItem * item = 0;
1444
1445         DocumentClass::const_iterator lit = tclass.begin();
1446         DocumentClass::const_iterator len = tclass.end();
1447         for (; lit != len; ++lit) {
1448                 int const toclevel = lit->toclevel;
1449                 if (toclevel != Layout::NOT_IN_TOC && lit->labeltype == LABEL_COUNTER) {
1450                         item = new QTreeWidgetItem(numberingModule->tocTW);
1451                         item->setText(0, toqstr(translateIfPossible(lit->name())));
1452                         item->setText(1, (toclevel <= depth) ? yes : no);
1453                         item->setText(2, (toclevel <= toc) ? yes : no);
1454                 }
1455         }
1456
1457         numberingModule->tocTW->setUpdatesEnabled(true);
1458         numberingModule->tocTW->update();
1459 }
1460
1461
1462 void GuiDocument::apply(BufferParams & params)
1463 {
1464         // preamble
1465         preambleModule->apply(params);
1466
1467         // biblio
1468         params.setCiteEngine(ENGINE_BASIC);
1469
1470         if (biblioModule->citeNatbibRB->isChecked()) {
1471                 bool const use_numerical_citations =
1472                         biblioModule->citeStyleCO->currentIndex();
1473                 if (use_numerical_citations)
1474                         params.setCiteEngine(ENGINE_NATBIB_NUMERICAL);
1475                 else
1476                         params.setCiteEngine(ENGINE_NATBIB_AUTHORYEAR);
1477
1478         } else if (biblioModule->citeJurabibRB->isChecked())
1479                 params.setCiteEngine(ENGINE_JURABIB);
1480
1481         params.use_bibtopic =
1482                 biblioModule->bibtopicCB->isChecked();
1483
1484         // language & quotes
1485         if (langModule->defaultencodingRB->isChecked()) {
1486                 params.inputenc = "auto";
1487         } else {
1488                 int i = langModule->encodingCO->currentIndex();
1489                 if (i == 0)
1490                         params.inputenc = "default";
1491                 else {
1492                         QString const enc_gui =
1493                                 langModule->encodingCO->currentText();
1494                         Encodings::const_iterator it = encodings.begin();
1495                         Encodings::const_iterator const end = encodings.end();
1496                         bool found = false;
1497                         for (; it != end; ++it) {
1498                                 if (qt_(it->guiName()) == enc_gui) {
1499                                         params.inputenc = it->latexName();
1500                                         found = true;
1501                                         break;
1502                                 }
1503                         }
1504                         if (!found) {
1505                                 // should not happen
1506                                 lyxerr << "GuiDocument::apply: Unknown encoding! Resetting to default" << endl;
1507                                 params.inputenc = "default";
1508                         }
1509                 }
1510         }
1511
1512         InsetQuotes::QuoteLanguage lga = InsetQuotes::EnglishQuotes;
1513         switch (langModule->quoteStyleCO->currentIndex()) {
1514         case 0:
1515                 lga = InsetQuotes::EnglishQuotes;
1516                 break;
1517         case 1:
1518                 lga = InsetQuotes::SwedishQuotes;
1519                 break;
1520         case 2:
1521                 lga = InsetQuotes::GermanQuotes;
1522                 break;
1523         case 3:
1524                 lga = InsetQuotes::PolishQuotes;
1525                 break;
1526         case 4:
1527                 lga = InsetQuotes::FrenchQuotes;
1528                 break;
1529         case 5:
1530                 lga = InsetQuotes::DanishQuotes;
1531                 break;
1532         }
1533         params.quotes_language = lga;
1534
1535         QString const lang = langModule->languageCO->itemData(
1536                 langModule->languageCO->currentIndex()).toString();
1537         params.language = lyx::languages.getLanguage(fromqstr(lang));
1538
1539         // numbering
1540         if (params.documentClass().hasTocLevels()) {
1541                 params.tocdepth = numberingModule->tocSL->value();
1542                 params.secnumdepth = numberingModule->depthSL->value();
1543         }
1544
1545         // bullets
1546         params.user_defined_bullet(0) = bulletsModule->getBullet(0);
1547         params.user_defined_bullet(1) = bulletsModule->getBullet(1);
1548         params.user_defined_bullet(2) = bulletsModule->getBullet(2);
1549         params.user_defined_bullet(3) = bulletsModule->getBullet(3);
1550
1551         // packages
1552         params.graphicsDriver =
1553                 tex_graphics[latexModule->psdriverCO->currentIndex()];
1554         
1555         // text layout
1556         int idx = latexModule->classCO->currentIndex();
1557         if (idx >= 0) {
1558                 string const classname = classes_model_.getIDString(idx);
1559                 params.setBaseClass(classname);
1560         }
1561
1562         // Modules
1563         params.clearLayoutModules();
1564         int const srows = modules_sel_model_.rowCount();
1565         vector<string> selModList;
1566         for (int i = 0; i < srows; ++i)
1567                 params.addLayoutModule(modules_sel_model_.getIDString(i));
1568         // update the list of removed modules
1569         params.clearRemovedModules();
1570         set<string> const & reqmods = params.baseClass()->defaultModules();
1571         set<string>::const_iterator rit = reqmods.begin();
1572         set<string>::const_iterator ren = reqmods.end();
1573         // check each of the required modules
1574         for (; rit != ren; rit++) {
1575                 vector<string>::const_iterator mit = params.getModules().begin();
1576                 vector<string>::const_iterator men = params.getModules().end();
1577                 bool found = false;
1578                 for (; mit != men; mit++) {
1579                         if (*rit == *mit) {
1580                                 found = true;
1581                                 break;
1582                         }
1583                 }
1584                 if (!found) {
1585                         // the module isn't present so must have been removed by the user
1586                         params.addRemovedModule(*rit);
1587                 }
1588         }
1589
1590         if (mathsModule->amsautoCB->isChecked()) {
1591                 params.use_amsmath = BufferParams::package_auto;
1592         } else {
1593                 if (mathsModule->amsCB->isChecked())
1594                         params.use_amsmath = BufferParams::package_on;
1595                 else
1596                         params.use_amsmath = BufferParams::package_off;
1597         }
1598
1599         if (mathsModule->esintautoCB->isChecked())
1600                 params.use_esint = BufferParams::package_auto;
1601         else {
1602                 if (mathsModule->esintCB->isChecked())
1603                         params.use_esint = BufferParams::package_on;
1604                 else
1605                         params.use_esint = BufferParams::package_off;
1606         }
1607
1608         if (pageLayoutModule->pagestyleCO->currentIndex() == 0)
1609                 params.pagestyle = "default";
1610         else {
1611                 docstring style_gui =
1612                         qstring_to_ucs4(pageLayoutModule->pagestyleCO->currentText());
1613                 for (size_t i = 0; i < pagestyles.size(); ++i)
1614                         if (pagestyles[i].second == style_gui)
1615                                 params.pagestyle = pagestyles[i].first;
1616         }
1617
1618         switch (textLayoutModule->lspacingCO->currentIndex()) {
1619         case 0:
1620                 params.spacing().set(Spacing::Single);
1621                 break;
1622         case 1:
1623                 params.spacing().set(Spacing::Onehalf);
1624                 break;
1625         case 2:
1626                 params.spacing().set(Spacing::Double);
1627                 break;
1628         case 3:
1629                 params.spacing().set(Spacing::Other,
1630                         fromqstr(textLayoutModule->lspacingLE->text()));
1631                 break;
1632         }
1633
1634         if (textLayoutModule->twoColumnCB->isChecked())
1635                 params.columns = 2;
1636         else
1637                 params.columns = 1;
1638
1639         // text should have passed validation
1640         params.listings_params =
1641                 InsetListingsParams(fromqstr(textLayoutModule->listingsED->toPlainText())).params();
1642
1643         if (textLayoutModule->indentRB->isChecked())
1644                 params.paragraph_separation = BufferParams::ParagraphIndentSeparation;
1645         else
1646                 params.paragraph_separation = BufferParams::ParagraphSkipSeparation;
1647
1648         switch (textLayoutModule->skipCO->currentIndex()) {
1649         case 0:
1650                 params.setDefSkip(VSpace(VSpace::SMALLSKIP));
1651                 break;
1652         case 1:
1653                 params.setDefSkip(VSpace(VSpace::MEDSKIP));
1654                 break;
1655         case 2:
1656                 params.setDefSkip(VSpace(VSpace::BIGSKIP));
1657                 break;
1658         case 3:
1659         {
1660                 VSpace vs = VSpace(
1661                         widgetsToLength(textLayoutModule->skipLE,
1662                                 textLayoutModule->skipLengthCO)
1663                         );
1664                 params.setDefSkip(vs);
1665                 break;
1666         }
1667         default:
1668                 // DocumentDefskipCB assures that this never happens
1669                 // so Assert then !!!  - jbl
1670                 params.setDefSkip(VSpace(VSpace::MEDSKIP));
1671                 break;
1672         }
1673
1674         params.options =
1675                 fromqstr(latexModule->optionsLE->text());
1676
1677         if (latexModule->childDocGB->isChecked())
1678                 params.master =
1679                         fromqstr(latexModule->childDocLE->text());
1680         else
1681                 params.master = string();
1682
1683         params.float_placement = floatModule->get();
1684
1685         // fonts
1686         params.fontsRoman =
1687                 tex_fonts_roman[fontModule->fontsRomanCO->currentIndex()];
1688
1689         params.fontsSans =
1690                 tex_fonts_sans[fontModule->fontsSansCO->currentIndex()];
1691
1692         params.fontsTypewriter =
1693                 tex_fonts_monospaced[fontModule->fontsTypewriterCO->currentIndex()];
1694
1695         params.fontsCJK =
1696                 fromqstr(fontModule->cjkFontLE->text());
1697
1698         params.fontsSansScale = fontModule->scaleSansSB->value();
1699
1700         params.fontsTypewriterScale = fontModule->scaleTypewriterSB->value();
1701
1702         params.fontsSC = fontModule->fontScCB->isChecked();
1703
1704         params.fontsOSF = fontModule->fontOsfCB->isChecked();
1705
1706         params.fontsDefaultFamily = GuiDocument::fontfamilies[
1707                 fontModule->fontsDefaultCO->currentIndex()];
1708
1709         if (fontModule->fontsizeCO->currentIndex() == 0)
1710                 params.fontsize = "default";
1711         else
1712                 params.fontsize =
1713                         fromqstr(fontModule->fontsizeCO->currentText());
1714
1715         // paper
1716         params.papersize = PAPER_SIZE(
1717                 pageLayoutModule->papersizeCO->currentIndex());
1718
1719         // custom, A3, B3 and B4 paper sizes need geometry
1720         int psize = pageLayoutModule->papersizeCO->currentIndex();
1721         bool geom_papersize = (psize == 1 || psize == 5 || psize == 8 || psize == 9);
1722
1723         params.paperwidth = widgetsToLength(pageLayoutModule->paperwidthLE,
1724                 pageLayoutModule->paperwidthUnitCO);
1725
1726         params.paperheight = widgetsToLength(pageLayoutModule->paperheightLE,
1727                 pageLayoutModule->paperheightUnitCO);
1728
1729         if (pageLayoutModule->facingPagesCB->isChecked())
1730                 params.sides = TwoSides;
1731         else
1732                 params.sides = OneSide;
1733
1734         if (pageLayoutModule->landscapeRB->isChecked())
1735                 params.orientation = ORIENTATION_LANDSCAPE;
1736         else
1737                 params.orientation = ORIENTATION_PORTRAIT;
1738
1739         // margins
1740         params.use_geometry = !marginsModule->marginCB->isChecked()
1741                 || geom_papersize;
1742
1743         Ui::MarginsUi const * m = marginsModule;
1744
1745         params.leftmargin = widgetsToLength(m->innerLE, m->innerUnit);
1746         params.topmargin = widgetsToLength(m->topLE, m->topUnit);
1747         params.rightmargin = widgetsToLength(m->outerLE, m->outerUnit);
1748         params.bottommargin = widgetsToLength(m->bottomLE, m->bottomUnit);
1749         params.headheight = widgetsToLength(m->headheightLE, m->headheightUnit);
1750         params.headsep = widgetsToLength(m->headsepLE, m->headsepUnit);
1751         params.footskip = widgetsToLength(m->footskipLE, m->footskipUnit);
1752         params.columnsep = widgetsToLength(m->columnsepLE, m->columnsepUnit);
1753
1754         branchesModule->apply(params);
1755
1756         // PDF support
1757         PDFOptions & pdf = params.pdfoptions();
1758         pdf.use_hyperref = pdfSupportModule->use_hyperrefGB->isChecked();
1759         pdf.title = fromqstr(pdfSupportModule->titleLE->text());
1760         pdf.author = fromqstr(pdfSupportModule->authorLE->text());
1761         pdf.subject = fromqstr(pdfSupportModule->subjectLE->text());
1762         pdf.keywords = fromqstr(pdfSupportModule->keywordsLE->text());
1763
1764         pdf.bookmarks = pdfSupportModule->bookmarksGB->isChecked();
1765         pdf.bookmarksnumbered = pdfSupportModule->bookmarksnumberedCB->isChecked();
1766         pdf.bookmarksopen = pdfSupportModule->bookmarksopenGB->isChecked();
1767         pdf.bookmarksopenlevel = pdfSupportModule->bookmarksopenlevelSB->value();
1768
1769         pdf.breaklinks = pdfSupportModule->breaklinksCB->isChecked();
1770         pdf.pdfborder = pdfSupportModule->pdfborderCB->isChecked();
1771         pdf.pdfusetitle = pdfSupportModule->pdfusetitleCB->isChecked();
1772         pdf.colorlinks = pdfSupportModule->colorlinksCB->isChecked();
1773         pdf.backref = pdfSupportModule->backrefCB->isChecked();
1774         pdf.pagebackref = pdfSupportModule->pagebackrefCB->isChecked();
1775         if (pdfSupportModule->fullscreenCB->isChecked())
1776                 pdf.pagemode = pdf.pagemode_fullscreen;
1777         else
1778                 pdf.pagemode.clear();
1779         pdf.quoted_options = pdf.quoted_options_check(
1780                                 fromqstr(pdfSupportModule->optionsLE->text()));
1781 }
1782
1783
1784 void GuiDocument::paramsToDialog(BufferParams const & params)
1785 {
1786         // set the default unit
1787         Length::UNIT defaultUnit = Length::CM;
1788         switch (lyxrc.default_papersize) {
1789                 case PAPER_DEFAULT: break;
1790
1791                 case PAPER_USLETTER:
1792                 case PAPER_USLEGAL:
1793                 case PAPER_USEXECUTIVE:
1794                         defaultUnit = Length::IN;
1795                         break;
1796
1797                 case PAPER_A3:
1798                 case PAPER_A4:
1799                 case PAPER_A5:
1800                 case PAPER_B3:
1801                 case PAPER_B4:
1802                 case PAPER_B5:
1803                         defaultUnit = Length::CM;
1804                         break;
1805                 case PAPER_CUSTOM:
1806                         break;
1807         }
1808
1809         // preamble
1810         preambleModule->update(params, id());
1811
1812         // biblio
1813         biblioModule->citeDefaultRB->setChecked(
1814                 params.citeEngine() == ENGINE_BASIC);
1815
1816         biblioModule->citeNatbibRB->setChecked(
1817                 params.citeEngine() == ENGINE_NATBIB_NUMERICAL ||
1818                 params.citeEngine() == ENGINE_NATBIB_AUTHORYEAR);
1819
1820         biblioModule->citeStyleCO->setCurrentIndex(
1821                 params.citeEngine() == ENGINE_NATBIB_NUMERICAL);
1822
1823         biblioModule->citeJurabibRB->setChecked(
1824                 params.citeEngine() == ENGINE_JURABIB);
1825
1826         biblioModule->bibtopicCB->setChecked(
1827                 params.use_bibtopic);
1828
1829         // language & quotes
1830         int const pos = langModule->languageCO->findData(toqstr(
1831                 params.language->lang()));
1832         langModule->languageCO->setCurrentIndex(pos);
1833
1834         langModule->quoteStyleCO->setCurrentIndex(
1835                 params.quotes_language);
1836
1837         bool default_enc = true;
1838         if (params.inputenc != "auto") {
1839                 default_enc = false;
1840                 if (params.inputenc == "default") {
1841                         langModule->encodingCO->setCurrentIndex(0);
1842                 } else {
1843                         string enc_gui;
1844                         Encodings::const_iterator it = encodings.begin();
1845                         Encodings::const_iterator const end = encodings.end();
1846                         for (; it != end; ++it) {
1847                                 if (it->latexName() == params.inputenc) {
1848                                         enc_gui = it->guiName();
1849                                         break;
1850                                 }
1851                         }
1852                         int const i = langModule->encodingCO->findText(
1853                                         qt_(enc_gui));
1854                         if (i >= 0)
1855                                 langModule->encodingCO->setCurrentIndex(i);
1856                         else
1857                                 // unknown encoding. Set to default.
1858                                 default_enc = true;
1859                 }
1860         }
1861         langModule->defaultencodingRB->setChecked(default_enc);
1862         langModule->otherencodingRB->setChecked(!default_enc);
1863
1864         // numbering
1865         int const min_toclevel = documentClass().min_toclevel();
1866         int const max_toclevel = documentClass().max_toclevel();
1867         if (documentClass().hasTocLevels()) {
1868                 numberingModule->setEnabled(true);
1869                 numberingModule->depthSL->setMinimum(min_toclevel - 1);
1870                 numberingModule->depthSL->setMaximum(max_toclevel);
1871                 numberingModule->depthSL->setValue(params.secnumdepth);
1872                 numberingModule->tocSL->setMaximum(min_toclevel - 1);
1873                 numberingModule->tocSL->setMaximum(max_toclevel);
1874                 numberingModule->tocSL->setValue(params.tocdepth);
1875                 updateNumbering();
1876         } else {
1877                 numberingModule->setEnabled(false);
1878                 numberingModule->tocTW->clear();
1879         }
1880
1881         // bullets
1882         bulletsModule->setBullet(0, params.user_defined_bullet(0));
1883         bulletsModule->setBullet(1, params.user_defined_bullet(1));
1884         bulletsModule->setBullet(2, params.user_defined_bullet(2));
1885         bulletsModule->setBullet(3, params.user_defined_bullet(3));
1886         bulletsModule->init();
1887
1888         // packages
1889         int nitem = findToken(tex_graphics, params.graphicsDriver);
1890         if (nitem >= 0)
1891                 latexModule->psdriverCO->setCurrentIndex(nitem);
1892         updateModuleInfo();
1893         
1894         mathsModule->amsCB->setChecked(
1895                 params.use_amsmath == BufferParams::package_on);
1896         mathsModule->amsautoCB->setChecked(
1897                 params.use_amsmath == BufferParams::package_auto);
1898
1899         mathsModule->esintCB->setChecked(
1900                 params.use_esint == BufferParams::package_on);
1901         mathsModule->esintautoCB->setChecked(
1902                 params.use_esint == BufferParams::package_auto);
1903
1904         switch (params.spacing().getSpace()) {
1905                 case Spacing::Other: nitem = 3; break;
1906                 case Spacing::Double: nitem = 2; break;
1907                 case Spacing::Onehalf: nitem = 1; break;
1908                 case Spacing::Default: case Spacing::Single: nitem = 0; break;
1909         }
1910
1911         // text layout
1912         string const & layoutID = params.baseClassID();
1913         setLayoutComboByIDString(layoutID);
1914
1915         updatePagestyle(documentClass().opt_pagestyle(),
1916                                  params.pagestyle);
1917
1918         textLayoutModule->lspacingCO->setCurrentIndex(nitem);
1919         if (params.spacing().getSpace() == Spacing::Other) {
1920                 textLayoutModule->lspacingLE->setText(
1921                         toqstr(params.spacing().getValueAsString()));
1922         }
1923         setLSpacing(nitem);
1924
1925         if (params.paragraph_separation == BufferParams::ParagraphIndentSeparation)
1926                 textLayoutModule->indentRB->setChecked(true);
1927         else
1928                 textLayoutModule->skipRB->setChecked(true);
1929
1930         int skip = 0;
1931         switch (params.getDefSkip().kind()) {
1932         case VSpace::SMALLSKIP:
1933                 skip = 0;
1934                 break;
1935         case VSpace::MEDSKIP:
1936                 skip = 1;
1937                 break;
1938         case VSpace::BIGSKIP:
1939                 skip = 2;
1940                 break;
1941         case VSpace::LENGTH:
1942         {
1943                 skip = 3;
1944                 string const length = params.getDefSkip().asLyXCommand();
1945                 lengthToWidgets(textLayoutModule->skipLE,
1946                         textLayoutModule->skipLengthCO,
1947                         length, defaultUnit);
1948                 break;
1949         }
1950         default:
1951                 skip = 0;
1952                 break;
1953         }
1954         textLayoutModule->skipCO->setCurrentIndex(skip);
1955         setSkip(skip);
1956
1957         textLayoutModule->twoColumnCB->setChecked(
1958                 params.columns == 2);
1959
1960         // break listings_params to multiple lines
1961         string lstparams =
1962                 InsetListingsParams(params.listings_params).separatedParams();
1963         textLayoutModule->listingsED->setPlainText(toqstr(lstparams));
1964
1965         if (!params.options.empty()) {
1966                 latexModule->optionsLE->setText(
1967                         toqstr(params.options));
1968         } else {
1969                 latexModule->optionsLE->setText(QString());
1970         }
1971
1972         if (!params.master.empty()) {
1973                 latexModule->childDocGB->setChecked(true);
1974                 latexModule->childDocLE->setText(
1975                         toqstr(params.master));
1976         } else {
1977                 latexModule->childDocLE->setText(QString());
1978                 latexModule->childDocGB->setChecked(false);
1979         }
1980
1981         floatModule->set(params.float_placement);
1982
1983         // Fonts
1984         updateFontsize(documentClass().opt_fontsize(),
1985                         params.fontsize);
1986
1987         int n = findToken(tex_fonts_roman, params.fontsRoman);
1988         if (n >= 0) {
1989                 fontModule->fontsRomanCO->setCurrentIndex(n);
1990                 romanChanged(n);
1991         }
1992
1993         n = findToken(tex_fonts_sans, params.fontsSans);
1994         if (n >= 0)     {
1995                 fontModule->fontsSansCO->setCurrentIndex(n);
1996                 sansChanged(n);
1997         }
1998
1999         n = findToken(tex_fonts_monospaced, params.fontsTypewriter);
2000         if (n >= 0) {
2001                 fontModule->fontsTypewriterCO->setCurrentIndex(n);
2002                 ttChanged(n);
2003         }
2004
2005         if (!params.fontsCJK.empty())
2006                 fontModule->cjkFontLE->setText(
2007                         toqstr(params.fontsCJK));
2008         else
2009                 fontModule->cjkFontLE->setText(QString());
2010
2011         fontModule->fontScCB->setChecked(params.fontsSC);
2012         fontModule->fontOsfCB->setChecked(params.fontsOSF);
2013         fontModule->scaleSansSB->setValue(params.fontsSansScale);
2014         fontModule->scaleTypewriterSB->setValue(params.fontsTypewriterScale);
2015         n = findToken(GuiDocument::fontfamilies, params.fontsDefaultFamily);
2016         if (n >= 0)
2017                 fontModule->fontsDefaultCO->setCurrentIndex(n);
2018
2019         // paper
2020         int const psize = params.papersize;
2021         pageLayoutModule->papersizeCO->setCurrentIndex(psize);
2022         setCustomPapersize(psize);
2023
2024         bool const landscape =
2025                 params.orientation == ORIENTATION_LANDSCAPE;
2026         pageLayoutModule->landscapeRB->setChecked(landscape);
2027         pageLayoutModule->portraitRB->setChecked(!landscape);
2028
2029         pageLayoutModule->facingPagesCB->setChecked(
2030                 params.sides == TwoSides);
2031
2032
2033         lengthToWidgets(pageLayoutModule->paperwidthLE,
2034                 pageLayoutModule->paperwidthUnitCO, params.paperwidth, defaultUnit);
2035
2036         lengthToWidgets(pageLayoutModule->paperheightLE,
2037                 pageLayoutModule->paperheightUnitCO, params.paperheight, defaultUnit);
2038
2039         // margins
2040         Ui::MarginsUi * m = marginsModule;
2041
2042         setMargins(!params.use_geometry);
2043
2044         lengthToWidgets(m->topLE, m->topUnit,
2045                 params.topmargin, defaultUnit);
2046
2047         lengthToWidgets(m->bottomLE, m->bottomUnit,
2048                 params.bottommargin, defaultUnit);
2049
2050         lengthToWidgets(m->innerLE, m->innerUnit,
2051                 params.leftmargin, defaultUnit);
2052
2053         lengthToWidgets(m->outerLE, m->outerUnit,
2054                 params.rightmargin, defaultUnit);
2055
2056         lengthToWidgets(m->headheightLE, m->headheightUnit,
2057                 params.headheight, defaultUnit);
2058
2059         lengthToWidgets(m->headsepLE, m->headsepUnit,
2060                 params.headsep, defaultUnit);
2061
2062         lengthToWidgets(m->footskipLE, m->footskipUnit,
2063                 params.footskip, defaultUnit);
2064
2065         lengthToWidgets(m->columnsepLE, m->columnsepUnit,
2066                 params.columnsep, defaultUnit);
2067
2068         branchesModule->update(params);
2069
2070         // PDF support
2071         PDFOptions const & pdf = params.pdfoptions();
2072         pdfSupportModule->use_hyperrefGB->setChecked(pdf.use_hyperref);
2073         pdfSupportModule->titleLE->setText(toqstr(pdf.title));
2074         pdfSupportModule->authorLE->setText(toqstr(pdf.author));
2075         pdfSupportModule->subjectLE->setText(toqstr(pdf.subject));
2076         pdfSupportModule->keywordsLE->setText(toqstr(pdf.keywords));
2077
2078         pdfSupportModule->bookmarksGB->setChecked(pdf.bookmarks);
2079         pdfSupportModule->bookmarksnumberedCB->setChecked(pdf.bookmarksnumbered);
2080         pdfSupportModule->bookmarksopenGB->setChecked(pdf.bookmarksopen);
2081
2082         pdfSupportModule->bookmarksopenlevelSB->setValue(pdf.bookmarksopenlevel);
2083
2084         pdfSupportModule->breaklinksCB->setChecked(pdf.breaklinks);
2085         pdfSupportModule->pdfborderCB->setChecked(pdf.pdfborder);
2086         pdfSupportModule->pdfusetitleCB->setChecked(pdf.pdfusetitle);
2087         pdfSupportModule->colorlinksCB->setChecked(pdf.colorlinks);
2088         pdfSupportModule->backrefCB->setChecked(pdf.backref);
2089         pdfSupportModule->pagebackrefCB->setChecked(pdf.pagebackref);
2090         pdfSupportModule->fullscreenCB->setChecked
2091                 (pdf.pagemode == pdf.pagemode_fullscreen);
2092
2093         pdfSupportModule->optionsLE->setText(
2094                 toqstr(pdf.quoted_options));
2095 }
2096
2097
2098 void GuiDocument::applyView()
2099 {
2100         apply(params());
2101 }
2102
2103
2104 void GuiDocument::saveDocDefault()
2105 {
2106         // we have to apply the params first
2107         applyView();
2108         saveAsDefault();
2109 }
2110
2111
2112 void GuiDocument::updateAvailableModules() 
2113 {
2114         modules_av_model_.clear();
2115         vector<modInfoStruct> const & modInfoList = getModuleInfo();
2116         int const mSize = modInfoList.size();
2117         for (int i = 0; i != mSize; ++i) {
2118                 modInfoStruct const & modInfo = modInfoList[i];
2119                 modules_av_model_.insertRow(i, modInfo.name, modInfo.id, 
2120                                 modInfo.description);
2121         }
2122 }
2123
2124
2125 void GuiDocument::updateSelectedModules() 
2126 {
2127         // and selected ones, too
2128         modules_sel_model_.clear();
2129         vector<modInfoStruct> const selModList = getSelectedModules();
2130         int const sSize = selModList.size();
2131         for (int i = 0; i != sSize; ++i) {
2132                 modInfoStruct const & modInfo = selModList[i];
2133                 modules_sel_model_.insertRow(i, modInfo.name, modInfo.id,
2134                                 modInfo.description);
2135         }
2136 }
2137
2138
2139 void GuiDocument::updateContents()
2140 {
2141         // Nothing to do here as the document settings is not cursor dependant.
2142         return;
2143 }
2144
2145
2146 void GuiDocument::useClassDefaults()
2147 {
2148         if (applyPB->isEnabled()) {
2149                 int const ret = Alert::prompt(_("Unapplied changes"),
2150                                 _("Some changes in the dialog were not yet applied.\n"
2151                                   "If you do not apply now, they will be lost after this action."),
2152                                 1, 1, _("&Apply"), _("&Dismiss"));
2153                 if (ret == 0)
2154                         applyView();
2155         }
2156
2157         int idx = latexModule->classCO->currentIndex();
2158         string const classname = classes_model_.getIDString(idx);
2159         if (!bp_.setBaseClass(classname)) {
2160                 Alert::error(_("Error"), _("Unable to set document class."));
2161                 return;
2162         }
2163         bp_.useClassDefaults();
2164         paramsToDialog(bp_);
2165 }
2166
2167
2168 void GuiDocument::setLayoutComboByIDString(std::string const & idString)
2169 {
2170         int idx = classes_model_.findIDString(idString);
2171         if (idx < 0)
2172                 Alert::warning(_("Can't set layout!"), 
2173                         bformat(_("Unable to set layout for ID: %1$s"), from_utf8(idString)));
2174         else 
2175                 latexModule->classCO->setCurrentIndex(idx);
2176 }
2177
2178
2179 bool GuiDocument::isValid()
2180 {
2181         return validate_listings_params().empty()
2182                 && (textLayoutModule->skipCO->currentIndex() != 3
2183                         || !textLayoutModule->skipLE->text().isEmpty());
2184 }
2185
2186
2187 char const * const GuiDocument::fontfamilies[5] = {
2188         "default", "rmdefault", "sfdefault", "ttdefault", ""
2189 };
2190
2191
2192 char const * GuiDocument::fontfamilies_gui[5] = {
2193         N_("Default"), N_("Roman"), N_("Sans Serif"), N_("Typewriter"), ""
2194 };
2195
2196
2197 bool GuiDocument::initialiseParams(string const &)
2198 {
2199         BufferView * view = bufferview();
2200         if (!view) {
2201                 bp_ = BufferParams();
2202                 paramsToDialog(bp_);
2203                 return true;
2204         }
2205         bp_ = view->buffer().params();
2206         loadModuleInfo();
2207         updateAvailableModules();
2208         updateSelectedModules();
2209         //FIXME It'd be nice to make sure here that the selected
2210         //modules are consistent: That required modules are actually
2211         //selected, and that we don't have conflicts. If so, we could
2212         //at least pop up a warning.
2213         paramsToDialog(bp_);
2214         return true;
2215 }
2216
2217
2218 void GuiDocument::clearParams()
2219 {
2220         bp_ = BufferParams();
2221 }
2222
2223
2224 BufferId GuiDocument::id() const
2225 {
2226         BufferView const * const view = bufferview();
2227         return view? &view->buffer() : 0;
2228 }
2229
2230
2231 vector<GuiDocument::modInfoStruct> const & GuiDocument::getModuleInfo()
2232 {
2233         return moduleNames_;
2234 }
2235
2236
2237 vector<GuiDocument::modInfoStruct> const GuiDocument::getSelectedModules()
2238 {
2239         vector<string> const & mods = params().getModules();
2240         vector<string>::const_iterator it =  mods.begin();
2241         vector<string>::const_iterator end = mods.end();
2242         vector<modInfoStruct> mInfo;
2243         for (; it != end; ++it) {
2244                 modInfoStruct m;
2245                 m.id = *it;
2246                 LyXModule * mod = moduleList[*it];
2247                 if (mod)
2248                         m.name = qt_(mod->getName());
2249                 else 
2250                         m.name = toqstr(*it) + toqstr(" (") + qt_("Not Found") + toqstr(")");
2251                 mInfo.push_back(m);
2252         }
2253         return mInfo;
2254 }
2255
2256
2257 DocumentClass const & GuiDocument::documentClass() const
2258 {
2259         return bp_.documentClass();
2260 }
2261
2262
2263 static void dispatch_bufferparams(Dialog const & dialog,
2264         BufferParams const & bp, FuncCode lfun)
2265 {
2266         ostringstream ss;
2267         ss << "\\begin_header\n";
2268         bp.writeFile(ss);
2269         ss << "\\end_header\n";
2270         dialog.dispatch(FuncRequest(lfun, ss.str()));
2271 }
2272
2273
2274 void GuiDocument::dispatchParams()
2275 {
2276         // This must come first so that a language change is correctly noticed
2277         setLanguage();
2278
2279         // Apply the BufferParams. Note that this will set the base class
2280         // and then update the buffer's layout.
2281         dispatch_bufferparams(*this, params(), LFUN_BUFFER_PARAMS_APPLY);
2282
2283         if (!params().master.empty()) {
2284                 FileName const master_file = support::makeAbsPath(params().master,
2285                            support::onlyPath(buffer().absFileName()));
2286                 if (isLyXFilename(master_file.absFilename())) {
2287                         Buffer * master = checkAndLoadLyXFile(master_file);
2288                         buffer().setParent(master);
2289                 }
2290         }
2291
2292         // Generate the colours requested by each new branch.
2293         BranchList & branchlist = params().branchlist();
2294         if (!branchlist.empty()) {
2295                 BranchList::const_iterator it = branchlist.begin();
2296                 BranchList::const_iterator const end = branchlist.end();
2297                 for (; it != end; ++it) {
2298                         docstring const & current_branch = it->getBranch();
2299                         Branch const * branch = branchlist.find(current_branch);
2300                         string const x11hexname = X11hexname(branch->getColor());
2301                         // display the new color
2302                         docstring const str = current_branch + ' ' + from_ascii(x11hexname);
2303                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
2304                 }
2305
2306                 // Open insets of selected branches, close deselected ones
2307                 dispatch(FuncRequest(LFUN_ALL_INSETS_TOGGLE,
2308                         "assign branch"));
2309         }
2310         // FIXME: If we used an LFUN, we would not need those two lines:
2311         bufferview()->processUpdateFlags(Update::Force | Update::FitCursor);
2312 }
2313
2314
2315 void GuiDocument::setLanguage() const
2316 {
2317         Language const * const newL = bp_.language;
2318         if (buffer().params().language == newL)
2319                 return;
2320
2321         string const & lang_name = newL->lang();
2322         dispatch(FuncRequest(LFUN_BUFFER_LANGUAGE, lang_name));
2323 }
2324
2325
2326 void GuiDocument::saveAsDefault() const
2327 {
2328         dispatch_bufferparams(*this, params(), LFUN_BUFFER_SAVE_AS_DEFAULT);
2329 }
2330
2331
2332 bool GuiDocument::isFontAvailable(string const & font) const
2333 {
2334         if (font == "default" || font == "cmr"
2335             || font == "cmss" || font == "cmtt")
2336                 // these are standard
2337                 return true;
2338         if (font == "lmodern" || font == "lmss" || font == "lmtt")
2339                 return LaTeXFeatures::isAvailable("lmodern");
2340         if (font == "times" || font == "palatino"
2341                  || font == "helvet" || font == "courier")
2342                 return LaTeXFeatures::isAvailable("psnfss");
2343         if (font == "cmbr" || font == "cmtl")
2344                 return LaTeXFeatures::isAvailable("cmbright");
2345         if (font == "utopia")
2346                 return LaTeXFeatures::isAvailable("utopia")
2347                         || LaTeXFeatures::isAvailable("fourier");
2348         if (font == "beraserif" || font == "berasans"
2349                 || font == "beramono")
2350                 return LaTeXFeatures::isAvailable("bera");
2351         return LaTeXFeatures::isAvailable(font);
2352 }
2353
2354
2355 bool GuiDocument::providesOSF(string const & font) const
2356 {
2357         if (font == "cmr")
2358                 return isFontAvailable("eco");
2359         if (font == "palatino")
2360                 return isFontAvailable("mathpazo");
2361         return false;
2362 }
2363
2364
2365 bool GuiDocument::providesSC(string const & font) const
2366 {
2367         if (font == "palatino")
2368                 return isFontAvailable("mathpazo");
2369         if (font == "utopia")
2370                 return isFontAvailable("fourier");
2371         return false;
2372 }
2373
2374
2375 bool GuiDocument::providesScale(string const & font) const
2376 {
2377         return font == "helvet" || font == "luximono"
2378                 || font == "berasans"  || font == "beramono";
2379 }
2380
2381
2382 void GuiDocument::loadModuleInfo()
2383 {
2384         moduleNames_.clear();
2385         LyXModuleList::const_iterator it  = moduleList.begin();
2386         LyXModuleList::const_iterator end = moduleList.end();
2387         for (; it != end; ++it) {
2388                 modInfoStruct m;
2389                 m.id = it->getID();
2390                 m.name = qt_(it->getName());
2391                 // this is supposed to give us the first sentence of the description
2392                 QString desc = qt_(it->getDescription());
2393                 int const pos = desc.indexOf(".");
2394                 if (pos > 0)
2395                         desc.truncate(pos + 1);
2396                 m.description = desc;
2397                 moduleNames_.push_back(m);
2398         }
2399 }
2400
2401
2402 Dialog * createGuiDocument(GuiView & lv) { return new GuiDocument(lv); }
2403
2404
2405 } // namespace frontend
2406 } // namespace lyx
2407
2408 #include "GuiDocument_moc.cpp"