]> git.lyx.org Git - lyx.git/blob - src/frontends/qt2/QDocument.C
better selection and scrolling behaviour
[lyx.git] / src / frontends / qt2 / QDocument.C
1 /**
2  * \file QDocument.C
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  *
8  * Full author contact details are available in file CREDITS
9  */
10
11 #include <config.h>
12
13 #ifdef __GNUG__
14 #pragma implementation
15 #endif
16
17 #include "gettext.h"
18
19 #include "ControlDocument.h"
20 #include "QDocument.h"
21 #include "QDocumentDialog.h"
22 #include "Qt2BC.h"
23
24 #include "language.h"
25 #include "helper_funcs.h" // getSecond()
26 #include "insets/insetquotes.h"
27 #include "frnt_lang.h"
28 #include "tex-strings.h" // tex_graphics
29 #include "support/lstrings.h" // tostr()
30 #include "support/filetools.h" // LibFileSearch()
31 #include "lyxtextclasslist.h"
32 #include "vspace.h"
33 #include "bufferparams.h"
34
35 #include <qpushbutton.h>
36 #include <qmultilineedit.h>
37 #include <qradiobutton.h>
38 #include <qcombobox.h>
39 #include <qcheckbox.h>
40 #include <qspinbox.h>
41 #include <qlineedit.h>
42 #include <qstringlist.h>
43 #include "lengthcombo.h"
44
45 #include "QBrowseBox.h"
46
47 #include <vector>
48
49 using std::vector;
50
51 typedef Qt2CB<ControlDocument, Qt2DB<QDocumentDialog> > base_class;
52
53
54 QDocument::QDocument()
55         : base_class(_("Document Settings"))
56 {
57         vector<frnt::LanguagePair> const langs = frnt::getLanguageData(false);
58         lang_ = getSecond(langs);
59 }
60
61
62 void QDocument::build_dialog()
63 {
64         dialog_.reset(new QDocumentDialog(this));
65
66         // biblio
67         dialog_->biblioModule->citeStyleCO->insertItem(_("Author-year"));
68         dialog_->biblioModule->citeStyleCO->insertItem(_("Numerical"));
69         dialog_->biblioModule->citeStyleCO->setCurrentItem(0);
70
71         // language & quotes
72         vector<frnt::LanguagePair> const langs = frnt::getLanguageData(false);
73         vector<frnt::LanguagePair>::const_iterator lit  = langs.begin();
74         vector<frnt::LanguagePair>::const_iterator lend = langs.end();
75         for (; lit != lend; ++lit) {
76                 dialog_->langModule->languageCO->insertItem(
77                         lit->first.c_str());
78         }
79
80         dialog_->langModule->quoteStyleCO->insertItem(_("``text''"));
81         dialog_->langModule->quoteStyleCO->insertItem(_("''text''"));
82         dialog_->langModule->quoteStyleCO->insertItem(_(",,text``"));
83         dialog_->langModule->quoteStyleCO->insertItem(_(",,text''"));
84         dialog_->langModule->quoteStyleCO->insertItem(_("«text»"));
85         dialog_->langModule->quoteStyleCO->insertItem(_("»text«"));
86
87         // packages
88         char const * items[] = {"default", "auto", "latin1", "latin2",
89                              "latin3", "latin4", "latin5", "latin9",
90                              "koi8-r", "koi8-u", "cp866", "cp1251",
91                              "iso88595", "pt154", 0};
92         dialog_->packagesModule->encodingCO->insertStrList(items);
93
94         dialog_->packagesModule->lspacingCO->insertItem(
95                 _("Single"), Spacing::Single);
96         dialog_->packagesModule->lspacingCO->insertItem(
97                 _("OneHalf"), Spacing::Onehalf);
98         dialog_->packagesModule->lspacingCO->insertItem(
99                 _("Double"), Spacing::Double);
100         dialog_->packagesModule->lspacingCO->insertItem(
101                 _("Custom"), Spacing::Other);
102
103         for (int n = 0; tex_graphics[n][0]; ++n) {
104                 QString enc = tex_graphics[n];
105                 dialog_->packagesModule->psdriverCO->insertItem(enc);
106         }
107
108         // paper
109         char const * sizes[] = {
110                 _("Default") , _("Custom") , _("US letter") , _("US legal")
111                    , _("US executive") , _("A3") , _("A4") , _("A5")
112                    , _("B3") , _("B4") , _("B5"), 0 };
113         dialog_->paperModule->papersizeCO->insertStrList(sizes);
114
115         // layout
116         for (LyXTextClassList::const_iterator cit = textclasslist.begin();
117              cit != textclasslist.end(); ++cit) {
118                 dialog_->layoutModule->classCO->insertItem(cit->description().c_str());
119         }
120
121         for (int n = 0; tex_fonts[n][0]; ++n) {
122                 QString font = tex_fonts[n];
123                 dialog_->layoutModule->fontsCO->insertItem(font);
124         }
125
126         dialog_->layoutModule->fontsizeCO->insertItem(_("default"));
127         dialog_->layoutModule->fontsizeCO->insertItem(_("10"));
128         dialog_->layoutModule->fontsizeCO->insertItem(_("11"));
129         dialog_->layoutModule->fontsizeCO->insertItem(_("12"));
130
131         dialog_->layoutModule->skipCO->insertItem(_("Smallskip"));
132         dialog_->layoutModule->skipCO->insertItem(_("Medskip"));
133         dialog_->layoutModule->skipCO->insertItem(_("Bigskip"));
134         dialog_->layoutModule->skipCO->insertItem(_("Length"));
135
136         dialog_->layoutModule->pagestyleCO->insertItem(_("default"));
137         dialog_->layoutModule->pagestyleCO->insertItem(_("empty"));
138         dialog_->layoutModule->pagestyleCO->insertItem(_("plain"));
139         dialog_->layoutModule->pagestyleCO->insertItem(_("headings"));
140         dialog_->layoutModule->pagestyleCO->insertItem(_("fancy"));
141
142         // margins
143         dialog_->setMargins(0);
144
145         // Manage the restore, ok, apply, restore and cancel/close buttons
146         bc().setOK(dialog_->okPB);
147         bc().setApply(dialog_->applyPB);
148         bc().setCancel(dialog_->closePB);
149         bc().setRestore(dialog_->restorePB);
150 }
151
152
153 void QDocument::apply()
154 {
155         BufferParams & params = controller().params();
156
157         // preamble
158         params.preamble =
159                 dialog_->preambleModule->preambleMLE->text().latin1();
160
161         // biblio
162         params.use_natbib =
163                 dialog_->biblioModule->natbibCB->isChecked();
164         params.use_numerical_citations  =
165                 dialog_->biblioModule->citeStyleCO->currentItem();
166
167         // language & quotes
168         if (dialog_->langModule->singleQuoteRB->isChecked())
169                 params.quotes_times = InsetQuotes::SingleQ;
170         else
171                 params.quotes_times = InsetQuotes::DoubleQ;
172
173
174         InsetQuotes::quote_language lga = InsetQuotes::EnglishQ;
175         switch (dialog_->langModule->quoteStyleCO->currentItem()) {
176         case 0:
177                 lga = InsetQuotes::EnglishQ;
178                 break;
179         case 1:
180                 lga = InsetQuotes::SwedishQ;
181                 break;
182         case 2:
183                 lga = InsetQuotes::GermanQ;
184                 break;
185         case 3:
186                 lga = InsetQuotes::PolishQ;
187                 break;
188         case 4:
189                 lga = InsetQuotes::FrenchQ;
190                 break;
191         case 5:
192                 lga = InsetQuotes::DanishQ;
193                 break;
194         }
195         params.quotes_language = lga;
196
197         int const pos = dialog_->langModule->languageCO->currentItem();
198         params.language = languages.getLanguage(lang_[pos]);
199
200         // numbering
201         params.secnumdepth =
202                 dialog_->numberingModule->tocDepthSB->value();
203         params.tocdepth =
204                 dialog_->numberingModule->sectionnrDepthSB->value();
205
206         // bullets
207         params.user_defined_bullets[0].setText(dialog_->bulletsModule->bullet1LE->text().latin1());
208         params.user_defined_bullets[1].setText(dialog_->bulletsModule->bullet2LE->text().latin1());
209         params.user_defined_bullets[2].setText(dialog_->bulletsModule->bullet3LE->text().latin1());
210         params.user_defined_bullets[3].setText(dialog_->bulletsModule->bullet4LE->text().latin1());
211
212         params.user_defined_bullets[0].setSize(dialog_->bulletsModule->bulletsize1CO->currentItem()-1);
213         params.user_defined_bullets[1].setSize(dialog_->bulletsModule->bulletsize2CO->currentItem()-1);
214         params.user_defined_bullets[2].setSize(dialog_->bulletsModule->bulletsize3CO->currentItem()-1);
215         params.user_defined_bullets[3].setSize(dialog_->bulletsModule->bulletsize4CO->currentItem()-1);
216
217         // packages
218         switch (dialog_->packagesModule->lspacingCO->currentItem()) {
219         case 0:
220                 params.spacing.set(Spacing::Single);
221                 break;
222         case 1:
223                 params.spacing.set(Spacing::Onehalf);
224                 break;
225         case 2:
226                 params.spacing.set(Spacing::Double);
227                 break;
228         case 3:
229                 params.spacing.set(Spacing::Other,
230                                    dialog_->packagesModule->
231                                    lspacingLE->text().toFloat()
232                                    );
233                 break;
234         }
235
236         params.graphicsDriver =
237                 dialog_->packagesModule->psdriverCO->currentText().latin1();
238
239         params.use_amsmath =
240                 dialog_->packagesModule->amsCB->isChecked();
241
242         params.inputenc =
243                 dialog_->packagesModule->encodingCO->currentText().latin1();
244
245         // layout
246         params.textclass =
247                 dialog_->layoutModule->classCO->currentItem();
248
249         //bool succes = controller().classApply();
250
251         params.fonts =
252                 dialog_->layoutModule->fontsCO->currentText().latin1();
253
254         params.fontsize =
255                 dialog_->layoutModule->fontsizeCO->currentText().latin1();
256
257         params.pagestyle =
258                 dialog_->layoutModule->pagestyleCO->currentText().latin1();
259
260         if (dialog_->layoutModule->indentRB->isChecked())
261                 params.paragraph_separation = BufferParams::PARSEP_INDENT;
262         else
263                 params.paragraph_separation = BufferParams::PARSEP_SKIP;
264
265         switch (dialog_->layoutModule->skipCO->currentItem()) {
266         case 0:
267                 params.setDefSkip(VSpace(VSpace::SMALLSKIP));
268                 break;
269         case 1:
270                 params.setDefSkip(VSpace(VSpace::MEDSKIP));
271                 break;
272         case 2:
273                 params.setDefSkip(VSpace(VSpace::BIGSKIP));
274                 break;
275         case 3:
276         {
277                 LyXLength::UNIT unit =
278                         dialog_->layoutModule->skipLengthCO->
279                         currentLengthItem();
280                 double length =
281                         dialog_->layoutModule->skipLE->text().toDouble();
282                 VSpace vs = VSpace(LyXGlueLength(LyXLength(length,unit)));
283                 params.setDefSkip(vs);
284                 break;
285         }
286         default:
287                 // DocumentDefskipCB assures that this never happens
288                 // so Assert then !!!  - jbl
289                 params.setDefSkip(VSpace(VSpace::MEDSKIP));
290                 break;
291         }
292
293         params.options =
294                 dialog_->layoutModule->optionsLE->text().latin1();
295
296         params.float_placement =
297                 dialog_->layoutModule->floatPlacementLE->text().latin1();
298
299         // paper
300         params.papersize2 =
301                 dialog_->paperModule->papersizeCO->currentItem();
302
303         params.paperwidth =
304                 LyXLength(dialog_->paperModule->paperwidthLE->text().toDouble(),
305                           dialog_->paperModule->paperwidthUnitCO->currentLengthItem()
306                         ).asString();
307
308         params.paperheight =
309                 LyXLength(dialog_->paperModule->paperheightLE->text().toDouble(),
310                           dialog_->paperModule->paperheightUnitCO->currentLengthItem()
311                         ).asString();
312
313         if (dialog_->paperModule->twoColumnCB->isChecked())
314                 params.columns = 2;
315         else
316                 params.columns = 1;
317
318         if (dialog_->paperModule->facingPagesCB->isChecked())
319                 params.sides = LyXTextClass::TwoSides;
320         else
321                 params.sides = LyXTextClass::OneSide;
322
323         if (dialog_->paperModule->landscapeRB->isChecked())
324                 params.orientation = BufferParams::ORIENTATION_LANDSCAPE;
325         else
326                 params.orientation = BufferParams::ORIENTATION_PORTRAIT;
327
328         // margins
329         params.use_geometry =
330                 (dialog_->marginsModule->marginCO->currentItem() == 1);
331
332         int margin = dialog_->marginsModule->marginCO->currentItem();
333         if (margin > 0) {
334                 margin = margin - 1;
335         }
336         params.paperpackage = char(margin);
337
338         MarginsModuleBase const * m(dialog_->marginsModule);
339
340         params.leftmargin =
341                 LyXLength(m->innerLE->text().toDouble(),
342                           m->innerUnit->currentLengthItem()
343                           ).asString();
344
345         params.topmargin =
346                 LyXLength(m->topLE->text().toDouble(),
347                           m->topUnit->currentLengthItem()
348                           ).asString();
349
350         params.rightmargin =
351                 LyXLength(m->outerLE->text().toDouble(),
352                           m->outerUnit->currentLengthItem()
353                           ).asString();
354
355         params.bottommargin =
356                 LyXLength(m->bottomLE->text().toDouble(),
357                           m->bottomUnit->currentLengthItem()
358                           ).asString();
359
360         params.headheight =
361                 LyXLength(m->headheightLE->text().toDouble(),
362                           m->headheightUnit->currentLengthItem()
363                           ).asString();
364
365         params.headsep =
366                 LyXLength(m->headsepLE->text().toDouble(),
367                           m->headsepUnit->currentLengthItem()
368                           ).asString();
369
370         params.footskip =
371                 LyXLength(m->footskipLE->text().toDouble(),
372                           m->footskipUnit->currentLengthItem()
373                           ).asString();
374 }
375
376
377 namespace {
378
379 /** Return the position of val in the vector if found.
380     If not found, return 0.
381  */
382 template<class A>
383 typename std::vector<A>::size_type
384 findPos(std::vector<A> const & vec, A const & val)
385 {
386         typename std::vector<A>::const_iterator it =
387                 std::find(vec.begin(), vec.end(), val);
388         if (it == vec.end())
389                 return 0;
390         return std::distance(vec.begin(), it);
391 }
392
393 } // namespace anom
394
395
396 void QDocument::update_contents()
397 {
398         if (!dialog_.get())
399                 return;
400
401         BufferParams const & params = controller().params();
402
403         // preamble
404         QString preamble = params.preamble.c_str();
405         dialog_->preambleModule->preambleMLE->setText(preamble);
406
407         // biblio
408         dialog_->biblioModule->natbibCB->setChecked(
409                 params.use_natbib);
410         dialog_->biblioModule->citeStyleCO->setCurrentItem(
411                 params.use_numerical_citations ? 1 : 0);
412
413         // language & quotes
414         dialog_->langModule->singleQuoteRB->setChecked(
415                 params.quotes_times == InsetQuotes::SingleQ);
416         dialog_->langModule->doubleQuoteRB->setChecked(
417                 params.quotes_times == InsetQuotes::DoubleQ);
418
419         int const pos = int(findPos(lang_,
420                                     params.language->lang()));
421         dialog_->langModule->languageCO->setCurrentItem(pos);
422
423         dialog_->langModule->quoteStyleCO->setCurrentItem(
424                 params.quotes_language);
425
426         // numbering
427         dialog_->numberingModule->tocDepthSB->setValue(
428                 params.secnumdepth);
429         dialog_->numberingModule->sectionnrDepthSB->setValue(
430                 params.tocdepth);
431
432         // bullets
433         QString s;
434         s = params.user_defined_bullets[0].getText().c_str();
435         dialog_->bulletsModule->bullet1LE->setText(s);
436         s = params.user_defined_bullets[1].getText().c_str();
437         dialog_->bulletsModule->bullet2LE->setText(s);
438         s = params.user_defined_bullets[2].getText().c_str();
439         dialog_->bulletsModule->bullet3LE->setText(s);
440         s = params.user_defined_bullets[3].getText().c_str();
441         dialog_->bulletsModule->bullet4LE->setText(s);
442
443         dialog_->bulletsModule->bulletsize1CO->setCurrentItem(
444                 params.user_defined_bullets[0].getSize() + 1);
445         dialog_->bulletsModule->bulletsize2CO->setCurrentItem(
446                 params.user_defined_bullets[1].getSize() + 1);
447         dialog_->bulletsModule->bulletsize3CO->setCurrentItem(
448                 params.user_defined_bullets[2].getSize() + 1);
449         dialog_->bulletsModule->bulletsize4CO->setCurrentItem(
450                 params.user_defined_bullets[3].getSize() + 1);
451
452         // packages
453         char const * enc[] = {
454                 "default" , "auto" , "latin1" , "latin2" , "latin3" ,
455                 "latin4" , "latin5" , "latin9" , "koi8-r" , "koi8-u" ,
456                 "cp866" , "cp1251" , "iso88595" , "pt154" };
457         for (size_t i = 0; i < sizeof(enc)/sizeof(char *); ++i) {
458                 if (params.inputenc == enc[i])
459                         dialog_->packagesModule->encodingCO->setCurrentItem(i);
460         }
461
462         QString text = params.graphicsDriver.c_str();
463         int nitem = dialog_->packagesModule->psdriverCO->count();
464         for (int n = 0; n < nitem ; ++n) {
465                 QString enc = tex_graphics[n];
466                 if (enc == text) {
467                         dialog_->packagesModule->psdriverCO->setCurrentItem(n);
468                 }
469         }
470
471
472         dialog_->packagesModule->amsCB->setChecked(
473                 params.use_amsmath);
474
475         switch (params.spacing.getSpace()) {
476                 case Spacing::Other: nitem = 3; break;
477                 case Spacing::Double: nitem = 2; break;
478                 case Spacing::Onehalf: nitem = 1; break;
479                 case Spacing::Default: case Spacing::Single: nitem = 0; break;
480         }
481
482         dialog_->packagesModule->lspacingCO->setCurrentItem(nitem);
483         if (params.spacing.getSpace() == Spacing::Other) {
484                 dialog_->packagesModule->lspacingLE->setText(
485                         tostr(params.spacing.getValue()).c_str());
486                 dialog_->setLSpacing(3);
487         }
488
489         // layout
490         for (int n = 0; n<dialog_->layoutModule->classCO->count(); ++n) {
491                 if (dialog_->layoutModule->classCO->text(n) ==
492                     controller().textClass().description().c_str()) {
493                         dialog_->layoutModule->classCO->setCurrentItem(n);
494                         break;
495                 }
496         }
497
498         dialog_->updateFontsize(controller().textClass().opt_fontsize(),
499                                 params.fontsize);
500
501         dialog_->updatePagestyle(controller().textClass().opt_pagestyle(),
502                                  params.pagestyle);
503
504         for (int n = 0; tex_fonts[n][0]; ++n) {
505                 if (tex_fonts[n] == params.fonts) {
506                         dialog_->layoutModule->fontsCO->setCurrentItem(n);
507                         break;
508                 }
509         }
510
511         if (params.paragraph_separation
512             == BufferParams::PARSEP_INDENT) {
513                 dialog_->layoutModule->indentRB->setChecked(true);
514         } else {
515                 dialog_->layoutModule->skipRB->setChecked(true);
516         }
517
518         int skip = 0;
519         switch (params.getDefSkip().kind()) {
520         case VSpace::SMALLSKIP:
521                 skip = 0;
522                 break;
523         case VSpace::MEDSKIP:
524                 skip = 1;
525                 break;
526         case VSpace::BIGSKIP:
527                 skip = 2;
528                 break;
529         case VSpace::LENGTH:
530         {
531                 skip = 3;
532                 string const length = params.getDefSkip().asLyXCommand();
533                 dialog_->layoutModule->skipLengthCO->setCurrentItem(LyXLength(length).unit());
534                 dialog_->layoutModule->skipLE->setText(tostr(LyXLength(length).value()).c_str());
535                 break;
536         }
537         default:
538                 skip = 0;
539                 break;
540         }
541         dialog_->layoutModule->skipCO->setCurrentItem(skip);
542         dialog_->setSkip(skip);
543
544         if (!params.options.empty()) {
545                 dialog_->layoutModule->optionsLE->setText(
546                         params.options.c_str());
547         } else {
548                 dialog_->layoutModule->optionsLE->setText("");
549         }
550
551         // paper
552         int const psize = params.papersize2;
553         dialog_->paperModule->papersizeCO->setCurrentItem(psize);
554         dialog_->setMargins(psize);
555         dialog_->setCustomPapersize(psize);
556
557         bool const landscape =
558                 params.orientation == BufferParams::ORIENTATION_LANDSCAPE;
559         dialog_->paperModule->landscapeRB->setChecked(landscape);
560         dialog_->paperModule->portraitRB->setChecked(!landscape);
561
562         dialog_->paperModule->facingPagesCB->setChecked(
563                 params.sides == LyXTextClass::TwoSides);
564
565         dialog_->paperModule->twoColumnCB->setChecked(
566                 params.columns == 2);
567
568         dialog_->paperModule->paperwidthUnitCO->setCurrentItem(
569                 LyXLength(params.paperwidth).unit());
570
571         dialog_->paperModule->paperwidthLE->setText(
572                 tostr(LyXLength(params.paperwidth).value()).c_str());
573
574         dialog_->paperModule->paperheightUnitCO->setCurrentItem(
575                 LyXLength(params.paperheight).unit());
576
577         dialog_->paperModule->paperheightLE->setText(
578                 tostr(LyXLength(params.paperheight).value()).c_str());
579
580         // margins
581
582         MarginsModuleBase * m(dialog_->marginsModule);
583
584         int item = params.paperpackage;
585         if (params.use_geometry) {
586                 item = 1;
587         } else if (item > 0) {
588                 item = item + 1;
589         }
590         m->marginCO->setCurrentItem(item);
591         dialog_->setCustomMargins(item);
592
593         m->topUnit->setCurrentItem(LyXLength(params.topmargin).unit());
594         m->topLE->setText(tostr(LyXLength(params.topmargin).value()).c_str());
595
596         m->bottomUnit->setCurrentItem(LyXLength(params.bottommargin).unit());
597         m->bottomLE->setText(tostr(LyXLength(params.bottommargin).value()).c_str());
598
599         m->innerUnit->setCurrentItem(LyXLength(params.leftmargin).unit());
600         m->innerLE->setText(tostr(LyXLength(params.leftmargin).value()).c_str());
601
602         m->outerUnit->setCurrentItem(LyXLength(params.rightmargin).unit());
603         m->outerLE->setText(tostr(LyXLength(params.rightmargin).value()).c_str());
604
605         m->headheightUnit->setCurrentItem(LyXLength(params.headheight).unit());
606         m->headheightLE->setText(tostr(LyXLength(params.headheight).value()).c_str());
607
608         m->headsepUnit->setCurrentItem(LyXLength(params.headsep).unit());
609         m->headsepLE->setText(tostr(LyXLength(params.headsep).value()).c_str());
610
611         m->footskipUnit->setCurrentItem(LyXLength(params.footskip).unit());
612         m->footskipLE->setText(tostr(LyXLength(params.footskip).value()).c_str());
613 }
614
615
616 void QDocument::saveDocDefault()
617 {
618         // we have to apply the params first
619         apply();
620         controller().saveAsDefault();
621 }
622
623
624 void QDocument::useClassDefaults()
625 {
626         BufferParams & params = controller().params();
627
628         params.textclass = dialog_->layoutModule->classCO->currentItem();
629         params.useClassDefaults();
630         update_contents();
631 }