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