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