]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiDocument.cpp
Revert 23154.
[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->twoColumnCB, SIGNAL(clicked()),
540                 this, SLOT(setColSep()));
541         connect(textLayoutModule->listingsED, SIGNAL(textChanged()),
542                 this, SLOT(change_adaptor()));
543         connect(textLayoutModule->bypassCB, SIGNAL(clicked()), 
544                 this, SLOT(change_adaptor()));
545         connect(textLayoutModule->bypassCB, SIGNAL(clicked()), 
546                 this, SLOT(set_listings_msg()));
547         connect(textLayoutModule->listingsED, SIGNAL(textChanged()),
548                 this, SLOT(set_listings_msg()));
549         textLayoutModule->listingsTB->setPlainText(
550                 qt_("Input listings parameters on the right. Enter ? for a list of parameters."));
551         textLayoutModule->lspacingLE->setValidator(new QDoubleValidator(
552                 textLayoutModule->lspacingLE));
553         textLayoutModule->skipLE->setValidator(unsignedLengthValidator(
554                 textLayoutModule->skipLE));
555
556         textLayoutModule->skipCO->addItem(qt_("SmallSkip"));
557         textLayoutModule->skipCO->addItem(qt_("MedSkip"));
558         textLayoutModule->skipCO->addItem(qt_("BigSkip"));
559         textLayoutModule->skipCO->addItem(qt_("Length"));
560         // remove the %-items from the unit choice
561         textLayoutModule->skipLengthCO->noPercents();
562         textLayoutModule->lspacingCO->insertItem(
563                 Spacing::Single, qt_("Single"));
564         textLayoutModule->lspacingCO->insertItem(
565                 Spacing::Onehalf, qt_("OneHalf"));
566         textLayoutModule->lspacingCO->insertItem(
567                 Spacing::Double, qt_("Double"));
568         textLayoutModule->lspacingCO->insertItem(
569                 Spacing::Other, qt_("Custom"));
570
571         // initialize the length validator
572         bc().addCheckedLineEdit(textLayoutModule->skipLE);
573
574         fontModule = new UiWidget<Ui::FontUi>;
575         // fonts
576         connect(fontModule->fontsRomanCO, SIGNAL(activated(int)),
577                 this, SLOT(change_adaptor()));
578         connect(fontModule->fontsRomanCO, SIGNAL(activated(int)),
579                 this, SLOT(romanChanged(int)));
580         connect(fontModule->fontsSansCO, SIGNAL(activated(int)),
581                 this, SLOT(change_adaptor()));
582         connect(fontModule->fontsSansCO, SIGNAL(activated(int)),
583                 this, SLOT(sansChanged(int)));
584         connect(fontModule->fontsTypewriterCO, SIGNAL(activated(int)),
585                 this, SLOT(change_adaptor()));
586         connect(fontModule->fontsTypewriterCO, SIGNAL(activated(int)),
587                 this, SLOT(ttChanged(int)));
588         connect(fontModule->fontsDefaultCO, SIGNAL(activated(int)),
589                 this, SLOT(change_adaptor()));
590         connect(fontModule->fontsizeCO, SIGNAL(activated(int)),
591                 this, SLOT(change_adaptor()));
592         connect(fontModule->scaleSansSB, SIGNAL(valueChanged(int)),
593                 this, SLOT(change_adaptor()));
594         connect(fontModule->scaleTypewriterSB, SIGNAL(valueChanged(int)),
595                 this, SLOT(change_adaptor()));
596         connect(fontModule->fontScCB, SIGNAL(clicked()),
597                 this, SLOT(change_adaptor()));
598         connect(fontModule->fontOsfCB, SIGNAL(clicked()),
599                 this, SLOT(change_adaptor()));
600
601         for (int n = 0; tex_fonts_roman[n][0]; ++n) {
602                 QString font = qt_(tex_fonts_roman_gui[n]);
603                 if (!isFontAvailable(tex_fonts_roman[n]))
604                         font += qt_(" (not installed)");
605                 fontModule->fontsRomanCO->addItem(font);
606         }
607         for (int n = 0; tex_fonts_sans[n][0]; ++n) {
608                 QString font = qt_(tex_fonts_sans_gui[n]);
609                 if (!isFontAvailable(tex_fonts_sans[n]))
610                         font += qt_(" (not installed)");
611                 fontModule->fontsSansCO->addItem(font);
612         }
613         for (int n = 0; tex_fonts_monospaced[n][0]; ++n) {
614                 QString font = qt_(tex_fonts_monospaced_gui[n]);
615                 if (!isFontAvailable(tex_fonts_monospaced[n]))
616                         font += qt_(" (not installed)");
617                 fontModule->fontsTypewriterCO->addItem(font);
618         }
619
620         fontModule->fontsizeCO->addItem(qt_("Default"));
621         fontModule->fontsizeCO->addItem(qt_("10"));
622         fontModule->fontsizeCO->addItem(qt_("11"));
623         fontModule->fontsizeCO->addItem(qt_("12"));
624
625         for (int n = 0; GuiDocument::fontfamilies_gui[n][0]; ++n)
626                 fontModule->fontsDefaultCO->addItem(
627                         qt_(GuiDocument::fontfamilies_gui[n]));
628
629
630         pageLayoutModule = new UiWidget<Ui::PageLayoutUi>;
631         // page layout
632         connect(pageLayoutModule->papersizeCO, SIGNAL(activated(int)),
633                 this, SLOT(setCustomPapersize(int)));
634         connect(pageLayoutModule->papersizeCO, SIGNAL(activated(int)),
635                 this, SLOT(setCustomPapersize(int)));
636         connect(pageLayoutModule->portraitRB, SIGNAL(clicked()),
637                 this, SLOT(portraitChanged()));
638         connect(pageLayoutModule->papersizeCO, SIGNAL(activated(int)),
639                 this, SLOT(change_adaptor()));
640         connect(pageLayoutModule->paperheightLE, SIGNAL(textChanged(const QString &)),
641                 this, SLOT(change_adaptor()));
642         connect(pageLayoutModule->paperwidthLE, SIGNAL(textChanged(const QString &)),
643                 this, SLOT(change_adaptor()));
644         connect(pageLayoutModule->paperwidthUnitCO, SIGNAL(activated(int)),
645                 this, SLOT(change_adaptor()));
646         connect(pageLayoutModule->paperheightUnitCO, SIGNAL(activated(int)),
647                 this, SLOT(change_adaptor()));
648         connect(pageLayoutModule->portraitRB, SIGNAL(clicked()),
649                 this, SLOT(change_adaptor()));
650         connect(pageLayoutModule->landscapeRB, SIGNAL(clicked()),
651                 this, SLOT(change_adaptor()));
652         connect(pageLayoutModule->facingPagesCB, SIGNAL(clicked()),
653                 this, SLOT(change_adaptor()));
654         connect(pageLayoutModule->pagestyleCO, SIGNAL(activated(int)),
655                 this, SLOT(change_adaptor()));
656
657         pageLayoutModule->pagestyleCO->addItem(qt_("Default"));
658         pageLayoutModule->pagestyleCO->addItem(qt_("empty"));
659         pageLayoutModule->pagestyleCO->addItem(qt_("plain"));
660         pageLayoutModule->pagestyleCO->addItem(qt_("headings"));
661         pageLayoutModule->pagestyleCO->addItem(qt_("fancy"));
662         bc().addCheckedLineEdit(pageLayoutModule->paperheightLE,
663                 pageLayoutModule->paperheightL);
664         bc().addCheckedLineEdit(pageLayoutModule->paperwidthLE,
665                 pageLayoutModule->paperwidthL);
666
667         // paper
668         QComboBox * cb = pageLayoutModule->papersizeCO;
669         cb->addItem(qt_("Default"));
670         cb->addItem(qt_("Custom"));
671         cb->addItem(qt_("US letter"));
672         cb->addItem(qt_("US legal"));
673         cb->addItem(qt_("US executive"));
674         cb->addItem(qt_("A3"));
675         cb->addItem(qt_("A4"));
676         cb->addItem(qt_("A5"));
677         cb->addItem(qt_("B3"));
678         cb->addItem(qt_("B4"));
679         cb->addItem(qt_("B5"));
680         // remove the %-items from the unit choice
681         pageLayoutModule->paperwidthUnitCO->noPercents();
682         pageLayoutModule->paperheightUnitCO->noPercents();
683         pageLayoutModule->paperheightLE->setValidator(unsignedLengthValidator(
684                 pageLayoutModule->paperheightLE));
685         pageLayoutModule->paperwidthLE->setValidator(unsignedLengthValidator(
686                 pageLayoutModule->paperwidthLE));
687
688
689         marginsModule = new UiWidget<Ui::MarginsUi>;
690         // margins
691         connect(marginsModule->marginCB, SIGNAL(toggled(bool)),
692                 this, SLOT(setCustomMargins(bool)));
693         connect(marginsModule->marginCB, SIGNAL(clicked()),
694                 this, SLOT(change_adaptor()));
695         connect(marginsModule->topLE, SIGNAL(textChanged(const QString &)),
696                 this, SLOT(change_adaptor()));
697         connect(marginsModule->topUnit, SIGNAL(activated(int)),
698                 this, SLOT(change_adaptor()));
699         connect(marginsModule->bottomLE, SIGNAL(textChanged(const QString &)),
700                 this, SLOT(change_adaptor()));
701         connect(marginsModule->bottomUnit, SIGNAL(activated(int)),
702                 this, SLOT(change_adaptor()));
703         connect(marginsModule->innerLE, SIGNAL(textChanged(const QString &)),
704                 this, SLOT(change_adaptor()));
705         connect(marginsModule->innerUnit, SIGNAL(activated(int)),
706                 this, SLOT(change_adaptor()));
707         connect(marginsModule->outerLE, SIGNAL(textChanged(const QString &)),
708                 this, SLOT(change_adaptor()));
709         connect(marginsModule->outerUnit, SIGNAL(activated(int)),
710                 this, SLOT(change_adaptor()));
711         connect(marginsModule->headheightLE, SIGNAL(textChanged(const QString &)),
712                 this, SLOT(change_adaptor()));
713         connect(marginsModule->headheightUnit, SIGNAL(activated(int)),
714                 this, SLOT(change_adaptor()));
715         connect(marginsModule->headsepLE, SIGNAL(textChanged(const QString &)),
716                 this, SLOT(change_adaptor()));
717         connect(marginsModule->headsepUnit, SIGNAL(activated(int)),
718                 this, SLOT(change_adaptor()));
719         connect(marginsModule->footskipLE, SIGNAL(textChanged(const QString&)),
720                 this, SLOT(change_adaptor()));
721         connect(marginsModule->footskipUnit, SIGNAL(activated(int)),
722                 this, SLOT(change_adaptor()));
723         connect(marginsModule->columnsepLE, SIGNAL(textChanged(const QString&)),
724                 this, SLOT(change_adaptor()));
725         connect(marginsModule->columnsepUnit, SIGNAL(activated(int)),
726                 this, SLOT(change_adaptor()));
727         marginsModule->topLE->setValidator(unsignedLengthValidator(
728                 marginsModule->topLE));
729         marginsModule->bottomLE->setValidator(unsignedLengthValidator(
730                 marginsModule->bottomLE));
731         marginsModule->innerLE->setValidator(unsignedLengthValidator(
732                 marginsModule->innerLE));
733         marginsModule->outerLE->setValidator(unsignedLengthValidator(
734                 marginsModule->outerLE));
735         marginsModule->headsepLE->setValidator(unsignedLengthValidator(
736                 marginsModule->headsepLE));
737         marginsModule->headheightLE->setValidator(unsignedLengthValidator(
738                 marginsModule->headheightLE));
739         marginsModule->footskipLE->setValidator(unsignedLengthValidator(
740                 marginsModule->footskipLE));
741         marginsModule->columnsepLE->setValidator(unsignedLengthValidator(
742                 marginsModule->columnsepLE));
743
744         bc().addCheckedLineEdit(marginsModule->topLE,
745                 marginsModule->topL);
746         bc().addCheckedLineEdit(marginsModule->bottomLE,
747                 marginsModule->bottomL);
748         bc().addCheckedLineEdit(marginsModule->innerLE,
749                 marginsModule->innerL);
750         bc().addCheckedLineEdit(marginsModule->outerLE,
751                 marginsModule->outerL);
752         bc().addCheckedLineEdit(marginsModule->headsepLE,
753                 marginsModule->headsepL);
754         bc().addCheckedLineEdit(marginsModule->headheightLE,
755                 marginsModule->headheightL);
756         bc().addCheckedLineEdit(marginsModule->footskipLE,
757                 marginsModule->footskipL);
758         bc().addCheckedLineEdit(marginsModule->columnsepLE,
759                 marginsModule->columnsepL);
760
761
762         langModule = new UiWidget<Ui::LanguageUi>;
763         // language & quote
764         connect(langModule->languageCO, SIGNAL(activated(int)),
765                 this, SLOT(change_adaptor()));
766         connect(langModule->defaultencodingRB, SIGNAL(clicked()),
767                 this, SLOT(change_adaptor()));
768         connect(langModule->otherencodingRB, SIGNAL(clicked()),
769                 this, SLOT(change_adaptor()));
770         connect(langModule->encodingCO, SIGNAL(activated(int)),
771                 this, SLOT(change_adaptor()));
772         connect(langModule->quoteStyleCO, SIGNAL(activated(int)),
773                 this, SLOT(change_adaptor()));
774         // language & quotes
775         vector<LanguagePair> const langs = getLanguageData(false);
776         vector<LanguagePair>::const_iterator lit  = langs.begin();
777         vector<LanguagePair>::const_iterator lend = langs.end();
778         for (; lit != lend; ++lit) {
779                 langModule->languageCO->addItem(toqstr(lit->first));
780         }
781
782         // Always put the default encoding in the first position.
783         // It is special because the displayed text is translated.
784         langModule->encodingCO->addItem(qt_("LaTeX default"));
785         Encodings::const_iterator it = encodings.begin();
786         Encodings::const_iterator const end = encodings.end();
787         for (; it != end; ++it)
788                 langModule->encodingCO->addItem(toqstr(it->latexName()));
789
790         langModule->quoteStyleCO->addItem(qt_("``text''"));
791         langModule->quoteStyleCO->addItem(qt_("''text''"));
792         langModule->quoteStyleCO->addItem(qt_(",,text``"));
793         langModule->quoteStyleCO->addItem(qt_(",,text''"));
794         langModule->quoteStyleCO->addItem(qt_("<<text>>"));
795         langModule->quoteStyleCO->addItem(qt_(">>text<<"));
796
797
798
799         numberingModule = new UiWidget<Ui::NumberingUi>;
800         // numbering
801         connect(numberingModule->depthSL, SIGNAL(valueChanged(int)),
802                 this, SLOT(change_adaptor()));
803         connect(numberingModule->tocSL, SIGNAL(valueChanged(int)),
804                 this, SLOT(change_adaptor()));
805         connect(numberingModule->depthSL, SIGNAL(valueChanged(int)),
806                 this, SLOT(updateNumbering()));
807         connect(numberingModule->tocSL, SIGNAL(valueChanged(int)),
808                 this, SLOT(updateNumbering()));
809         numberingModule->tocTW->setColumnCount(3);
810         numberingModule->tocTW->headerItem()->setText(0, qt_("Example"));
811         numberingModule->tocTW->headerItem()->setText(1, qt_("Numbered"));
812         numberingModule->tocTW->headerItem()->setText(2, qt_("Appears in TOC"));
813
814
815         biblioModule = new UiWidget<Ui::BiblioUi>;
816         connect(biblioModule->citeNatbibRB, SIGNAL(toggled(bool)),
817                 biblioModule->citationStyleL, SLOT(setEnabled(bool)));
818         connect(biblioModule->citeNatbibRB, SIGNAL(toggled(bool)),
819                 biblioModule->citeStyleCO, SLOT(setEnabled(bool)));
820         // biblio
821         connect(biblioModule->citeDefaultRB, SIGNAL(clicked()),
822                 this, SLOT(change_adaptor()));
823         connect(biblioModule->citeNatbibRB, SIGNAL(clicked()),
824                 this, SLOT(change_adaptor()));
825         connect(biblioModule->citeStyleCO, SIGNAL(activated(int)),
826                 this, SLOT(change_adaptor()));
827         connect(biblioModule->citeJurabibRB, SIGNAL(clicked()),
828                 this, SLOT(change_adaptor()));
829         connect(biblioModule->bibtopicCB, SIGNAL(clicked()),
830                 this, SLOT(change_adaptor()));
831         // biblio
832         biblioModule->citeStyleCO->addItem(qt_("Author-year"));
833         biblioModule->citeStyleCO->addItem(qt_("Numerical"));
834         biblioModule->citeStyleCO->setCurrentIndex(0);
835
836
837         mathsModule = new UiWidget<Ui::MathsUi>;
838         connect(mathsModule->amsautoCB, SIGNAL(toggled(bool)),
839                 mathsModule->amsCB, SLOT(setDisabled(bool)));
840         connect(mathsModule->esintautoCB, SIGNAL(toggled(bool)),
841                 mathsModule->esintCB, SLOT(setDisabled(bool)));
842         // maths
843         connect(mathsModule->amsCB, SIGNAL(clicked()),
844                 this, SLOT(change_adaptor()));
845         connect(mathsModule->amsautoCB, SIGNAL(clicked()),
846                 this, SLOT(change_adaptor()));
847         connect(mathsModule->esintCB, SIGNAL(clicked()),
848                 this, SLOT(change_adaptor()));
849         connect(mathsModule->esintautoCB, SIGNAL(clicked()),
850                 this, SLOT(change_adaptor()));
851
852         latexModule = new UiWidget<Ui::LaTeXUi>;
853         // latex class
854         connect(latexModule->optionsLE, SIGNAL(textChanged(const QString &)),
855                 this, SLOT(change_adaptor()));
856         connect(latexModule->psdriverCO, SIGNAL(activated(int)),
857                 this, SLOT(change_adaptor()));
858         connect(latexModule->classCO, SIGNAL(activated(int)),
859                 this, SLOT(classChanged()));
860         connect(latexModule->classCO, SIGNAL(activated(int)),
861                 this, SLOT(change_adaptor()));
862         
863         selectionManager = 
864                 new ModuleSelMan(latexModule->availableLV, latexModule->selectedLV, 
865                         latexModule->addPB, latexModule->deletePB, 
866                         latexModule->upPB, latexModule->downPB, 
867                         availableModel(), selectedModel());
868         connect(selectionManager, SIGNAL(updateHook()),
869                 this, SLOT(updateModuleInfo()));
870         connect(selectionManager, SIGNAL(updateHook()),
871                 this, SLOT(change_adaptor()));
872         
873         // postscript drivers
874         for (int n = 0; tex_graphics[n][0]; ++n) {
875                 QString enc = qt_(tex_graphics_gui[n]);
876                 latexModule->psdriverCO->addItem(enc);
877         }
878         // latex classes
879         //FIXME This seems too involved with the kernel. Some of this
880         //should be moved to the kernel---which should perhaps just
881         //give us a list of entries or something of the sort.
882         for (TextClassList::const_iterator cit = textclasslist.begin();
883              cit != textclasslist.end(); ++cit) {
884                 if (cit->isTeXClassAvailable()) {
885                         latexModule->classCO->addItem(toqstr(cit->description()));
886                 } else {
887                         docstring item =
888                                 bformat(_("Unavailable: %1$s"), from_utf8(cit->description()));
889                         latexModule->classCO->addItem(toqstr(item));
890                 }
891         }
892
893         // branches
894         branchesModule = new GuiBranches;
895         connect(branchesModule, SIGNAL(changed()),
896                 this, SLOT(change_adaptor()));
897
898         // preamble
899         preambleModule = new PreambleModule;
900         connect(preambleModule, SIGNAL(changed()),
901                 this, SLOT(change_adaptor()));
902
903         // bullets
904         bulletsModule = new BulletsModule;
905         connect(bulletsModule, SIGNAL(changed()),
906                 this, SLOT(change_adaptor()));
907
908         // embedded files
909         embeddedFilesModule = new UiWidget<Ui::EmbeddedFilesUi>;
910         connect(embeddedFilesModule->bundleCB, SIGNAL(toggled(bool)),
911                 this, SLOT(change_adaptor()));
912         connect(embeddedFilesModule->addPB, SIGNAL(clicked()),
913                 this, SLOT(change_adaptor()));
914         connect(embeddedFilesModule->removePB, SIGNAL(clicked()),
915                 this, SLOT(change_adaptor()));
916
917         // PDF support
918         pdfSupportModule = new UiWidget<Ui::PDFSupportUi>;
919
920         connect(pdfSupportModule->use_hyperrefGB, SIGNAL(toggled(bool)),
921                 this, SLOT(change_adaptor()));
922         connect(pdfSupportModule->titleLE, SIGNAL(textChanged(const QString &)),
923                 this, SLOT(change_adaptor()));
924         connect(pdfSupportModule->authorLE, SIGNAL(textChanged(const QString &)),
925                 this, SLOT(change_adaptor()));
926         connect(pdfSupportModule->subjectLE, SIGNAL(textChanged(const QString &)),
927                 this, SLOT(change_adaptor()));
928         connect(pdfSupportModule->keywordsLE, SIGNAL(textChanged(const QString &)),
929                 this, SLOT(change_adaptor()));
930         connect(pdfSupportModule->bookmarksGB, SIGNAL(toggled(bool)),
931                 this, SLOT(change_adaptor()));
932         connect(pdfSupportModule->bookmarksnumberedCB, SIGNAL(toggled(bool)),
933                 this, SLOT(change_adaptor()));
934         connect(pdfSupportModule->bookmarksopenGB, SIGNAL(toggled(bool)),
935                 this, SLOT(change_adaptor()));
936         connect(pdfSupportModule->bookmarksopenlevelSB, SIGNAL(valueChanged(int)),
937                 this, SLOT(change_adaptor()));
938         connect(pdfSupportModule->breaklinksCB, SIGNAL(toggled(bool)),
939                 this, SLOT(change_adaptor()));
940         connect(pdfSupportModule->pdfborderCB, SIGNAL(toggled(bool)),
941                 this, SLOT(change_adaptor()));
942         connect(pdfSupportModule->colorlinksCB, SIGNAL(toggled(bool)),
943                 this, SLOT(change_adaptor()));
944         connect(pdfSupportModule->backrefCB, SIGNAL(toggled(bool)),
945                 this, SLOT(change_adaptor()));
946         connect(pdfSupportModule->pdfusetitleCB, SIGNAL(toggled(bool)),
947                 this, SLOT(change_adaptor()));
948         connect(pdfSupportModule->pagebackrefCB, SIGNAL(toggled(bool)),
949                 this, SLOT(change_adaptor()));
950         connect(pdfSupportModule->fullscreenCB, SIGNAL(toggled(bool)),
951                 this, SLOT(change_adaptor()));
952         connect(pdfSupportModule->optionsLE, SIGNAL(textChanged(const QString &)),
953                 this, SLOT(change_adaptor()));
954
955         // float
956         floatModule = new FloatPlacement;
957         connect(floatModule, SIGNAL(changed()),
958                 this, SLOT(change_adaptor()));
959
960         docPS->addPanel(latexModule, _("Document Class"));
961         docPS->addPanel(fontModule, _("Fonts"));
962         docPS->addPanel(textLayoutModule, _("Text Layout"));
963         docPS->addPanel(pageLayoutModule, _("Page Layout"));
964         docPS->addPanel(marginsModule, _("Page Margins"));
965         docPS->addPanel(langModule, _("Language"));
966         docPS->addPanel(numberingModule, _("Numbering & TOC"));
967         docPS->addPanel(biblioModule, _("Bibliography"));
968         docPS->addPanel(pdfSupportModule, _("PDF Properties"));
969         docPS->addPanel(mathsModule, _("Math Options"));
970         docPS->addPanel(floatModule, _("Float Placement"));
971         docPS->addPanel(bulletsModule, _("Bullets"));
972         docPS->addPanel(branchesModule, _("Branches"));
973         docPS->addPanel(embeddedFilesModule, _("Embedded Files"));
974         docPS->addPanel(preambleModule, _("LaTeX Preamble"));
975         docPS->setCurrentPanel(_("Document Class"));
976 // FIXME: hack to work around resizing bug in Qt >= 4.2
977 // bug verified with Qt 4.2.{0-3} (JSpitzm)
978 #if QT_VERSION >= 0x040200
979         docPS->updateGeometry();
980 #endif
981 }
982
983
984 void GuiDocument::showPreamble()
985 {
986         docPS->setCurrentPanel(_("LaTeX Preamble"));
987 }
988
989
990 void GuiDocument::saveDefaultClicked()
991 {
992         saveDocDefault();
993 }
994
995
996 void GuiDocument::useDefaultsClicked()
997 {
998         useClassDefaults();
999 }
1000
1001
1002 void GuiDocument::change_adaptor()
1003 {
1004         changed();
1005 }
1006
1007
1008 docstring GuiDocument::validate_listings_params()
1009 {
1010         // use a cache here to avoid repeated validation
1011         // of the same parameters
1012         static string param_cache = string();
1013         static docstring msg_cache = docstring();
1014         
1015         if (textLayoutModule->bypassCB->isChecked())
1016                 return docstring();
1017
1018         string params = fromqstr(textLayoutModule->listingsED->toPlainText());
1019         if (params != param_cache) {
1020                 param_cache = params;
1021                 msg_cache = InsetListingsParams(params).validate();
1022         }
1023         return msg_cache;
1024 }
1025
1026
1027 void GuiDocument::set_listings_msg()
1028 {
1029         static bool isOK = true;
1030         docstring msg = validate_listings_params();
1031         if (msg.empty()) {
1032                 if (isOK)
1033                         return;
1034                 isOK = true;
1035                 // listingsTB->setTextColor("black");
1036                 textLayoutModule->listingsTB->setPlainText(
1037                         qt_("Input listings parameters on the right. Enter ? for a list of parameters."));
1038         } else {
1039                 isOK = false;
1040                 // listingsTB->setTextColor("red");
1041                 textLayoutModule->listingsTB->setPlainText(toqstr(msg));
1042         }
1043 }
1044
1045
1046 void GuiDocument::setLSpacing(int item)
1047 {
1048         textLayoutModule->lspacingLE->setEnabled(item == 3);
1049 }
1050
1051
1052 void GuiDocument::setSkip(int item)
1053 {
1054         bool const enable = (item == 3);
1055         textLayoutModule->skipLE->setEnabled(enable);
1056         textLayoutModule->skipLengthCO->setEnabled(enable);
1057 }
1058
1059
1060 void GuiDocument::enableSkip(bool skip)
1061 {
1062         textLayoutModule->skipCO->setEnabled(skip);
1063         textLayoutModule->skipLE->setEnabled(skip);
1064         textLayoutModule->skipLengthCO->setEnabled(skip);
1065         if (skip)
1066                 setSkip(textLayoutModule->skipCO->currentIndex());
1067 }
1068
1069 void GuiDocument::portraitChanged()
1070 {
1071         setMargins(pageLayoutModule->papersizeCO->currentIndex());
1072 }
1073
1074 void GuiDocument::setMargins(bool custom)
1075 {
1076         marginsModule->marginCB->setChecked(custom);
1077         setCustomMargins(custom);
1078 }
1079
1080
1081 void GuiDocument::setCustomPapersize(int papersize)
1082 {
1083         bool const custom = (papersize == 1);
1084
1085         pageLayoutModule->paperwidthL->setEnabled(custom);
1086         pageLayoutModule->paperwidthLE->setEnabled(custom);
1087         pageLayoutModule->paperwidthUnitCO->setEnabled(custom);
1088         pageLayoutModule->paperheightL->setEnabled(custom);
1089         pageLayoutModule->paperheightLE->setEnabled(custom);
1090         pageLayoutModule->paperheightLE->setFocus();
1091         pageLayoutModule->paperheightUnitCO->setEnabled(custom);
1092 }
1093
1094
1095 void GuiDocument::setColSep()
1096 {
1097         setCustomMargins(marginsModule->marginCB->checkState() == Qt::Checked);
1098 }
1099
1100
1101 void GuiDocument::setCustomMargins(bool custom)
1102 {
1103         marginsModule->topL->setEnabled(!custom);
1104         marginsModule->topLE->setEnabled(!custom);
1105         marginsModule->topUnit->setEnabled(!custom);
1106
1107         marginsModule->bottomL->setEnabled(!custom);
1108         marginsModule->bottomLE->setEnabled(!custom);
1109         marginsModule->bottomUnit->setEnabled(!custom);
1110
1111         marginsModule->innerL->setEnabled(!custom);
1112         marginsModule->innerLE->setEnabled(!custom);
1113         marginsModule->innerUnit->setEnabled(!custom);
1114
1115         marginsModule->outerL->setEnabled(!custom);
1116         marginsModule->outerLE->setEnabled(!custom);
1117         marginsModule->outerUnit->setEnabled(!custom);
1118
1119         marginsModule->headheightL->setEnabled(!custom);
1120         marginsModule->headheightLE->setEnabled(!custom);
1121         marginsModule->headheightUnit->setEnabled(!custom);
1122
1123         marginsModule->headsepL->setEnabled(!custom);
1124         marginsModule->headsepLE->setEnabled(!custom);
1125         marginsModule->headsepUnit->setEnabled(!custom);
1126
1127         marginsModule->footskipL->setEnabled(!custom);
1128         marginsModule->footskipLE->setEnabled(!custom);
1129         marginsModule->footskipUnit->setEnabled(!custom);
1130
1131         bool const enableColSep = !custom && 
1132                         textLayoutModule->twoColumnCB->checkState() == Qt::Checked;
1133         marginsModule->columnsepL->setEnabled(enableColSep);
1134         marginsModule->columnsepLE->setEnabled(enableColSep);
1135         marginsModule->columnsepUnit->setEnabled(enableColSep);
1136 }
1137
1138
1139 void GuiDocument::updateFontsize(string const & items, string const & sel)
1140 {
1141         fontModule->fontsizeCO->clear();
1142         fontModule->fontsizeCO->addItem(qt_("Default"));
1143
1144         for (int n = 0; !token(items,'|',n).empty(); ++n)
1145                 fontModule->fontsizeCO->
1146                         addItem(toqstr(token(items,'|',n)));
1147
1148         for (int n = 0; n < fontModule->fontsizeCO->count(); ++n) {
1149                 if (fromqstr(fontModule->fontsizeCO->itemText(n)) == sel) {
1150                         fontModule->fontsizeCO->setCurrentIndex(n);
1151                         break;
1152                 }
1153         }
1154 }
1155
1156
1157 void GuiDocument::romanChanged(int item)
1158 {
1159         string const font = tex_fonts_roman[item];
1160         fontModule->fontScCB->setEnabled(providesSC(font));
1161         fontModule->fontOsfCB->setEnabled(providesOSF(font));
1162 }
1163
1164
1165 void GuiDocument::sansChanged(int item)
1166 {
1167         string const font = tex_fonts_sans[item];
1168         bool scaleable = providesScale(font);
1169         fontModule->scaleSansSB->setEnabled(scaleable);
1170         fontModule->scaleSansLA->setEnabled(scaleable);
1171 }
1172
1173
1174 void GuiDocument::ttChanged(int item)
1175 {
1176         string const font = tex_fonts_monospaced[item];
1177         bool scaleable = providesScale(font);
1178         fontModule->scaleTypewriterSB->setEnabled(scaleable);
1179         fontModule->scaleTypewriterLA->setEnabled(scaleable);
1180 }
1181
1182
1183 void GuiDocument::updatePagestyle(string const & items, string const & sel)
1184 {
1185         pagestyles.clear();
1186         pageLayoutModule->pagestyleCO->clear();
1187         pageLayoutModule->pagestyleCO->addItem(qt_("Default"));
1188
1189         for (int n = 0; !token(items,'|',n).empty(); ++n) {
1190                 string style = token(items, '|', n);
1191                 docstring style_gui = _(style);
1192                 pagestyles.push_back(pair<string, docstring>(style, style_gui));
1193                 pageLayoutModule->pagestyleCO->addItem(toqstr(style_gui));
1194         }
1195
1196         if (sel == "default") {
1197                 pageLayoutModule->pagestyleCO->setCurrentIndex(0);
1198                 return;
1199         }
1200
1201         int nn = 0;
1202
1203         for (size_t i = 0; i < pagestyles.size(); ++i)
1204                 if (pagestyles[i].first == sel)
1205                         nn = pageLayoutModule->pagestyleCO->findText(
1206                                         toqstr(pagestyles[i].second));
1207
1208         if (nn > 0)
1209                 pageLayoutModule->pagestyleCO->setCurrentIndex(nn);
1210 }
1211
1212
1213 void GuiDocument::classChanged()
1214 {
1215         textclass_type const tc = latexModule->classCO->currentIndex();
1216         bp_.setBaseClass(tc);
1217         if (lyxrc.auto_reset_options) {
1218                 if (applyPB->isEnabled()) {
1219                         int const ret = Alert::prompt(_("Unapplied changes"),
1220                                         _("Some changes in the dialog were not yet applied."
1221                                         "If you do not apply now, they will be lost after this action."),
1222                                         1, 1, _("&Apply"), _("&Dismiss"));
1223                         if (ret == 0)
1224                                 applyView();
1225                 }
1226                 bp_.useClassDefaults();
1227                 forceUpdate();
1228         }
1229 }
1230
1231
1232 namespace {
1233         //This is an insanely complicated attempt to make this sort of thing
1234         //work with RTL languages.
1235         docstring formatStrVec(vector<string> const & v, docstring const & s) 
1236         {
1237                 //this mess formats the list as "v[0], v[1], ..., [s] v[n]"
1238                 int const vSize = v.size();
1239                 if (v.size() == 0)
1240                         return docstring();
1241                 else if (v.size() == 1) 
1242                         return from_ascii(v[0]);
1243                 else if (v.size() == 2) {
1244                         docstring retval = _("%1$s and %2$s");
1245                         retval = subst(retval, _("and"), s);
1246                         return bformat(retval, from_ascii(v[0]), from_ascii(v[1]));
1247                 }
1248                 //The idea here is to format all but the last two items...
1249                 docstring t2 = _("%1$s, %2$s");
1250                 docstring retval = from_ascii(v[0]);
1251                 for (int i = 1; i < vSize - 2; ++i)
1252                         retval = bformat(t2, retval, from_ascii(v[i])); 
1253                 //...and then to  plug them, and the last two, into this schema
1254                 docstring t = _("%1$s, %2$s, and %3$s");
1255                 t = subst(t, _("and"), s);
1256                 return bformat(t, retval, from_ascii(v[vSize - 2]), from_ascii(v[vSize - 1]));
1257         }
1258         
1259         vector<string> idsToNames(vector<string> const & idList)
1260         {
1261                 vector<string> retval;
1262                 vector<string>::const_iterator it  = idList.begin();
1263                 vector<string>::const_iterator end = idList.end();
1264                 for (; it != end; ++it) {
1265                         LyXModule const * const mod = moduleList[*it];
1266                         if (!mod)
1267                                 retval.push_back(*it + " (Unavailable)");
1268                         else
1269                                 retval.push_back(mod->getName());
1270                 }
1271                 return retval;
1272         }
1273 }
1274
1275
1276 void GuiDocument::updateModuleInfo()
1277 {
1278         selectionManager->update();
1279         
1280         //Module description
1281         bool const focusOnSelected = selectionManager->selectedFocused();
1282         QListView const * const lv = 
1283                         focusOnSelected ? latexModule->selectedLV : latexModule->availableLV;
1284         if (lv->selectionModel()->selectedIndexes().isEmpty()) {
1285                 latexModule->infoML->document()->clear();
1286                 return;
1287         }
1288         QModelIndex const & idx = lv->selectionModel()->currentIndex();
1289         GuiIdListModel const & idModel = 
1290                         focusOnSelected  ? selected_model_ : available_model_;
1291         string const modName = idModel.getIDString(idx.row());
1292         docstring desc = getModuleDescription(modName);
1293
1294         vector<string> pkgList = getPackageList(modName);
1295         docstring pkgdesc = formatStrVec(pkgList, _("and"));
1296         if (!pkgdesc.empty()) {
1297                 if (!desc.empty())
1298                         desc += "\n";
1299                 desc += bformat(_("Package(s) required: %1$s."), pkgdesc);
1300         }
1301
1302         pkgList = getRequiredList(modName);
1303         if (!pkgList.empty()) {
1304                 vector<string> const reqDescs = idsToNames(pkgList);
1305                 pkgdesc = formatStrVec(reqDescs, _("or"));
1306                 if (!desc.empty())
1307                         desc += "\n";
1308                 desc += bformat(_("Module required: %1$s."), pkgdesc);
1309         }
1310
1311         pkgList = getExcludedList(modName);
1312         if (!pkgList.empty()) {
1313                 vector<string> const reqDescs = idsToNames(pkgList);
1314                 pkgdesc = formatStrVec(reqDescs, _( "and"));
1315                 if (!desc.empty())
1316                         desc += "\n";
1317                 desc += bformat(_("Modules excluded: %1$s."), pkgdesc);
1318         }
1319
1320         if (!isModuleAvailable(modName)) {
1321                 if (!desc.empty())
1322                         desc += "\n";
1323                 desc += _("WARNING: Some packages are unavailable!");
1324         }
1325
1326         latexModule->infoML->document()->setPlainText(toqstr(desc));
1327 }
1328
1329
1330 void GuiDocument::updateEmbeddedFileList()
1331 {
1332         embeddedFilesModule->filesLW->clear();
1333         // add current embedded files
1334         EmbeddedFileList & files = buffer().embeddedFiles();
1335         files.update(buffer());
1336         EmbeddedFileList::iterator fit = files.begin();
1337         EmbeddedFileList::iterator fit_end = files.end();
1338         for (; fit != fit_end; ++fit) {
1339                 QString label = toqstr(fit->relFilename(buffer().filePath()));
1340                 if (fit->refCount() > 1)
1341                         label += " (" + QString::number(fit->refCount()) + ")";
1342                 QListWidgetItem * item = new QListWidgetItem(label);
1343                 item->setFlags(item->flags() | Qt::ItemIsSelectable
1344                         | Qt::ItemIsUserCheckable);
1345                 if(fit->embedded())
1346                         item->setCheckState(Qt::Checked);
1347                 else
1348                         item->setCheckState(Qt::Unchecked);
1349                 // index of the currently used ParConstIterator
1350                 embeddedFilesModule->filesLW->addItem(item);
1351         }
1352 }
1353
1354
1355 void GuiDocument::updateNumbering()
1356 {
1357         TextClass const & tclass = bp_.getTextClass();
1358
1359         numberingModule->tocTW->setUpdatesEnabled(false);
1360         numberingModule->tocTW->clear();
1361
1362         int const depth = numberingModule->depthSL->value();
1363         int const toc = numberingModule->tocSL->value();
1364         QString const no = qt_("No");
1365         QString const yes = qt_("Yes");
1366         QTreeWidgetItem * item = 0;
1367         for (size_t i = 0; i != tclass.layoutCount(); ++i) {
1368                 Layout const & lt = *tclass.layout(i);
1369                 int const toclevel = lt.toclevel;
1370                 if (toclevel != Layout::NOT_IN_TOC && lt.labeltype == LABEL_COUNTER) {
1371                         item = new QTreeWidgetItem(numberingModule->tocTW);
1372                         item->setText(0, toqstr(translateIfPossible(lt.name())));
1373                         item->setText(1, (toclevel <= depth) ? yes : no);
1374                         item->setText(2, (toclevel <= toc) ? yes : no);
1375                 }
1376         }
1377
1378         numberingModule->tocTW->setUpdatesEnabled(true);
1379         numberingModule->tocTW->update();
1380 }
1381
1382
1383 void GuiDocument::apply(BufferParams & params)
1384 {
1385         // preamble
1386         preambleModule->apply(params);
1387
1388         // biblio
1389         params.setCiteEngine(biblio::ENGINE_BASIC);
1390
1391         if (biblioModule->citeNatbibRB->isChecked()) {
1392                 bool const use_numerical_citations =
1393                         biblioModule->citeStyleCO->currentIndex();
1394                 if (use_numerical_citations)
1395                         params.setCiteEngine(biblio::ENGINE_NATBIB_NUMERICAL);
1396                 else
1397                         params.setCiteEngine(biblio::ENGINE_NATBIB_AUTHORYEAR);
1398
1399         } else if (biblioModule->citeJurabibRB->isChecked())
1400                 params.setCiteEngine(biblio::ENGINE_JURABIB);
1401
1402         params.use_bibtopic =
1403                 biblioModule->bibtopicCB->isChecked();
1404
1405         // language & quotes
1406         if (langModule->defaultencodingRB->isChecked()) {
1407                 params.inputenc = "auto";
1408         } else {
1409                 int i = langModule->encodingCO->currentIndex();
1410                 if (i == 0)
1411                         params.inputenc = "default";
1412                 else
1413                         params.inputenc =
1414                                 fromqstr(langModule->encodingCO->currentText());
1415         }
1416
1417         InsetQuotes::quote_language lga = InsetQuotes::EnglishQ;
1418         switch (langModule->quoteStyleCO->currentIndex()) {
1419         case 0:
1420                 lga = InsetQuotes::EnglishQ;
1421                 break;
1422         case 1:
1423                 lga = InsetQuotes::SwedishQ;
1424                 break;
1425         case 2:
1426                 lga = InsetQuotes::GermanQ;
1427                 break;
1428         case 3:
1429                 lga = InsetQuotes::PolishQ;
1430                 break;
1431         case 4:
1432                 lga = InsetQuotes::FrenchQ;
1433                 break;
1434         case 5:
1435                 lga = InsetQuotes::DanishQ;
1436                 break;
1437         }
1438         params.quotes_language = lga;
1439
1440         int const pos = langModule->languageCO->currentIndex();
1441         params.language = lyx::languages.getLanguage(lang_[pos]);
1442
1443         // numbering
1444         if (params.getTextClass().hasTocLevels()) {
1445                 params.tocdepth = numberingModule->tocSL->value();
1446                 params.secnumdepth = numberingModule->depthSL->value();
1447         }
1448
1449         // bullets
1450         params.user_defined_bullet(0) = bulletsModule->getBullet(0);
1451         params.user_defined_bullet(1) = bulletsModule->getBullet(1);
1452         params.user_defined_bullet(2) = bulletsModule->getBullet(2);
1453         params.user_defined_bullet(3) = bulletsModule->getBullet(3);
1454
1455         // packages
1456         params.graphicsDriver =
1457                 tex_graphics[latexModule->psdriverCO->currentIndex()];
1458         
1459         // text layout
1460         params.setBaseClass(latexModule->classCO->currentIndex());
1461
1462         // Modules
1463         params.clearLayoutModules();
1464         int const srows = selected_model_.rowCount();
1465         vector<string> selModList;
1466         for (int i = 0; i < srows; ++i)
1467                 params.addLayoutModule(selected_model_.getIDString(i));
1468
1469         if (mathsModule->amsautoCB->isChecked()) {
1470                 params.use_amsmath = BufferParams::package_auto;
1471         } else {
1472                 if (mathsModule->amsCB->isChecked())
1473                         params.use_amsmath = BufferParams::package_on;
1474                 else
1475                         params.use_amsmath = BufferParams::package_off;
1476         }
1477
1478         if (mathsModule->esintautoCB->isChecked())
1479                 params.use_esint = BufferParams::package_auto;
1480         else {
1481                 if (mathsModule->esintCB->isChecked())
1482                         params.use_esint = BufferParams::package_on;
1483                 else
1484                         params.use_esint = BufferParams::package_off;
1485         }
1486
1487         if (pageLayoutModule->pagestyleCO->currentIndex() == 0)
1488                 params.pagestyle = "default";
1489         else {
1490                 docstring style_gui =
1491                         qstring_to_ucs4(pageLayoutModule->pagestyleCO->currentText());
1492                 for (size_t i = 0; i < pagestyles.size(); ++i)
1493                         if (pagestyles[i].second == style_gui)
1494                                 params.pagestyle = pagestyles[i].first;
1495         }
1496
1497         switch (textLayoutModule->lspacingCO->currentIndex()) {
1498         case 0:
1499                 params.spacing().set(Spacing::Single);
1500                 break;
1501         case 1:
1502                 params.spacing().set(Spacing::Onehalf);
1503                 break;
1504         case 2:
1505                 params.spacing().set(Spacing::Double);
1506                 break;
1507         case 3:
1508                 params.spacing().set(Spacing::Other,
1509                         fromqstr(textLayoutModule->lspacingLE->text()));
1510                 break;
1511         }
1512
1513         if (textLayoutModule->twoColumnCB->isChecked())
1514                 params.columns = 2;
1515         else
1516                 params.columns = 1;
1517
1518         // text should have passed validation
1519         params.listings_params =
1520                 InsetListingsParams(fromqstr(textLayoutModule->listingsED->toPlainText())).params();
1521
1522         if (textLayoutModule->indentRB->isChecked())
1523                 params.paragraph_separation = BufferParams::PARSEP_INDENT;
1524         else
1525                 params.paragraph_separation = BufferParams::PARSEP_SKIP;
1526
1527         switch (textLayoutModule->skipCO->currentIndex()) {
1528         case 0:
1529                 params.setDefSkip(VSpace(VSpace::SMALLSKIP));
1530                 break;
1531         case 1:
1532                 params.setDefSkip(VSpace(VSpace::MEDSKIP));
1533                 break;
1534         case 2:
1535                 params.setDefSkip(VSpace(VSpace::BIGSKIP));
1536                 break;
1537         case 3:
1538         {
1539                 VSpace vs = VSpace(
1540                         widgetsToLength(textLayoutModule->skipLE,
1541                                 textLayoutModule->skipLengthCO)
1542                         );
1543                 params.setDefSkip(vs);
1544                 break;
1545         }
1546         default:
1547                 // DocumentDefskipCB assures that this never happens
1548                 // so Assert then !!!  - jbl
1549                 params.setDefSkip(VSpace(VSpace::MEDSKIP));
1550                 break;
1551         }
1552
1553         params.options =
1554                 fromqstr(latexModule->optionsLE->text());
1555
1556         params.float_placement = floatModule->get();
1557
1558         // fonts
1559         params.fontsRoman =
1560                 tex_fonts_roman[fontModule->fontsRomanCO->currentIndex()];
1561
1562         params.fontsSans =
1563                 tex_fonts_sans[fontModule->fontsSansCO->currentIndex()];
1564
1565         params.fontsTypewriter =
1566                 tex_fonts_monospaced[fontModule->fontsTypewriterCO->currentIndex()];
1567
1568         params.fontsSansScale = fontModule->scaleSansSB->value();
1569
1570         params.fontsTypewriterScale = fontModule->scaleTypewriterSB->value();
1571
1572         params.fontsSC = fontModule->fontScCB->isChecked();
1573
1574         params.fontsOSF = fontModule->fontOsfCB->isChecked();
1575
1576         params.fontsDefaultFamily = GuiDocument::fontfamilies[
1577                 fontModule->fontsDefaultCO->currentIndex()];
1578
1579         if (fontModule->fontsizeCO->currentIndex() == 0)
1580                 params.fontsize = "default";
1581         else
1582                 params.fontsize =
1583                         fromqstr(fontModule->fontsizeCO->currentText());
1584
1585         // paper
1586         params.papersize = PAPER_SIZE(
1587                 pageLayoutModule->papersizeCO->currentIndex());
1588
1589         // custom, A3, B3 and B4 paper sizes need geometry
1590         int psize = pageLayoutModule->papersizeCO->currentIndex();
1591         bool geom_papersize = (psize == 1 || psize == 5 || psize == 8 || psize == 9);
1592
1593         params.paperwidth = widgetsToLength(pageLayoutModule->paperwidthLE,
1594                 pageLayoutModule->paperwidthUnitCO);
1595
1596         params.paperheight = widgetsToLength(pageLayoutModule->paperheightLE,
1597                 pageLayoutModule->paperheightUnitCO);
1598
1599         if (pageLayoutModule->facingPagesCB->isChecked())
1600                 params.sides = TwoSides;
1601         else
1602                 params.sides = OneSide;
1603
1604         if (pageLayoutModule->landscapeRB->isChecked())
1605                 params.orientation = ORIENTATION_LANDSCAPE;
1606         else
1607                 params.orientation = ORIENTATION_PORTRAIT;
1608
1609         // margins
1610         params.use_geometry =
1611                 (!marginsModule->marginCB->isChecked()
1612                 || geom_papersize);
1613
1614         Ui::MarginsUi const * m(marginsModule);
1615
1616         params.leftmargin = widgetsToLength(m->innerLE, m->innerUnit);
1617         params.topmargin = widgetsToLength(m->topLE, m->topUnit);
1618         params.rightmargin = widgetsToLength(m->outerLE, m->outerUnit);
1619         params.bottommargin = widgetsToLength(m->bottomLE, m->bottomUnit);
1620         params.headheight = widgetsToLength(m->headheightLE, m->headheightUnit);
1621         params.headsep = widgetsToLength(m->headsepLE, m->headsepUnit);
1622         params.footskip = widgetsToLength(m->footskipLE, m->footskipUnit);
1623         params.columnsep = widgetsToLength(m->columnsepLE, m->columnsepUnit);
1624
1625         branchesModule->apply(params);
1626
1627         // PDF support
1628         PDFOptions & pdf = params.pdfoptions();
1629         pdf.use_hyperref = pdfSupportModule->use_hyperrefGB->isChecked();
1630         pdf.title = fromqstr(pdfSupportModule->titleLE->text());
1631         pdf.author = fromqstr(pdfSupportModule->authorLE->text());
1632         pdf.subject = fromqstr(pdfSupportModule->subjectLE->text());
1633         pdf.keywords = fromqstr(pdfSupportModule->keywordsLE->text());
1634
1635         pdf.bookmarks = pdfSupportModule->bookmarksGB->isChecked();
1636         pdf.bookmarksnumbered = pdfSupportModule->bookmarksnumberedCB->isChecked();
1637         pdf.bookmarksopen = pdfSupportModule->bookmarksopenGB->isChecked();
1638         pdf.bookmarksopenlevel = pdfSupportModule->bookmarksopenlevelSB->value();
1639
1640         pdf.breaklinks = pdfSupportModule->breaklinksCB->isChecked();
1641         pdf.pdfborder = pdfSupportModule->pdfborderCB->isChecked();
1642         pdf.pdfusetitle = pdfSupportModule->pdfusetitleCB->isChecked();
1643         pdf.colorlinks = pdfSupportModule->colorlinksCB->isChecked();
1644         pdf.backref = pdfSupportModule->backrefCB->isChecked();
1645         pdf.pagebackref = pdfSupportModule->pagebackrefCB->isChecked();
1646         if (pdfSupportModule->fullscreenCB->isChecked())
1647                 pdf.pagemode = pdf.pagemode_fullscreen;
1648         else
1649                 pdf.pagemode.clear();
1650         pdf.quoted_options = fromqstr(pdfSupportModule->optionsLE->text());
1651
1652         // Embedded files
1653         // FIXME
1654 }
1655
1656
1657 /** Return the position of val in the vector if found.
1658     If not found, return 0.
1659  */
1660 template<class A>
1661 static size_t findPos(vector<A> const & vec, A const & val)
1662 {
1663         typename vector<A>::const_iterator it =
1664                 find(vec.begin(), vec.end(), val);
1665         if (it == vec.end())
1666                 return 0;
1667         return distance(vec.begin(), it);
1668 }
1669
1670
1671 void GuiDocument::updateParams()
1672 {
1673         updateParams(bp_);
1674 }
1675
1676
1677 void GuiDocument::updateParams(BufferParams const & params)
1678 {
1679         // set the default unit
1680         Length::UNIT defaultUnit = Length::CM;
1681         switch (lyxrc.default_papersize) {
1682                 case PAPER_DEFAULT: break;
1683
1684                 case PAPER_USLETTER:
1685                 case PAPER_USLEGAL:
1686                 case PAPER_USEXECUTIVE:
1687                         defaultUnit = Length::IN;
1688                         break;
1689
1690                 case PAPER_A3:
1691                 case PAPER_A4:
1692                 case PAPER_A5:
1693                 case PAPER_B3:
1694                 case PAPER_B4:
1695                 case PAPER_B5:
1696                         defaultUnit = Length::CM;
1697                         break;
1698                 case PAPER_CUSTOM:
1699                         break;
1700         }
1701
1702         // preamble
1703         preambleModule->update(params, id());
1704
1705         // biblio
1706         biblioModule->citeDefaultRB->setChecked(
1707                 params.getEngine() == biblio::ENGINE_BASIC);
1708
1709         biblioModule->citeNatbibRB->setChecked(
1710                 params.getEngine() == biblio::ENGINE_NATBIB_NUMERICAL ||
1711                 params.getEngine() == biblio::ENGINE_NATBIB_AUTHORYEAR);
1712
1713         biblioModule->citeStyleCO->setCurrentIndex(
1714                 params.getEngine() == biblio::ENGINE_NATBIB_NUMERICAL);
1715
1716         biblioModule->citeJurabibRB->setChecked(
1717                 params.getEngine() == biblio::ENGINE_JURABIB);
1718
1719         biblioModule->bibtopicCB->setChecked(
1720                 params.use_bibtopic);
1721
1722         // language & quotes
1723         int const pos = int(findPos(lang_,
1724                                     params.language->lang()));
1725         langModule->languageCO->setCurrentIndex(pos);
1726
1727         langModule->quoteStyleCO->setCurrentIndex(
1728                 params.quotes_language);
1729
1730         bool default_enc = true;
1731         if (params.inputenc != "auto") {
1732                 default_enc = false;
1733                 if (params.inputenc == "default") {
1734                         langModule->encodingCO->setCurrentIndex(0);
1735                 } else {
1736                         int const i = langModule->encodingCO->findText(
1737                                         toqstr(params.inputenc));
1738                         if (i >= 0)
1739                                 langModule->encodingCO->setCurrentIndex(i);
1740                         else
1741                                 // unknown encoding. Set to default.
1742                                 default_enc = true;
1743                 }
1744         }
1745         langModule->defaultencodingRB->setChecked(default_enc);
1746         langModule->otherencodingRB->setChecked(!default_enc);
1747
1748         // numbering
1749         int const min_toclevel = textClass().min_toclevel();
1750         int const max_toclevel = textClass().max_toclevel();
1751         if (textClass().hasTocLevels()) {
1752                 numberingModule->setEnabled(true);
1753                 numberingModule->depthSL->setMinimum(min_toclevel - 1);
1754                 numberingModule->depthSL->setMaximum(max_toclevel);
1755                 numberingModule->depthSL->setValue(params.secnumdepth);
1756                 numberingModule->tocSL->setMaximum(min_toclevel - 1);
1757                 numberingModule->tocSL->setMaximum(max_toclevel);
1758                 numberingModule->tocSL->setValue(params.tocdepth);
1759                 updateNumbering();
1760         } else {
1761                 numberingModule->setEnabled(false);
1762                 numberingModule->tocTW->clear();
1763         }
1764
1765         // bullets
1766         bulletsModule->setBullet(0, params.user_defined_bullet(0));
1767         bulletsModule->setBullet(1, params.user_defined_bullet(1));
1768         bulletsModule->setBullet(2, params.user_defined_bullet(2));
1769         bulletsModule->setBullet(3, params.user_defined_bullet(3));
1770         bulletsModule->init();
1771
1772         // packages
1773         int nitem = findToken(tex_graphics, params.graphicsDriver);
1774         if (nitem >= 0)
1775                 latexModule->psdriverCO->setCurrentIndex(nitem);
1776         updateModuleInfo();
1777         
1778         mathsModule->amsCB->setChecked(
1779                 params.use_amsmath == BufferParams::package_on);
1780         mathsModule->amsautoCB->setChecked(
1781                 params.use_amsmath == BufferParams::package_auto);
1782
1783         mathsModule->esintCB->setChecked(
1784                 params.use_esint == BufferParams::package_on);
1785         mathsModule->esintautoCB->setChecked(
1786                 params.use_esint == BufferParams::package_auto);
1787
1788         switch (params.spacing().getSpace()) {
1789                 case Spacing::Other: nitem = 3; break;
1790                 case Spacing::Double: nitem = 2; break;
1791                 case Spacing::Onehalf: nitem = 1; break;
1792                 case Spacing::Default: case Spacing::Single: nitem = 0; break;
1793         }
1794
1795         // text layout
1796         latexModule->classCO->setCurrentIndex(params.getBaseClass());
1797         
1798         updatePagestyle(textClass().opt_pagestyle(),
1799                                  params.pagestyle);
1800
1801         textLayoutModule->lspacingCO->setCurrentIndex(nitem);
1802         if (params.spacing().getSpace() == Spacing::Other) {
1803                 textLayoutModule->lspacingLE->setText(
1804                         toqstr(params.spacing().getValueAsString()));
1805         }
1806         setLSpacing(nitem);
1807
1808         if (params.paragraph_separation == BufferParams::PARSEP_INDENT)
1809                 textLayoutModule->indentRB->setChecked(true);
1810         else
1811                 textLayoutModule->skipRB->setChecked(true);
1812
1813         int skip = 0;
1814         switch (params.getDefSkip().kind()) {
1815         case VSpace::SMALLSKIP:
1816                 skip = 0;
1817                 break;
1818         case VSpace::MEDSKIP:
1819                 skip = 1;
1820                 break;
1821         case VSpace::BIGSKIP:
1822                 skip = 2;
1823                 break;
1824         case VSpace::LENGTH:
1825         {
1826                 skip = 3;
1827                 string const length = params.getDefSkip().asLyXCommand();
1828                 lengthToWidgets(textLayoutModule->skipLE,
1829                         textLayoutModule->skipLengthCO,
1830                         length, defaultUnit);
1831                 break;
1832         }
1833         default:
1834                 skip = 0;
1835                 break;
1836         }
1837         textLayoutModule->skipCO->setCurrentIndex(skip);
1838         setSkip(skip);
1839
1840         textLayoutModule->twoColumnCB->setChecked(
1841                 params.columns == 2);
1842
1843         // break listings_params to multiple lines
1844         string lstparams =
1845                 InsetListingsParams(params.listings_params).separatedParams();
1846         textLayoutModule->listingsED->setPlainText(toqstr(lstparams));
1847
1848         if (!params.options.empty()) {
1849                 latexModule->optionsLE->setText(
1850                         toqstr(params.options));
1851         } else {
1852                 latexModule->optionsLE->setText(QString());
1853         }
1854
1855         floatModule->set(params.float_placement);
1856
1857         // Fonts
1858         updateFontsize(textClass().opt_fontsize(),
1859                         params.fontsize);
1860
1861         int n = findToken(tex_fonts_roman, params.fontsRoman);
1862         if (n >= 0) {
1863                 fontModule->fontsRomanCO->setCurrentIndex(n);
1864                 romanChanged(n);
1865         }
1866
1867         n = findToken(tex_fonts_sans, params.fontsSans);
1868         if (n >= 0)     {
1869                 fontModule->fontsSansCO->setCurrentIndex(n);
1870                 sansChanged(n);
1871         }
1872
1873         n = findToken(tex_fonts_monospaced, params.fontsTypewriter);
1874         if (n >= 0) {
1875                 fontModule->fontsTypewriterCO->setCurrentIndex(n);
1876                 ttChanged(n);
1877         }
1878
1879         fontModule->fontScCB->setChecked(params.fontsSC);
1880         fontModule->fontOsfCB->setChecked(params.fontsOSF);
1881         fontModule->scaleSansSB->setValue(params.fontsSansScale);
1882         fontModule->scaleTypewriterSB->setValue(params.fontsTypewriterScale);
1883         n = findToken(GuiDocument::fontfamilies, params.fontsDefaultFamily);
1884         if (n >= 0)
1885                 fontModule->fontsDefaultCO->setCurrentIndex(n);
1886
1887         // paper
1888         int const psize = params.papersize;
1889         pageLayoutModule->papersizeCO->setCurrentIndex(psize);
1890         setCustomPapersize(psize);
1891
1892         bool const landscape =
1893                 params.orientation == ORIENTATION_LANDSCAPE;
1894         pageLayoutModule->landscapeRB->setChecked(landscape);
1895         pageLayoutModule->portraitRB->setChecked(!landscape);
1896
1897         pageLayoutModule->facingPagesCB->setChecked(
1898                 params.sides == TwoSides);
1899
1900
1901         lengthToWidgets(pageLayoutModule->paperwidthLE,
1902                 pageLayoutModule->paperwidthUnitCO, params.paperwidth, defaultUnit);
1903
1904         lengthToWidgets(pageLayoutModule->paperheightLE,
1905                 pageLayoutModule->paperheightUnitCO, params.paperheight, defaultUnit);
1906
1907         // margins
1908         Ui::MarginsUi * m = marginsModule;
1909
1910         setMargins(!params.use_geometry);
1911
1912         lengthToWidgets(m->topLE, m->topUnit,
1913                 params.topmargin, defaultUnit);
1914
1915         lengthToWidgets(m->bottomLE, m->bottomUnit,
1916                 params.bottommargin, defaultUnit);
1917
1918         lengthToWidgets(m->innerLE, m->innerUnit,
1919                 params.leftmargin, defaultUnit);
1920
1921         lengthToWidgets(m->outerLE, m->outerUnit,
1922                 params.rightmargin, defaultUnit);
1923
1924         lengthToWidgets(m->headheightLE, m->headheightUnit,
1925                 params.headheight, defaultUnit);
1926
1927         lengthToWidgets(m->headsepLE, m->headsepUnit,
1928                 params.headsep, defaultUnit);
1929
1930         lengthToWidgets(m->footskipLE, m->footskipUnit,
1931                 params.footskip, defaultUnit);
1932
1933         lengthToWidgets(m->columnsepLE, m->columnsepUnit,
1934                 params.columnsep, defaultUnit);
1935
1936         branchesModule->update(params);
1937
1938         // PDF support
1939         PDFOptions const & pdf = params.pdfoptions();
1940         pdfSupportModule->use_hyperrefGB->setChecked(pdf.use_hyperref);
1941         pdfSupportModule->titleLE->setText(toqstr(pdf.title));
1942         pdfSupportModule->authorLE->setText(toqstr(pdf.author));
1943         pdfSupportModule->subjectLE->setText(toqstr(pdf.subject));
1944         pdfSupportModule->keywordsLE->setText(toqstr(pdf.keywords));
1945
1946         pdfSupportModule->bookmarksGB->setChecked(pdf.bookmarks);
1947         pdfSupportModule->bookmarksnumberedCB->setChecked(pdf.bookmarksnumbered);
1948         pdfSupportModule->bookmarksopenGB->setChecked(pdf.bookmarksopen);
1949
1950         pdfSupportModule->bookmarksopenlevelSB->setValue(pdf.bookmarksopenlevel);
1951
1952         pdfSupportModule->breaklinksCB->setChecked(pdf.breaklinks);
1953         pdfSupportModule->pdfborderCB->setChecked(pdf.pdfborder);
1954         pdfSupportModule->pdfusetitleCB->setChecked(pdf.pdfusetitle);
1955         pdfSupportModule->colorlinksCB->setChecked(pdf.colorlinks);
1956         pdfSupportModule->backrefCB->setChecked(pdf.backref);
1957         pdfSupportModule->pagebackrefCB->setChecked(pdf.pagebackref);
1958         pdfSupportModule->fullscreenCB->setChecked
1959                 (pdf.pagemode == pdf.pagemode_fullscreen);
1960
1961         pdfSupportModule->optionsLE->setText(
1962                 toqstr(pdf.quoted_options));
1963
1964         // embedded files
1965         updateEmbeddedFileList();
1966 }
1967
1968
1969 void GuiDocument::applyView()
1970 {
1971         apply(params());
1972 }
1973
1974
1975 void GuiDocument::saveDocDefault()
1976 {
1977         // we have to apply the params first
1978         applyView();
1979         saveAsDefault();
1980 }
1981
1982
1983 void GuiDocument::updateAvailableModules() 
1984 {
1985         available_model_.clear();
1986         vector<modInfoStruct> const modInfoList = getModuleInfo();
1987         int const mSize = modInfoList.size();
1988         for (int i = 0; i < mSize; ++i) {
1989                 modInfoStruct const & modInfo = modInfoList[i];
1990                 available_model_.insertRow(i, qt_(modInfo.name), modInfo.id);
1991         }
1992 }
1993
1994
1995 void GuiDocument::updateSelectedModules() 
1996 {
1997         //and selected ones, too
1998         selected_model_.clear();
1999         vector<modInfoStruct> const selModList = getSelectedModules();
2000         int const sSize = selModList.size();
2001         for (int i = 0; i < sSize; ++i) {
2002                 modInfoStruct const & modInfo = selModList[i];
2003                 selected_model_.insertRow(i, qt_(modInfo.name), modInfo.id);
2004         }
2005 }
2006
2007
2008 void GuiDocument::updateContents()
2009 {
2010         if (id() == current_id_)
2011                 return;
2012
2013         updateAvailableModules();
2014         updateSelectedModules();
2015         
2016         //FIXME It'd be nice to make sure here that the selected
2017         //modules are consistent: That required modules are actually
2018         //selected, and that we don't have conflicts. If so, we could
2019         //at least pop up a warning.
2020         updateParams(bp_);
2021         current_id_ = id();
2022 }
2023
2024
2025 void GuiDocument::forceUpdate()
2026 {
2027         // reset to force dialog update
2028         current_id_ = 0;
2029         updateContents();
2030 }
2031
2032
2033 void GuiDocument::useClassDefaults()
2034 {
2035         if (applyPB->isEnabled()) {
2036                 int const ret = Alert::prompt(_("Unapplied changes"),
2037                                 _("Some changes in the dialog were not yet applied."
2038                                   "If you do not apply now, they will be lost after this action."),
2039                                 1, 1, _("&Apply"), _("&Dismiss"));
2040                 if (ret == 0)
2041                         applyView();
2042         }
2043
2044         bp_.setBaseClass(latexModule->classCO->currentIndex());
2045         bp_.useClassDefaults();
2046         forceUpdate();
2047 }
2048
2049
2050 bool GuiDocument::isValid()
2051 {
2052         return (validate_listings_params().empty() &&
2053                 (textLayoutModule->skipCO->currentIndex() != 3 ||
2054                  !textLayoutModule->skipLE->text().isEmpty()));
2055 }
2056
2057
2058 char const * const GuiDocument::fontfamilies[5] = {
2059         "default", "rmdefault", "sfdefault", "ttdefault", ""
2060 };
2061
2062
2063 char const * GuiDocument::fontfamilies_gui[5] = {
2064         N_("Default"), N_("Roman"), N_("Sans Serif"), N_("Typewriter"), ""
2065 };
2066
2067
2068 bool GuiDocument::initialiseParams(string const &)
2069 {
2070         bp_ = buffer().params();
2071         loadModuleInfo();
2072         return true;
2073 }
2074
2075
2076 void GuiDocument::clearParams()
2077 {
2078         bp_ = BufferParams();
2079 }
2080
2081
2082 BufferId GuiDocument::id() const
2083 {
2084         return &buffer();
2085 }
2086
2087
2088 vector<GuiDocument::modInfoStruct> const & GuiDocument::getModuleInfo()
2089 {
2090         return moduleNames_;
2091 }
2092
2093
2094 vector<GuiDocument::modInfoStruct> const GuiDocument::getSelectedModules()
2095 {
2096         vector<string> const & mods = params().getModules();
2097         vector<string>::const_iterator it =  mods.begin();
2098         vector<string>::const_iterator end = mods.end();
2099         vector<modInfoStruct> mInfo;
2100         for (; it != end; ++it) {
2101                 modInfoStruct m;
2102                 m.id = *it;
2103                 LyXModule * mod = moduleList[*it];
2104                 if (mod)
2105                         m.name = mod->getName();
2106                 else 
2107                         m.name = *it + " (Not Found)";
2108                 mInfo.push_back(m);
2109         }
2110         return mInfo;
2111 }
2112
2113
2114 TextClass const & GuiDocument::textClass() const
2115 {
2116         return textclasslist[bp_.getBaseClass()];
2117 }
2118
2119
2120 static void dispatch_bufferparams(Dialog const & dialog,
2121         BufferParams const & bp, kb_action lfun)
2122 {
2123         ostringstream ss;
2124         ss << "\\begin_header\n";
2125         bp.writeFile(ss);
2126         ss << "\\end_header\n";
2127         dialog.dispatch(FuncRequest(lfun, ss.str()));
2128 }
2129
2130
2131 void GuiDocument::dispatchParams()
2132 {
2133         // This must come first so that a language change is correctly noticed
2134         setLanguage();
2135
2136         // Apply the BufferParams. Note that this will set the base class
2137         // and then update the buffer's layout.
2138         dispatch_bufferparams(*this, params(), LFUN_BUFFER_PARAMS_APPLY);
2139
2140         // Generate the colours requested by each new branch.
2141         BranchList & branchlist = params().branchlist();
2142         if (!branchlist.empty()) {
2143                 BranchList::const_iterator it = branchlist.begin();
2144                 BranchList::const_iterator const end = branchlist.end();
2145                 for (; it != end; ++it) {
2146                         docstring const & current_branch = it->getBranch();
2147                         Branch const * branch = branchlist.find(current_branch);
2148                         string const x11hexname = X11hexname(branch->getColor());
2149                         // display the new color
2150                         docstring const str = current_branch + ' ' + from_ascii(x11hexname);
2151                         dispatch(FuncRequest(LFUN_SET_COLOR, str));
2152                 }
2153
2154                 // Open insets of selected branches, close deselected ones
2155                 dispatch(FuncRequest(LFUN_ALL_INSETS_TOGGLE,
2156                         "assign branch"));
2157         }
2158         // FIXME: If we used an LFUN, we would not need those two lines:
2159         bufferview()->processUpdateFlags(Update::Force | Update::FitCursor);
2160 }
2161
2162
2163 void GuiDocument::setLanguage() const
2164 {
2165         Language const * const newL = bp_.language;
2166         if (buffer().params().language == newL)
2167                 return;
2168
2169         string const & lang_name = newL->lang();
2170         dispatch(FuncRequest(LFUN_BUFFER_LANGUAGE, lang_name));
2171 }
2172
2173
2174 void GuiDocument::saveAsDefault() const
2175 {
2176         dispatch_bufferparams(*this, params(), LFUN_BUFFER_SAVE_AS_DEFAULT);
2177 }
2178
2179
2180 bool GuiDocument::isFontAvailable(string const & font) const
2181 {
2182         if (font == "default" || font == "cmr"
2183             || font == "cmss" || font == "cmtt")
2184                 // these are standard
2185                 return true;
2186         if (font == "lmodern" || font == "lmss" || font == "lmtt")
2187                 return LaTeXFeatures::isAvailable("lmodern");
2188         if (font == "times" || font == "palatino"
2189                  || font == "helvet" || font == "courier")
2190                 return LaTeXFeatures::isAvailable("psnfss");
2191         if (font == "cmbr" || font == "cmtl")
2192                 return LaTeXFeatures::isAvailable("cmbright");
2193         if (font == "utopia")
2194                 return LaTeXFeatures::isAvailable("utopia")
2195                         || LaTeXFeatures::isAvailable("fourier");
2196         if (font == "beraserif" || font == "berasans"
2197                 || font == "beramono")
2198                 return LaTeXFeatures::isAvailable("bera");
2199         return LaTeXFeatures::isAvailable(font);
2200 }
2201
2202
2203 bool GuiDocument::providesOSF(string const & font) const
2204 {
2205         if (font == "cmr")
2206                 return isFontAvailable("eco");
2207         if (font == "palatino")
2208                 return isFontAvailable("mathpazo");
2209         return false;
2210 }
2211
2212
2213 bool GuiDocument::providesSC(string const & font) const
2214 {
2215         if (font == "palatino")
2216                 return isFontAvailable("mathpazo");
2217         if (font == "utopia")
2218                 return isFontAvailable("fourier");
2219         return false;
2220 }
2221
2222
2223 bool GuiDocument::providesScale(string const & font) const
2224 {
2225         return font == "helvet" || font == "luximono"
2226                 || font == "berasans"  || font == "beramono";
2227 }
2228
2229
2230 void GuiDocument::loadModuleInfo()
2231 {
2232         moduleNames_.clear();
2233         LyXModuleList::const_iterator it  = moduleList.begin();
2234         LyXModuleList::const_iterator end = moduleList.end();
2235         for (; it != end; ++it) {
2236                 modInfoStruct m;
2237                 m.id = it->getID();
2238                 m.name = it->getName();
2239                 moduleNames_.push_back(m);
2240         }
2241 }
2242
2243
2244 Dialog * createGuiDocument(GuiView & lv) { return new GuiDocument(lv); }
2245
2246
2247 } // namespace frontend
2248 } // namespace lyx
2249
2250 #include "GuiDocument_moc.cpp"