]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiPrefs.cpp
clear the pixmap cache and the font metrics cache in case of zoom or dpi changes.
[lyx.git] / src / frontends / qt4 / GuiPrefs.cpp
1 /**
2  * \file GuiPrefs.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author John Levon
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "GuiPrefs.h"
14
15 #include "qt_helpers.h"
16 #include "GuiApplication.h"
17 #include "GuiFontLoader.h"
18
19 #include "BufferList.h"
20 #include "Color.h"
21 #include "ConverterCache.h"
22 #include "debug.h"
23 #include "Font.h"
24 #include "FuncRequest.h"
25 #include "gettext.h"
26 #include "GuiFontExample.h"
27 #include "PanelStack.h"
28 #include "paper.h"
29 #include "Session.h"
30
31 #include "support/lstrings.h"
32 #include "support/os.h"
33 #include "support/FileFilterList.h"
34
35 #include "frontend_helpers.h"
36
37 #include "frontends/alert.h"
38 #include "frontends/Application.h"
39
40 #include <QCheckBox>
41 #include <QColorDialog>
42 #include <QFontDatabase>
43 #include <QLineEdit>
44 #include <QPixmapCache>
45 #include <QPushButton>
46 #include <QSpinBox>
47 #include <QString>
48 #include <QValidator>
49 #include <QCloseEvent>
50
51 #include <iomanip>
52 #include <sstream>
53 #include <algorithm>
54 #include <utility>
55
56 using namespace Ui;
57
58 using std::endl;
59 using std::ostringstream;
60 using std::pair;
61 using std::string;
62 using std::vector;
63
64 namespace lyx {
65 namespace frontend {
66
67 using support::compare_ascii_no_case;
68 using support::os::external_path;
69 using support::os::external_path_list;
70 using support::os::internal_path;
71 using support::os::internal_path_list;
72 using support::FileFilterList;
73
74
75 /////////////////////////////////////////////////////////////////////
76 //
77 // Helpers
78 //
79 /////////////////////////////////////////////////////////////////////
80
81 template<class A>
82 static size_t findPos_helper(std::vector<A> const & vec, A const & val)
83 {
84         typedef typename std::vector<A>::const_iterator Cit;
85
86         Cit it = std::find(vec.begin(), vec.end(), val);
87         if (it == vec.end())
88                 return 0;
89         return std::distance(vec.begin(), it);
90 }
91
92
93 static std::pair<string, string> parseFontName(string const & name)
94 {
95         string::size_type const idx = name.find('[');
96         if (idx == string::npos || idx == 0)
97                 return make_pair(name, string());
98         return make_pair(name.substr(0, idx - 1),
99                          name.substr(idx + 1, name.size() - idx - 2));
100 }
101
102
103 static void setComboxFont(QComboBox * cb, string const & family,
104         string const & foundry)
105 {
106         QString fontname = toqstr(family);
107         if (!foundry.empty())
108                 fontname += " [" + toqstr(foundry) + ']';
109
110         for (int i = 0; i < cb->count(); ++i) {
111                 if (cb->itemText(i) == fontname) {
112                         cb->setCurrentIndex(i);
113                         return;
114                 }
115         }
116
117         // Try matching without foundry name
118
119         // We count in reverse in order to prefer the Xft foundry
120         for (int i = cb->count(); --i >= 0;) {
121                 pair<string, string> tmp = parseFontName(fromqstr(cb->itemText(i)));
122                 if (compare_ascii_no_case(tmp.first, family) == 0) {
123                         cb->setCurrentIndex(i);
124                         return;
125                 }
126         }
127
128         // family alone can contain e.g. "Helvetica [Adobe]"
129         pair<string, string> tmpfam = parseFontName(family);
130
131         // We count in reverse in order to prefer the Xft foundry
132         for (int i = cb->count() - 1; i >= 0; --i) {
133                 pair<string, string> tmp = parseFontName(fromqstr(cb->itemText(i)));
134                 if (compare_ascii_no_case(tmp.first, tmpfam.first) == 0) {
135                         cb->setCurrentIndex(i);
136                         return;
137                 }
138         }
139
140         // Bleh, default fonts, and the names couldn't be found. Hack
141         // for bug 1063.
142
143         QFont font;
144         font.setKerning(false);
145
146         if (family == theApp()->romanFontName()) {
147                 font.setStyleHint(QFont::Serif);
148                 font.setFamily(family.c_str());
149         } else if (family == theApp()->sansFontName()) {
150                 font.setStyleHint(QFont::SansSerif);
151                 font.setFamily(family.c_str());
152         } else if (family == theApp()->typewriterFontName()) {
153                 font.setStyleHint(QFont::TypeWriter);
154                 font.setFamily(family.c_str());
155         } else {
156                 lyxerr << "FAILED to find the default font: '"
157                        << foundry << "', '" << family << '\''<< endl;
158                 return;
159         }
160
161         QFontInfo info(font);
162         pair<string, string> tmp = parseFontName(fromqstr(info.family()));
163         string const & default_font_name = tmp.first;
164         lyxerr << "Apparent font is " << default_font_name << endl;
165
166         for (int i = 0; i < cb->count(); ++i) {
167                 lyxerr << "Looking at " << fromqstr(cb->itemText(i)) << endl;
168                 if (compare_ascii_no_case(fromqstr(cb->itemText(i)),
169                                     default_font_name) == 0) {
170                         cb->setCurrentIndex(i);
171                         return;
172                 }
173         }
174
175         lyxerr << "FAILED to find the font: '"
176                << foundry << "', '" << family << '\'' <<endl;
177 }
178
179
180 /////////////////////////////////////////////////////////////////////
181 //
182 // PrefPlaintext
183 //
184 /////////////////////////////////////////////////////////////////////
185
186 PrefPlaintext::PrefPlaintext(QWidget * parent)
187         : PrefModule(_("Plain text"), 0, parent)
188 {
189         setupUi(this);
190         connect(plaintextLinelengthSB, SIGNAL(valueChanged(int)),
191                 this, SIGNAL(changed()));
192         connect(plaintextRoffED, SIGNAL(textChanged(const QString&)),
193                 this, SIGNAL(changed()));
194 }
195
196
197 void PrefPlaintext::apply(LyXRC & rc) const
198 {
199         rc.plaintext_linelen = plaintextLinelengthSB->value();
200         rc.plaintext_roff_command = fromqstr(plaintextRoffED->text());
201 }
202
203
204 void PrefPlaintext::update(LyXRC const & rc)
205 {
206         plaintextLinelengthSB->setValue(rc.plaintext_linelen);
207         plaintextRoffED->setText(toqstr(rc.plaintext_roff_command));
208 }
209
210
211 /////////////////////////////////////////////////////////////////////
212 //
213 // PrefDate
214 //
215 /////////////////////////////////////////////////////////////////////
216
217 PrefDate::PrefDate(QWidget * parent)
218         : PrefModule(_("Date format"), 0, parent)
219 {
220         setupUi(this);
221         connect(DateED, SIGNAL(textChanged(const QString &)),
222                 this, SIGNAL(changed()));
223 }
224
225
226 void PrefDate::apply(LyXRC & rc) const
227 {
228         rc.date_insert_format = fromqstr(DateED->text());
229 }
230
231
232 void PrefDate::update(LyXRC const & rc)
233 {
234         DateED->setText(toqstr(rc.date_insert_format));
235 }
236
237
238 /////////////////////////////////////////////////////////////////////
239 //
240 // PrefKeyboard
241 //
242 /////////////////////////////////////////////////////////////////////
243
244 PrefKeyboard::PrefKeyboard(GuiPreferences * form, QWidget * parent)
245         : PrefModule(_("Keyboard"), form, parent)
246 {
247         setupUi(this);
248
249         connect(keymapCB, SIGNAL(clicked()),
250                 this, SIGNAL(changed()));
251         connect(firstKeymapED, SIGNAL(textChanged(const QString&)),
252                 this, SIGNAL(changed()));
253         connect(secondKeymapED, SIGNAL(textChanged(const QString&)),
254                 this, SIGNAL(changed()));
255 }
256
257
258 void PrefKeyboard::apply(LyXRC & rc) const
259 {
260         // FIXME: can derive CB from the two EDs
261         rc.use_kbmap = keymapCB->isChecked();
262         rc.primary_kbmap = internal_path(fromqstr(firstKeymapED->text()));
263         rc.secondary_kbmap = internal_path(fromqstr(secondKeymapED->text()));
264 }
265
266
267 void PrefKeyboard::update(LyXRC const & rc)
268 {
269         // FIXME: can derive CB from the two EDs
270         keymapCB->setChecked(rc.use_kbmap);
271         firstKeymapED->setText(toqstr(external_path(rc.primary_kbmap)));
272         secondKeymapED->setText(toqstr(external_path(rc.secondary_kbmap)));
273 }
274
275
276 QString PrefKeyboard::testKeymap(QString keymap)
277 {
278         return toqstr(form_->browsekbmap(from_utf8(internal_path(fromqstr(keymap)))));
279 }
280
281
282 void PrefKeyboard::on_firstKeymapPB_clicked(bool)
283 {
284         QString const file = testKeymap(firstKeymapED->text());
285         if (!file.isEmpty())
286                 firstKeymapED->setText(file);
287 }
288
289
290 void PrefKeyboard::on_secondKeymapPB_clicked(bool)
291 {
292         QString const file = testKeymap(secondKeymapED->text());
293         if (!file.isEmpty())
294                 secondKeymapED->setText(file);
295 }
296
297
298 void PrefKeyboard::on_keymapCB_toggled(bool keymap)
299 {
300         firstKeymapLA->setEnabled(keymap);
301         secondKeymapLA->setEnabled(keymap);
302         firstKeymapED->setEnabled(keymap);
303         secondKeymapED->setEnabled(keymap);
304         firstKeymapPB->setEnabled(keymap);
305         secondKeymapPB->setEnabled(keymap);
306 }
307
308
309 /////////////////////////////////////////////////////////////////////
310 //
311 // PrefLatex
312 //
313 /////////////////////////////////////////////////////////////////////
314
315 PrefLatex::PrefLatex(GuiPreferences * form, QWidget * parent)
316         : PrefModule(_("LaTeX"), form, parent)
317 {
318         setupUi(this);
319         connect(latexEncodingED, SIGNAL(textChanged(const QString&)),
320                 this, SIGNAL(changed()));
321         connect(latexChecktexED, SIGNAL(textChanged(const QString&)),
322                 this, SIGNAL(changed()));
323         connect(latexBibtexED, SIGNAL(textChanged(const QString&)),
324                 this, SIGNAL(changed()));
325         connect(latexIndexED, SIGNAL(textChanged(const QString&)),
326                 this, SIGNAL(changed()));
327         connect(latexAutoresetCB, SIGNAL(clicked()),
328                 this, SIGNAL(changed()));
329         connect(latexDviPaperED, SIGNAL(textChanged(const QString&)),
330                 this, SIGNAL(changed()));
331         connect(latexPaperSizeCO, SIGNAL(activated(int)),
332                 this, SIGNAL(changed()));
333
334 #if defined(__CYGWIN__) || defined(_WIN32)
335         pathCB->setVisible(true);
336         connect(pathCB, SIGNAL(clicked()), 
337                 this, SIGNAL(changed()));
338 #else
339         pathCB->setVisible(false);
340 #endif
341 }
342
343
344 void PrefLatex::apply(LyXRC & rc) const
345 {
346         rc.fontenc = fromqstr(latexEncodingED->text());
347         rc.chktex_command = fromqstr(latexChecktexED->text());
348         rc.bibtex_command = fromqstr(latexBibtexED->text());
349         rc.index_command = fromqstr(latexIndexED->text());
350         rc.auto_reset_options = latexAutoresetCB->isChecked();
351         rc.view_dvi_paper_option = fromqstr(latexDviPaperED->text());
352         rc.default_papersize =
353                 form_->toPaperSize(latexPaperSizeCO->currentIndex());
354 #if defined(__CYGWIN__) || defined(_WIN32)
355         rc.windows_style_tex_paths = pathCB->isChecked();
356 #endif
357 }
358
359
360 void PrefLatex::update(LyXRC const & rc)
361 {
362         latexEncodingED->setText(toqstr(rc.fontenc));
363         latexChecktexED->setText(toqstr(rc.chktex_command));
364         latexBibtexED->setText(toqstr(rc.bibtex_command));
365         latexIndexED->setText(toqstr(rc.index_command));
366         latexAutoresetCB->setChecked(rc.auto_reset_options);
367         latexDviPaperED->setText(toqstr(rc.view_dvi_paper_option));
368         latexPaperSizeCO->setCurrentIndex(
369                 form_->fromPaperSize(rc.default_papersize));
370 #if defined(__CYGWIN__) || defined(_WIN32)
371         pathCB->setChecked(rc.windows_style_tex_paths);
372 #endif
373 }
374
375
376 /////////////////////////////////////////////////////////////////////
377 //
378 // PrefScreenFonts
379 //
380 /////////////////////////////////////////////////////////////////////
381
382 PrefScreenFonts::PrefScreenFonts(GuiPreferences * form, QWidget * parent)
383         : PrefModule(_("Screen fonts"), form, parent)
384 {
385         setupUi(this);
386
387         connect(screenRomanCO, SIGNAL(activated(const QString&)),
388                 this, SLOT(select_roman(const QString&)));
389         connect(screenSansCO, SIGNAL(activated(const QString&)),
390                 this, SLOT(select_sans(const QString&)));
391         connect(screenTypewriterCO, SIGNAL(activated(const QString&)),
392                 this, SLOT(select_typewriter(const QString&)));
393
394         QFontDatabase fontdb;
395         QStringList families(fontdb.families());
396         for (QStringList::Iterator it = families.begin(); it != families.end(); ++it) {
397                 screenRomanCO->addItem(*it);
398                 screenSansCO->addItem(*it);
399                 screenTypewriterCO->addItem(*it);
400         }
401         connect(screenRomanCO, SIGNAL(activated(const QString&)),
402                 this, SIGNAL(changed()));
403         connect(screenSansCO, SIGNAL(activated(const QString&)),
404                 this, SIGNAL(changed()));
405         connect(screenTypewriterCO, SIGNAL(activated(const QString&)),
406                 this, SIGNAL(changed()));
407         connect(screenZoomSB, SIGNAL(valueChanged(int)),
408                 this, SIGNAL(changed()));
409         connect(screenDpiSB, SIGNAL(valueChanged(int)),
410                 this, SIGNAL(changed()));
411         connect(screenTinyED, SIGNAL(textChanged(const QString&)),
412                 this, SIGNAL(changed()));
413         connect(screenSmallestED, SIGNAL(textChanged(const QString&)),
414                 this, SIGNAL(changed()));
415         connect(screenSmallerED, SIGNAL(textChanged(const QString&)),
416                 this, SIGNAL(changed()));
417         connect(screenSmallED, SIGNAL(textChanged(const QString&)),
418                 this, SIGNAL(changed()));
419         connect(screenNormalED, SIGNAL(textChanged(const QString&)),
420                 this, SIGNAL(changed()));
421         connect(screenLargeED, SIGNAL(textChanged(const QString&)),
422                 this, SIGNAL(changed()));
423         connect(screenLargerED, SIGNAL(textChanged(const QString&)),
424                 this, SIGNAL(changed()));
425         connect(screenLargestED, SIGNAL(textChanged(const QString&)),
426                 this, SIGNAL(changed()));
427         connect(screenHugeED, SIGNAL(textChanged(const QString&)),
428                 this, SIGNAL(changed()));
429         connect(screenHugerED, SIGNAL(textChanged(const QString&)),
430                 this, SIGNAL(changed()));
431
432         screenTinyED->setValidator(new QDoubleValidator(screenTinyED));
433         screenSmallestED->setValidator(new QDoubleValidator(screenSmallestED));
434         screenSmallerED->setValidator(new QDoubleValidator(screenSmallerED));
435         screenSmallED->setValidator(new QDoubleValidator(screenSmallED));
436         screenNormalED->setValidator(new QDoubleValidator(screenNormalED));
437         screenLargeED->setValidator(new QDoubleValidator(screenLargeED));
438         screenLargerED->setValidator(new QDoubleValidator(screenLargerED));
439         screenLargestED->setValidator(new QDoubleValidator(screenLargestED));
440         screenHugeED->setValidator(new QDoubleValidator(screenHugeED));
441         screenHugerED->setValidator(new QDoubleValidator(screenHugerED));
442 }
443
444
445 void PrefScreenFonts::apply(LyXRC & rc) const
446 {
447         LyXRC const oldrc(rc);
448
449         boost::tie(rc.roman_font_name, rc.roman_font_foundry)
450                 = parseFontName(fromqstr(screenRomanCO->currentText()));
451         boost::tie(rc.sans_font_name, rc.sans_font_foundry) =
452                 parseFontName(fromqstr(screenSansCO->currentText()));
453         boost::tie(rc.typewriter_font_name, rc.typewriter_font_foundry) =
454                 parseFontName(fromqstr(screenTypewriterCO->currentText()));
455
456         rc.zoom = screenZoomSB->value();
457         rc.dpi = screenDpiSB->value();
458         rc.font_sizes[Font::SIZE_TINY] = fromqstr(screenTinyED->text());
459         rc.font_sizes[Font::SIZE_SCRIPT] = fromqstr(screenSmallestED->text());
460         rc.font_sizes[Font::SIZE_FOOTNOTE] = fromqstr(screenSmallerED->text());
461         rc.font_sizes[Font::SIZE_SMALL] = fromqstr(screenSmallED->text());
462         rc.font_sizes[Font::SIZE_NORMAL] = fromqstr(screenNormalED->text());
463         rc.font_sizes[Font::SIZE_LARGE] = fromqstr(screenLargeED->text());
464         rc.font_sizes[Font::SIZE_LARGER] = fromqstr(screenLargerED->text());
465         rc.font_sizes[Font::SIZE_LARGEST] = fromqstr(screenLargestED->text());
466         rc.font_sizes[Font::SIZE_HUGE] = fromqstr(screenHugeED->text());
467         rc.font_sizes[Font::SIZE_HUGER] = fromqstr(screenHugerED->text());
468
469         if (rc.font_sizes != oldrc.font_sizes
470                 || rc.roman_font_name != oldrc.roman_font_name
471                 || rc.sans_font_name != oldrc.sans_font_name
472                 || rc.typewriter_font_name != oldrc.typewriter_font_name
473                 || rc.zoom != oldrc.zoom || rc.dpi != oldrc.dpi) {
474                 // The global QPixmapCache is used in GuiPainter to cache text
475                 // painting so we must reset it in case any of the above
476                 // parameter is changed.
477                 QPixmapCache::clear();
478                 guiApp->fontLoader().update();
479                 form_->updateScreenFonts();
480         }
481 }
482
483
484 void PrefScreenFonts::update(LyXRC const & rc)
485 {
486         setComboxFont(screenRomanCO, rc.roman_font_name,
487                         rc.roman_font_foundry);
488         setComboxFont(screenSansCO, rc.sans_font_name,
489                         rc.sans_font_foundry);
490         setComboxFont(screenTypewriterCO, rc.typewriter_font_name,
491                         rc.typewriter_font_foundry);
492
493         select_roman(screenRomanCO->currentText());
494         select_sans(screenSansCO->currentText());
495         select_typewriter(screenTypewriterCO->currentText());
496
497         screenZoomSB->setValue(rc.zoom);
498         screenDpiSB->setValue(rc.dpi);
499         screenTinyED->setText(toqstr(rc.font_sizes[Font::SIZE_TINY]));
500         screenSmallestED->setText(toqstr(rc.font_sizes[Font::SIZE_SCRIPT]));
501         screenSmallerED->setText(toqstr(rc.font_sizes[Font::SIZE_FOOTNOTE]));
502         screenSmallED->setText(toqstr(rc.font_sizes[Font::SIZE_SMALL]));
503         screenNormalED->setText(toqstr(rc.font_sizes[Font::SIZE_NORMAL]));
504         screenLargeED->setText(toqstr(rc.font_sizes[Font::SIZE_LARGE]));
505         screenLargerED->setText(toqstr(rc.font_sizes[Font::SIZE_LARGER]));
506         screenLargestED->setText(toqstr(rc.font_sizes[Font::SIZE_LARGEST]));
507         screenHugeED->setText(toqstr(rc.font_sizes[Font::SIZE_HUGE]));
508         screenHugerED->setText(toqstr(rc.font_sizes[Font::SIZE_HUGER]));
509 }
510
511 void PrefScreenFonts::select_roman(const QString& name)
512 {
513         screenRomanFE->set(QFont(name), name);
514 }
515
516
517 void PrefScreenFonts::select_sans(const QString& name)
518 {
519         screenSansFE->set(QFont(name), name);
520 }
521
522
523 void PrefScreenFonts::select_typewriter(const QString& name)
524 {
525         screenTypewriterFE->set(QFont(name), name);
526 }
527
528
529 /////////////////////////////////////////////////////////////////////
530 //
531 // PrefColors
532 //
533 /////////////////////////////////////////////////////////////////////
534
535 namespace {
536
537 struct ColorSorter
538 {
539         bool operator()(Color::color const & lhs, Color::color const & rhs) const {
540                 return lcolor.getGUIName(lhs) < lcolor.getGUIName(rhs);
541         }
542 };
543
544 } // namespace anon
545
546 PrefColors::PrefColors(GuiPreferences * form, QWidget * parent)
547         : PrefModule( _("Colors"), form, parent)
548 {
549         setupUi(this);
550
551         // FIXME: all of this initialization should be put into the controller.
552         // See http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg113301.html
553         // for some discussion of why that is not trivial.
554         QPixmap icon(32, 32);
555         for (int i = 0; i < Color::ignore; ++i) {
556                 Color::color lc = static_cast<Color::color>(i);
557                 if (lc == Color::none
558                         || lc == Color::black
559                         || lc == Color::white
560                         || lc == Color::red
561                         || lc == Color::green
562                         || lc == Color::blue
563                         || lc == Color::cyan
564                         || lc == Color::magenta
565                         || lc == Color::yellow
566                         || lc == Color::inherit
567                         || lc == Color::ignore) continue;
568
569                 lcolors_.push_back(lc);
570         }
571         std::sort(lcolors_.begin(), lcolors_.end(), ColorSorter());
572         vector<Color_color>::const_iterator cit = lcolors_.begin();
573         vector<Color_color>::const_iterator const end = lcolors_.end();
574         for (; cit != end; ++cit) {
575                         (void) new QListWidgetItem(QIcon(icon),
576                         toqstr(lcolor.getGUIName(*cit)), lyxObjectsLW);
577         }
578         curcolors_.resize(lcolors_.size());
579         newcolors_.resize(lcolors_.size());
580         // End initialization
581
582         connect(colorChangePB, SIGNAL(clicked()),
583                 this, SLOT(change_color()));
584         connect(lyxObjectsLW, SIGNAL(itemSelectionChanged()),
585                 this, SLOT(change_lyxObjects_selection()));
586         connect(lyxObjectsLW, SIGNAL(itemActivated(QListWidgetItem*)),
587                 this, SLOT(change_color()));
588 }
589
590
591 void PrefColors::apply(LyXRC & /*rc*/) const
592 {
593         for (unsigned int i = 0; i < lcolors_.size(); ++i)
594                 if (curcolors_[i] != newcolors_[i])
595                         form_->setColor(lcolors_[i], fromqstr(newcolors_[i]));
596 }
597
598
599 void PrefColors::update(LyXRC const & /*rc*/)
600 {
601         for (unsigned int i = 0; i < lcolors_.size(); ++i) {
602                 QColor color = QColor(guiApp->colorCache().get(lcolors_[i]));
603                 QPixmap coloritem(32, 32);
604                 coloritem.fill(color);
605                 lyxObjectsLW->item(i)->setIcon(QIcon(coloritem));
606                 newcolors_[i] = curcolors_[i] = color.name();
607         }
608         change_lyxObjects_selection();
609 }
610
611 void PrefColors::change_color()
612 {
613         int const row = lyxObjectsLW->currentRow();
614
615         // just to be sure
616         if (row < 0)
617                 return;
618
619         QString const color = newcolors_[row];
620         QColor c = QColorDialog::getColor(QColor(color), qApp->focusWidget());
621
622         if (c.isValid() && c.name() != color) {
623                 newcolors_[row] = c.name();
624                 QPixmap coloritem(32, 32);
625                 coloritem.fill(c);
626                 lyxObjectsLW->currentItem()->setIcon(QIcon(coloritem));
627                 // emit signal
628                 changed();
629         }
630 }
631
632 void PrefColors::change_lyxObjects_selection()
633 {
634         colorChangePB->setDisabled(lyxObjectsLW->currentRow() < 0);
635 }
636
637
638 /////////////////////////////////////////////////////////////////////
639 //
640 // PrefDisplay
641 //
642 /////////////////////////////////////////////////////////////////////
643
644 PrefDisplay::PrefDisplay(QWidget * parent)
645         : PrefModule(_("Graphics"), 0, parent)
646 {
647         setupUi(this);
648         connect(instantPreviewCO, SIGNAL(activated(int)),
649                 this, SIGNAL(changed()));
650         connect(displayGraphicsCO, SIGNAL(activated(int)),
651                 this, SIGNAL(changed()));
652 }
653
654
655 void PrefDisplay::apply(LyXRC & rc) const
656 {
657         switch (instantPreviewCO->currentIndex()) {
658                 case 0: rc.preview = LyXRC::PREVIEW_OFF; break;
659                 case 1: rc.preview = LyXRC::PREVIEW_NO_MATH; break;
660                 case 2: rc.preview = LyXRC::PREVIEW_ON; break;
661         }
662
663         lyx::graphics::DisplayType dtype;
664         switch (displayGraphicsCO->currentIndex()) {
665                 case 3: dtype = lyx::graphics::NoDisplay; break;
666                 case 2: dtype = lyx::graphics::ColorDisplay; break;
667                 case 1: dtype = lyx::graphics::GrayscaleDisplay;        break;
668                 case 0: dtype = lyx::graphics::MonochromeDisplay; break;
669                 default: dtype = lyx::graphics::GrayscaleDisplay;
670         }
671         rc.display_graphics = dtype;
672
673         // FIXME!! The graphics cache no longer has a changeDisplay method.
674 #if 0
675         if (old_value != rc.display_graphics) {
676                 lyx::graphics::GCache & gc = lyx::graphics::GCache::get();
677                 gc.changeDisplay();
678         }
679 #endif
680 }
681
682
683 void PrefDisplay::update(LyXRC const & rc)
684 {
685         switch (rc.preview) {
686         case LyXRC::PREVIEW_OFF:
687                 instantPreviewCO->setCurrentIndex(0);
688                 break;
689         case LyXRC::PREVIEW_NO_MATH :
690                 instantPreviewCO->setCurrentIndex(1);
691                 break;
692         case LyXRC::PREVIEW_ON :
693                 instantPreviewCO->setCurrentIndex(2);
694                 break;
695         }
696
697         int item = 2;
698         switch (rc.display_graphics) {
699                 case lyx::graphics::NoDisplay:          item = 3; break;
700                 case lyx::graphics::ColorDisplay:       item = 2; break;
701                 case lyx::graphics::GrayscaleDisplay:   item = 1; break;
702                 case lyx::graphics::MonochromeDisplay:  item = 0; break;
703                 default: break;
704         }
705         displayGraphicsCO->setCurrentIndex(item);
706 }
707
708
709 /////////////////////////////////////////////////////////////////////
710 //
711 // PrefPaths
712 //
713 /////////////////////////////////////////////////////////////////////
714
715 PrefPaths::PrefPaths(GuiPreferences * form, QWidget * parent)
716         : PrefModule(_("Paths"), form, parent)
717 {
718         setupUi(this);
719         connect(templateDirPB, SIGNAL(clicked()), this, SLOT(select_templatedir()));
720         connect(tempDirPB, SIGNAL(clicked()), this, SLOT(select_tempdir()));
721         connect(backupDirPB, SIGNAL(clicked()), this, SLOT(select_backupdir()));
722         connect(workingDirPB, SIGNAL(clicked()), this, SLOT(select_workingdir()));
723         connect(lyxserverDirPB, SIGNAL(clicked()), this, SLOT(select_lyxpipe()));
724         connect(workingDirED, SIGNAL(textChanged(const QString&)),
725                 this, SIGNAL(changed()));
726         connect(templateDirED, SIGNAL(textChanged(const QString&)),
727                 this, SIGNAL(changed()));
728         connect(backupDirED, SIGNAL(textChanged(const QString&)),
729                 this, SIGNAL(changed()));
730         connect(tempDirED, SIGNAL(textChanged(const QString&)),
731                 this, SIGNAL(changed()));
732         connect(lyxserverDirED, SIGNAL(textChanged(const QString&)),
733                 this, SIGNAL(changed()));
734         connect(pathPrefixED, SIGNAL(textChanged(const QString&)),
735                 this, SIGNAL(changed()));
736 }
737
738
739 void PrefPaths::apply(LyXRC & rc) const
740 {
741         rc.document_path = internal_path(fromqstr(workingDirED->text()));
742         rc.template_path = internal_path(fromqstr(templateDirED->text()));
743         rc.backupdir_path = internal_path(fromqstr(backupDirED->text()));
744         rc.tempdir_path = internal_path(fromqstr(tempDirED->text()));
745         rc.path_prefix = internal_path_list(fromqstr(pathPrefixED->text()));
746         // FIXME: should be a checkbox only
747         rc.lyxpipes = internal_path(fromqstr(lyxserverDirED->text()));
748 }
749
750
751 void PrefPaths::update(LyXRC const & rc)
752 {
753         workingDirED->setText(toqstr(external_path(rc.document_path)));
754         templateDirED->setText(toqstr(external_path(rc.template_path)));
755         backupDirED->setText(toqstr(external_path(rc.backupdir_path)));
756         tempDirED->setText(toqstr(external_path(rc.tempdir_path)));
757         pathPrefixED->setText(toqstr(external_path_list(rc.path_prefix)));
758         // FIXME: should be a checkbox only
759         lyxserverDirED->setText(toqstr(external_path(rc.lyxpipes)));
760 }
761
762
763 void PrefPaths::select_templatedir()
764 {
765         docstring file(form_->browsedir(
766                 from_utf8(internal_path(fromqstr(templateDirED->text()))),
767                 _("Select a document templates directory")));
768         if (!file.empty())
769                 templateDirED->setText(toqstr(file));
770 }
771
772
773 void PrefPaths::select_tempdir()
774 {
775         docstring file(form_->browsedir(
776                 from_utf8(internal_path(fromqstr(tempDirED->text()))),
777                 _("Select a temporary directory")));
778         if (!file.empty())
779                 tempDirED->setText(toqstr(file));
780 }
781
782
783 void PrefPaths::select_backupdir()
784 {
785         docstring file(form_->browsedir(
786                 from_utf8(internal_path(fromqstr(backupDirED->text()))),
787                 _("Select a backups directory")));
788         if (!file.empty())
789                 backupDirED->setText(toqstr(file));
790 }
791
792
793 void PrefPaths::select_workingdir()
794 {
795         docstring file(form_->browsedir(
796                 from_utf8(internal_path(fromqstr(workingDirED->text()))),
797                 _("Select a document directory")));
798         if (!file.empty())
799                 workingDirED->setText(toqstr(file));
800 }
801
802
803 void PrefPaths::select_lyxpipe()
804 {
805         docstring file(form_->browse(
806                 from_utf8(internal_path(fromqstr(lyxserverDirED->text()))),
807                 _("Give a filename for the LyX server pipe")));
808         if (!file.empty())
809                 lyxserverDirED->setText(toqstr(file));
810 }
811
812
813 /////////////////////////////////////////////////////////////////////
814 //
815 // PrefSpellchecker
816 //
817 /////////////////////////////////////////////////////////////////////
818
819 PrefSpellchecker::PrefSpellchecker(GuiPreferences * form, QWidget * parent)
820         : PrefModule(_("Spellchecker"), form, parent)
821 {
822         setupUi(this);
823
824         connect(persDictionaryPB, SIGNAL(clicked()), this, SLOT(select_dict()));
825 #if defined (USE_ISPELL)
826         connect(spellCommandCO, SIGNAL(activated(int)),
827                 this, SIGNAL(changed()));
828 #else
829         spellCommandCO->setEnabled(false);
830 #endif
831         connect(altLanguageED, SIGNAL(textChanged(const QString&)),
832                 this, SIGNAL(changed()));
833         connect(escapeCharactersED, SIGNAL(textChanged(const QString&)),
834                 this, SIGNAL(changed()));
835         connect(persDictionaryED, SIGNAL(textChanged(const QString&)),
836                 this, SIGNAL(changed()));
837         connect(compoundWordCB, SIGNAL(clicked()),
838                 this, SIGNAL(changed()));
839         connect(inputEncodingCB, SIGNAL(clicked()),
840                 this, SIGNAL(changed()));
841
842         spellCommandCO->addItem(qt_("ispell"));
843         spellCommandCO->addItem(qt_("aspell"));
844         spellCommandCO->addItem(qt_("hspell"));
845 #ifdef USE_PSPELL
846         spellCommandCO->addItem(qt_("pspell (library)"));
847 #else
848 #ifdef USE_ASPELL
849         spellCommandCO->addItem(qt_("aspell (library)"));
850 #endif
851 #endif
852 }
853
854
855 void PrefSpellchecker::apply(LyXRC & rc) const
856 {
857         switch (spellCommandCO->currentIndex()) {
858                 case 0:
859                 case 1:
860                 case 2:
861                         rc.use_spell_lib = false;
862                         rc.isp_command = fromqstr(spellCommandCO->currentText());
863                         break;
864                 case 3:
865                         rc.use_spell_lib = true;
866                         break;
867         }
868
869         // FIXME: remove isp_use_alt_lang
870         rc.isp_alt_lang = fromqstr(altLanguageED->text());
871         rc.isp_use_alt_lang = !rc.isp_alt_lang.empty();
872         // FIXME: remove isp_use_esc_chars
873         rc.isp_esc_chars = fromqstr(escapeCharactersED->text());
874         rc.isp_use_esc_chars = !rc.isp_esc_chars.empty();
875         // FIXME: remove isp_use_pers_dict
876         rc.isp_pers_dict = internal_path(fromqstr(persDictionaryED->text()));
877         rc.isp_use_pers_dict = !rc.isp_pers_dict.empty();
878         rc.isp_accept_compound = compoundWordCB->isChecked();
879         rc.isp_use_input_encoding = inputEncodingCB->isChecked();
880 }
881
882
883 void PrefSpellchecker::update(LyXRC const & rc)
884 {
885         spellCommandCO->setCurrentIndex(0);
886
887         if (rc.isp_command == "ispell") {
888                 spellCommandCO->setCurrentIndex(0);
889         } else if (rc.isp_command == "aspell") {
890                 spellCommandCO->setCurrentIndex(1);
891         } else if (rc.isp_command == "hspell") {
892                 spellCommandCO->setCurrentIndex(2);
893         }
894
895         if (rc.use_spell_lib) {
896 #if defined(USE_ASPELL) || defined(USE_PSPELL)
897                 spellCommandCO->setCurrentIndex(3);
898 #endif
899         }
900
901         // FIXME: remove isp_use_alt_lang
902         altLanguageED->setText(toqstr(rc.isp_alt_lang));
903         // FIXME: remove isp_use_esc_chars
904         escapeCharactersED->setText(toqstr(rc.isp_esc_chars));
905         // FIXME: remove isp_use_pers_dict
906         persDictionaryED->setText(toqstr(external_path(rc.isp_pers_dict)));
907         compoundWordCB->setChecked(rc.isp_accept_compound);
908         inputEncodingCB->setChecked(rc.isp_use_input_encoding);
909 }
910
911
912 void PrefSpellchecker::select_dict()
913 {
914         docstring file(form_->browsedict(
915                 from_utf8(internal_path(fromqstr(persDictionaryED->text())))));
916         if (!file.empty())
917                 persDictionaryED->setText(toqstr(file));
918 }
919
920
921
922 /////////////////////////////////////////////////////////////////////
923 //
924 // PrefConverters
925 //
926 /////////////////////////////////////////////////////////////////////
927
928
929 PrefConverters::PrefConverters(GuiPreferences * form, QWidget * parent)
930         : PrefModule(_("Converters"), form, parent)
931 {
932         setupUi(this);
933
934         connect(converterNewPB, SIGNAL(clicked()),
935                 this, SLOT(update_converter()));
936         connect(converterRemovePB, SIGNAL(clicked()),
937                 this, SLOT(remove_converter()));
938         connect(converterModifyPB, SIGNAL(clicked()),
939                 this, SLOT(update_converter()));
940         connect(convertersLW, SIGNAL(currentRowChanged(int)),
941                 this, SLOT(switch_converter()));
942         connect(converterFromCO, SIGNAL(activated(const QString&)),
943                 this, SLOT(converter_changed()));
944         connect(converterToCO, SIGNAL(activated(const QString&)),
945                 this, SLOT(converter_changed()));
946         connect(converterED, SIGNAL(textEdited(const QString&)),
947                 this, SLOT(converter_changed()));
948         connect(converterFlagED, SIGNAL(textEdited(const QString&)),
949                 this, SLOT(converter_changed()));
950         connect(converterNewPB, SIGNAL(clicked()),
951                 this, SIGNAL(changed()));
952         connect(converterRemovePB, SIGNAL(clicked()),
953                 this, SIGNAL(changed()));
954         connect(converterModifyPB, SIGNAL(clicked()),
955                 this, SIGNAL(changed()));
956         connect(maxAgeLE, SIGNAL(textEdited(const QString&)),
957                 this, SIGNAL(changed()));
958
959         maxAgeLE->setValidator(new QDoubleValidator(maxAgeLE));
960         //converterDefGB->setFocusProxy(convertersLW);
961 }
962
963
964 void PrefConverters::apply(LyXRC & rc) const
965 {
966         rc.use_converter_cache = cacheCB->isChecked();
967         rc.converter_cache_maxage = int(maxAgeLE->text().toDouble() * 86400.0);
968 }
969
970
971 void PrefConverters::update(LyXRC const & rc)
972 {
973         cacheCB->setChecked(rc.use_converter_cache);
974         QString max_age;
975         max_age.setNum(double(rc.converter_cache_maxage) / 86400.0, 'g', 6);
976         maxAgeLE->setText(max_age);
977         updateGui();
978 }
979
980
981 void PrefConverters::updateGui()
982 {
983         form_->formats().sort();
984         form_->converters().update(form_->formats());
985         // save current selection
986         QString current = converterFromCO->currentText()
987                 + " -> " + converterToCO->currentText();
988
989         converterFromCO->clear();
990         converterToCO->clear();
991
992         Formats::const_iterator cit = form_->formats().begin();
993         Formats::const_iterator end = form_->formats().end();
994         for (; cit != end; ++cit) {
995                 converterFromCO->addItem(toqstr(cit->prettyname()));
996                 converterToCO->addItem(toqstr(cit->prettyname()));
997         }
998
999         // currentRowChanged(int) is also triggered when updating the listwidget
1000         // block signals to avoid unnecessary calls to switch_converter()
1001         convertersLW->blockSignals(true);
1002         convertersLW->clear();
1003
1004         Converters::const_iterator ccit = form_->converters().begin();
1005         Converters::const_iterator cend = form_->converters().end();
1006         for (; ccit != cend; ++ccit) {
1007                 std::string const name =
1008                         ccit->From->prettyname() + " -> " + ccit->To->prettyname();
1009                 int type = form_->converters().getNumber(ccit->From->name(), ccit->To->name());
1010                 new QListWidgetItem(toqstr(name), convertersLW, type);
1011         }
1012         convertersLW->sortItems(Qt::AscendingOrder);
1013         convertersLW->blockSignals(false);
1014
1015         // restore selection
1016         if (!current.isEmpty()) {
1017                 QList<QListWidgetItem *> const item =
1018                         convertersLW->findItems(current, Qt::MatchExactly);
1019                 if (!item.isEmpty())
1020                         convertersLW->setCurrentItem(item.at(0));
1021         }
1022
1023         // select first element if restoring failed
1024         if (convertersLW->currentRow() == -1)
1025                 convertersLW->setCurrentRow(0);
1026
1027         updateButtons();
1028 }
1029
1030
1031 void PrefConverters::switch_converter()
1032 {
1033         int const cnr = convertersLW->currentItem()->type();
1034         Converter const & c(form_->converters().get(cnr));
1035         converterFromCO->setCurrentIndex(form_->formats().getNumber(c.from));
1036         converterToCO->setCurrentIndex(form_->formats().getNumber(c.to));
1037         converterED->setText(toqstr(c.command));
1038         converterFlagED->setText(toqstr(c.flags));
1039
1040         updateButtons();
1041 }
1042
1043
1044 void PrefConverters::converter_changed()
1045 {
1046         updateButtons();
1047 }
1048
1049
1050 void PrefConverters::updateButtons()
1051 {
1052         Format const & from = form_->formats().get(converterFromCO->currentIndex());
1053         Format const & to = form_->formats().get(converterToCO->currentIndex());
1054         int const sel = form_->converters().getNumber(from.name(), to.name());
1055         bool const known = !(sel < 0);
1056         bool const valid = !(converterED->text().isEmpty()
1057                 || from.name() == to.name());
1058
1059         int const cnr = convertersLW->currentItem()->type();
1060         Converter const & c(form_->converters().get(cnr));
1061         string const old_command = c.command;
1062         string const old_flag = c.flags;
1063         string const new_command(fromqstr(converterED->text()));
1064         string const new_flag(fromqstr(converterFlagED->text()));
1065
1066         bool modified = ((old_command != new_command) || (old_flag != new_flag));
1067
1068         converterModifyPB->setEnabled(valid && known && modified);
1069         converterNewPB->setEnabled(valid && !known);
1070         converterRemovePB->setEnabled(known);
1071
1072         maxAgeLE->setEnabled(cacheCB->isChecked());
1073         maxAgeLA->setEnabled(cacheCB->isChecked());
1074 }
1075
1076
1077 // FIXME: user must
1078 // specify unique from/to or it doesn't appear. This is really bad UI
1079 // this is why we can use the same function for both new and modify
1080 void PrefConverters::update_converter()
1081 {
1082         Format const & from = form_->formats().get(converterFromCO->currentIndex());
1083         Format const & to = form_->formats().get(converterToCO->currentIndex());
1084         string const flags = fromqstr(converterFlagED->text());
1085         string const command = fromqstr(converterED->text());
1086
1087         Converter const * old =
1088                 form_->converters().getConverter(from.name(), to.name());
1089         form_->converters().add(from.name(), to.name(), command, flags);
1090
1091         if (!old)
1092                 form_->converters().updateLast(form_->formats());
1093
1094         updateGui();
1095
1096         // Remove all files created by this converter from the cache, since
1097         // the modified converter might create different files.
1098         ConverterCache::get().remove_all(from.name(), to.name());
1099 }
1100
1101
1102 void PrefConverters::remove_converter()
1103 {
1104         Format const & from = form_->formats().get(converterFromCO->currentIndex());
1105         Format const & to = form_->formats().get(converterToCO->currentIndex());
1106         form_->converters().erase(from.name(), to.name());
1107
1108         updateGui();
1109
1110         // Remove all files created by this converter from the cache, since
1111         // a possible new converter might create different files.
1112         ConverterCache::get().remove_all(from.name(), to.name());
1113 }
1114
1115
1116 void PrefConverters::on_cacheCB_stateChanged(int state)
1117 {
1118         maxAgeLE->setEnabled(state == Qt::Checked);
1119         maxAgeLA->setEnabled(state == Qt::Checked);
1120         changed();
1121 }
1122
1123
1124 /////////////////////////////////////////////////////////////////////
1125 //
1126 // PrefFileformats
1127 //
1128 /////////////////////////////////////////////////////////////////////
1129 FormatValidator::FormatValidator(QWidget * parent, Formats const & f) 
1130         : QValidator(parent), formats_(f)
1131 {
1132 }
1133
1134
1135 void FormatValidator::fixup(QString & input) const
1136 {
1137         Formats::const_iterator cit = formats_.begin();
1138         Formats::const_iterator end = formats_.end();
1139         for (; cit != end; ++cit) {
1140                 string const name = str(cit);
1141                 if (distance(formats_.begin(), cit) == nr()) {
1142                         input = toqstr(name);
1143                         return;
1144
1145                 }
1146         }
1147 }
1148
1149
1150 QValidator::State FormatValidator::validate(QString & input, int & /*pos*/) const
1151 {
1152         Formats::const_iterator cit = formats_.begin();
1153         Formats::const_iterator end = formats_.end();
1154         bool unknown = true;
1155         for (; unknown && cit != end; ++cit) {
1156                 string const name = str(cit);
1157                 if (distance(formats_.begin(), cit) != nr())
1158                         unknown = toqstr(name) != input;
1159         }
1160
1161         if (unknown && !input.isEmpty()) 
1162                 return QValidator::Acceptable;
1163         else
1164                 return QValidator::Intermediate;
1165 }
1166
1167
1168 int FormatValidator::nr() const
1169 {
1170         QComboBox * p = qobject_cast<QComboBox *>(parent());
1171         return p->itemData(p->currentIndex()).toInt();
1172 }
1173
1174
1175 FormatNameValidator::FormatNameValidator(QWidget * parent, Formats const & f) 
1176         : FormatValidator(parent, f)
1177 {
1178 }
1179
1180 std::string FormatNameValidator::str(Formats::const_iterator it) const
1181 {
1182         return it->name();
1183 }
1184
1185
1186 FormatPrettynameValidator::FormatPrettynameValidator(QWidget * parent, Formats const & f) 
1187         : FormatValidator(parent, f)
1188 {
1189 }
1190
1191
1192 std::string FormatPrettynameValidator::str(Formats::const_iterator it) const
1193 {
1194         return it->prettyname();
1195 }
1196
1197
1198 PrefFileformats::PrefFileformats(GuiPreferences * form, QWidget * parent)
1199         : PrefModule(_("File formats"), form, parent)
1200 {
1201         setupUi(this);
1202         formatED->setValidator(new FormatNameValidator(formatsCB, form_->formats()));
1203         formatsCB->setValidator(new FormatPrettynameValidator(formatsCB, form_->formats()));
1204
1205         connect(documentCB, SIGNAL(clicked()),
1206                 this, SLOT(setFlags()));
1207         connect(vectorCB, SIGNAL(clicked()),
1208                 this, SLOT(setFlags()));
1209         connect(formatsCB->lineEdit(), SIGNAL(editingFinished()),
1210                 this, SLOT(updatePrettyname()));
1211         connect(formatsCB->lineEdit(), SIGNAL(textEdited(const QString &)),
1212                 this, SIGNAL(changed()));
1213 }
1214
1215
1216 void PrefFileformats::apply(LyXRC & /*rc*/) const
1217 {
1218 }
1219
1220
1221 void PrefFileformats::update(LyXRC const & /*rc*/)
1222 {
1223         updateView();
1224 }
1225
1226
1227 void PrefFileformats::updateView()
1228 {
1229         QString const current = formatsCB->currentText();
1230
1231         // update combobox with formats
1232         formatsCB->blockSignals(true);
1233         formatsCB->clear();
1234         form_->formats().sort();
1235         Formats::const_iterator cit = form_->formats().begin();
1236         Formats::const_iterator end = form_->formats().end();
1237         for (; cit != end; ++cit)
1238                 formatsCB->addItem(toqstr(cit->prettyname()),
1239                                                         QVariant(form_->formats().getNumber(cit->name())) );
1240
1241         // restore selection
1242         int const item = formatsCB->findText(current, Qt::MatchExactly);
1243         formatsCB->setCurrentIndex(item < 0 ? 0 : item);
1244         on_formatsCB_currentIndexChanged(item < 0 ? 0 : item);
1245         formatsCB->blockSignals(false);
1246 }
1247
1248
1249 void PrefFileformats::on_formatsCB_currentIndexChanged(int i)
1250 {
1251         int const nr = formatsCB->itemData(i).toInt();
1252         Format const f = form_->formats().get(nr);
1253
1254         formatED->setText(toqstr(f.name()));
1255         copierED->setText(toqstr(form_->movers().command(f.name())));
1256         extensionED->setText(toqstr(f.extension()));
1257         shortcutED->setText(toqstr(f.shortcut()));
1258         viewerED->setText(toqstr(f.viewer()));
1259         editorED->setText(toqstr(f.editor()));
1260         documentCB->setChecked((f.documentFormat()));
1261         vectorCB->setChecked((f.vectorFormat()));
1262 }
1263
1264
1265 void PrefFileformats::setFlags()
1266 {
1267         int flags = Format::none;
1268         if (documentCB->isChecked())
1269                 flags |= Format::document;
1270         if (vectorCB->isChecked())
1271                 flags |= Format::vector;
1272         currentFormat().setFlags(flags);
1273         changed();
1274 }
1275
1276
1277 void PrefFileformats::on_copierED_textEdited(const QString & s)
1278 {
1279         string const fmt = fromqstr(formatED->text());
1280         form_->movers().set(fmt, fromqstr(s));
1281         changed();
1282 }
1283
1284
1285 void PrefFileformats::on_extensionED_textEdited(const QString & s)
1286 {
1287         currentFormat().setExtension(fromqstr(s));
1288         changed();
1289 }
1290
1291 void PrefFileformats::on_viewerED_textEdited(const QString & s)
1292 {
1293         currentFormat().setViewer(fromqstr(s));
1294         changed();
1295 }
1296
1297
1298 void PrefFileformats::on_editorED_textEdited(const QString & s)
1299 {
1300         currentFormat().setEditor(fromqstr(s));
1301         changed();
1302 }
1303
1304
1305 void PrefFileformats::on_shortcutED_textEdited(const QString & s)
1306 {
1307         currentFormat().setShortcut(fromqstr(s));
1308         changed();
1309 }
1310
1311
1312 void PrefFileformats::on_formatED_editingFinished()
1313 {
1314         string const newname = fromqstr(formatED->displayText());
1315         if (newname == currentFormat().name())
1316                 return;
1317
1318         currentFormat().setName(newname);
1319         changed();
1320 }
1321
1322
1323 void PrefFileformats::on_formatED_textChanged(const QString &)
1324 {
1325         QString t = formatED->text();
1326         int p = 0;
1327         bool valid = formatED->validator()->validate(t, p) == QValidator::Acceptable;
1328         setValid(formatLA, valid);
1329 }
1330
1331
1332 void PrefFileformats::on_formatsCB_editTextChanged(const QString &)
1333 {
1334         QString t = formatsCB->currentText();
1335         int p = 0;
1336         bool valid = formatsCB->validator()->validate(t, p) == QValidator::Acceptable;
1337         setValid(formatsLA, valid);
1338 }
1339
1340
1341 void PrefFileformats::updatePrettyname()
1342 {
1343         string const newname = fromqstr(formatsCB->currentText());
1344         if (newname == currentFormat().prettyname())
1345                 return;
1346
1347         currentFormat().setPrettyname(newname);
1348         formatsChanged();
1349         updateView();
1350         changed();
1351 }
1352
1353
1354 Format & PrefFileformats::currentFormat()
1355 {
1356         int const i = formatsCB->currentIndex();
1357         int const nr = formatsCB->itemData(i).toInt();
1358         return form_->formats().get(nr);
1359 }
1360
1361
1362 void PrefFileformats::on_formatNewPB_clicked()
1363 {
1364         form_->formats().add("", "", "", "", "", "", Format::none);
1365         updateView();
1366         formatsCB->setCurrentIndex(0);
1367         formatsCB->setFocus(Qt::OtherFocusReason);
1368 }
1369
1370
1371 void PrefFileformats::on_formatRemovePB_clicked()
1372 {
1373         int const i = formatsCB->currentIndex();
1374         int const nr = formatsCB->itemData(i).toInt();
1375         string const current_text = form_->formats().get(nr).name();
1376         if (form_->converters().formatIsUsed(current_text)) {
1377                 Alert::error(_("Format in use"),
1378                              _("Cannot remove a Format used by a Converter. "
1379                                             "Remove the converter first."));
1380                 return;
1381         }
1382
1383         form_->formats().erase(current_text);
1384         formatsChanged();
1385         updateView();
1386         on_formatsCB_editTextChanged(formatsCB->currentText());
1387         changed();
1388 }
1389
1390
1391 /////////////////////////////////////////////////////////////////////
1392 //
1393 // PrefLanguage
1394 //
1395 /////////////////////////////////////////////////////////////////////
1396
1397 PrefLanguage::PrefLanguage(QWidget * parent)
1398         : PrefModule(_("Language"), 0, parent)
1399 {
1400         setupUi(this);
1401
1402         connect(rtlCB, SIGNAL(clicked()),
1403                 this, SIGNAL(changed()));
1404         connect(markForeignCB, SIGNAL(clicked()),
1405                 this, SIGNAL(changed()));
1406         connect(autoBeginCB, SIGNAL(clicked()),
1407                 this, SIGNAL(changed()));
1408         connect(autoEndCB, SIGNAL(clicked()),
1409                 this, SIGNAL(changed()));
1410         connect(useBabelCB, SIGNAL(clicked()),
1411                 this, SIGNAL(changed()));
1412         connect(globalCB, SIGNAL(clicked()),
1413                 this, SIGNAL(changed()));
1414         connect(languagePackageED, SIGNAL(textChanged(const QString&)),
1415                 this, SIGNAL(changed()));
1416         connect(startCommandED, SIGNAL(textChanged(const QString&)),
1417                 this, SIGNAL(changed()));
1418         connect(endCommandED, SIGNAL(textChanged(const QString&)),
1419                 this, SIGNAL(changed()));
1420         connect(defaultLanguageCO, SIGNAL(activated(int)),
1421                 this, SIGNAL(changed()));
1422
1423         defaultLanguageCO->clear();
1424
1425         // store the lang identifiers for later
1426         std::vector<LanguagePair> const langs = frontend::getLanguageData(false);
1427         std::vector<LanguagePair>::const_iterator lit  = langs.begin();
1428         std::vector<LanguagePair>::const_iterator lend = langs.end();
1429         lang_.clear();
1430         for (; lit != lend; ++lit) {
1431                 defaultLanguageCO->addItem(toqstr(lit->first));
1432                 lang_.push_back(lit->second);
1433         }
1434 }
1435
1436
1437 void PrefLanguage::apply(LyXRC & rc) const
1438 {
1439         // FIXME: remove rtl_support bool
1440         rc.rtl_support = rtlCB->isChecked();
1441         rc.mark_foreign_language = markForeignCB->isChecked();
1442         rc.language_auto_begin = autoBeginCB->isChecked();
1443         rc.language_auto_end = autoEndCB->isChecked();
1444         rc.language_use_babel = useBabelCB->isChecked();
1445         rc.language_global_options = globalCB->isChecked();
1446         rc.language_package = fromqstr(languagePackageED->text());
1447         rc.language_command_begin = fromqstr(startCommandED->text());
1448         rc.language_command_end = fromqstr(endCommandED->text());
1449         rc.default_language = lang_[defaultLanguageCO->currentIndex()];
1450 }
1451
1452
1453 void PrefLanguage::update(LyXRC const & rc)
1454 {
1455         // FIXME: remove rtl_support bool
1456         rtlCB->setChecked(rc.rtl_support);
1457         markForeignCB->setChecked(rc.mark_foreign_language);
1458         autoBeginCB->setChecked(rc.language_auto_begin);
1459         autoEndCB->setChecked(rc.language_auto_end);
1460         useBabelCB->setChecked(rc.language_use_babel);
1461         globalCB->setChecked(rc.language_global_options);
1462         languagePackageED->setText(toqstr(rc.language_package));
1463         startCommandED->setText(toqstr(rc.language_command_begin));
1464         endCommandED->setText(toqstr(rc.language_command_end));
1465
1466         int const pos = int(findPos_helper(lang_, rc.default_language));
1467         defaultLanguageCO->setCurrentIndex(pos);
1468 }
1469
1470
1471 /////////////////////////////////////////////////////////////////////
1472 //
1473 // PrefPrinter
1474 //
1475 /////////////////////////////////////////////////////////////////////
1476
1477 PrefPrinter::PrefPrinter(QWidget * parent)
1478         : PrefModule(_("Printer"), 0, parent)
1479 {
1480         setupUi(this);
1481
1482         connect(printerAdaptCB, SIGNAL(clicked()),
1483                 this, SIGNAL(changed()));
1484         connect(printerCommandED, SIGNAL(textChanged(const QString&)),
1485                 this, SIGNAL(changed()));
1486         connect(printerNameED, SIGNAL(textChanged(const QString&)),
1487                 this, SIGNAL(changed()));
1488         connect(printerPageRangeED, SIGNAL(textChanged(const QString&)),
1489                 this, SIGNAL(changed()));
1490         connect(printerCopiesED, SIGNAL(textChanged(const QString&)),
1491                 this, SIGNAL(changed()));
1492         connect(printerReverseED, SIGNAL(textChanged(const QString&)),
1493                 this, SIGNAL(changed()));
1494         connect(printerToPrinterED, SIGNAL(textChanged(const QString&)),
1495                 this, SIGNAL(changed()));
1496         connect(printerExtensionED, SIGNAL(textChanged(const QString&)),
1497                 this, SIGNAL(changed()));
1498         connect(printerSpoolCommandED, SIGNAL(textChanged(const QString&)),
1499                 this, SIGNAL(changed()));
1500         connect(printerPaperTypeED, SIGNAL(textChanged(const QString&)),
1501                 this, SIGNAL(changed()));
1502         connect(printerEvenED, SIGNAL(textChanged(const QString&)),
1503                 this, SIGNAL(changed()));
1504         connect(printerOddED, SIGNAL(textChanged(const QString&)),
1505                 this, SIGNAL(changed()));
1506         connect(printerCollatedED, SIGNAL(textChanged(const QString&)),
1507                 this, SIGNAL(changed()));
1508         connect(printerLandscapeED, SIGNAL(textChanged(const QString&)),
1509                 this, SIGNAL(changed()));
1510         connect(printerToFileED, SIGNAL(textChanged(const QString&)),
1511                 this, SIGNAL(changed()));
1512         connect(printerExtraED, SIGNAL(textChanged(const QString&)),
1513                 this, SIGNAL(changed()));
1514         connect(printerSpoolPrefixED, SIGNAL(textChanged(const QString&)),
1515                 this, SIGNAL(changed()));
1516         connect(printerPaperSizeED, SIGNAL(textChanged(const QString&)),
1517                 this, SIGNAL(changed()));
1518 }
1519
1520
1521 void PrefPrinter::apply(LyXRC & rc) const
1522 {
1523         rc.print_adapt_output = printerAdaptCB->isChecked();
1524         rc.print_command = fromqstr(printerCommandED->text());
1525         rc.printer = fromqstr(printerNameED->text());
1526
1527         rc.print_pagerange_flag = fromqstr(printerPageRangeED->text());
1528         rc.print_copies_flag = fromqstr(printerCopiesED->text());
1529         rc.print_reverse_flag = fromqstr(printerReverseED->text());
1530         rc.print_to_printer = fromqstr(printerToPrinterED->text());
1531         rc.print_file_extension = fromqstr(printerExtensionED->text());
1532         rc.print_spool_command = fromqstr(printerSpoolCommandED->text());
1533         rc.print_paper_flag = fromqstr(printerPaperTypeED->text());
1534         rc.print_evenpage_flag = fromqstr(printerEvenED->text());
1535         rc.print_oddpage_flag = fromqstr(printerOddED->text());
1536         rc.print_collcopies_flag = fromqstr(printerCollatedED->text());
1537         rc.print_landscape_flag = fromqstr(printerLandscapeED->text());
1538         rc.print_to_file = internal_path(fromqstr(printerToFileED->text()));
1539         rc.print_extra_options = fromqstr(printerExtraED->text());
1540         rc.print_spool_printerprefix = fromqstr(printerSpoolPrefixED->text());
1541         rc.print_paper_dimension_flag = fromqstr(printerPaperSizeED->text());
1542 }
1543
1544
1545 void PrefPrinter::update(LyXRC const & rc)
1546 {
1547         printerAdaptCB->setChecked(rc.print_adapt_output);
1548         printerCommandED->setText(toqstr(rc.print_command));
1549         printerNameED->setText(toqstr(rc.printer));
1550
1551         printerPageRangeED->setText(toqstr(rc.print_pagerange_flag));
1552         printerCopiesED->setText(toqstr(rc.print_copies_flag));
1553         printerReverseED->setText(toqstr(rc.print_reverse_flag));
1554         printerToPrinterED->setText(toqstr(rc.print_to_printer));
1555         printerExtensionED->setText(toqstr(rc.print_file_extension));
1556         printerSpoolCommandED->setText(toqstr(rc.print_spool_command));
1557         printerPaperTypeED->setText(toqstr(rc.print_paper_flag));
1558         printerEvenED->setText(toqstr(rc.print_evenpage_flag));
1559         printerOddED->setText(toqstr(rc.print_oddpage_flag));
1560         printerCollatedED->setText(toqstr(rc.print_collcopies_flag));
1561         printerLandscapeED->setText(toqstr(rc.print_landscape_flag));
1562         printerToFileED->setText(toqstr(external_path(rc.print_to_file)));
1563         printerExtraED->setText(toqstr(rc.print_extra_options));
1564         printerSpoolPrefixED->setText(toqstr(rc.print_spool_printerprefix));
1565         printerPaperSizeED->setText(toqstr(rc.print_paper_dimension_flag));
1566 }
1567
1568
1569 /////////////////////////////////////////////////////////////////////
1570 //
1571 // PrefUserInterface
1572 //
1573 /////////////////////////////////////////////////////////////////////
1574
1575 PrefUserInterface::PrefUserInterface(GuiPreferences * form, QWidget * parent)
1576         : PrefModule(_("User interface"), form, parent)
1577 {
1578         setupUi(this);
1579
1580         connect(autoSaveCB, SIGNAL(toggled(bool)),
1581                 autoSaveSB, SLOT(setEnabled(bool)));
1582         connect(autoSaveCB, SIGNAL(toggled(bool)),
1583                 TextLabel1, SLOT(setEnabled(bool)));
1584         connect(uiFilePB, SIGNAL(clicked()),
1585                 this, SLOT(select_ui()));
1586         connect(bindFilePB, SIGNAL(clicked()),
1587                 this, SLOT(select_bind()));
1588         connect(uiFileED, SIGNAL(textChanged(const QString &)),
1589                 this, SIGNAL(changed()));
1590         connect(bindFileED, SIGNAL(textChanged(const QString &)),
1591                 this, SIGNAL(changed()));
1592         connect(restoreCursorCB, SIGNAL(clicked()),
1593                 this, SIGNAL(changed()));
1594         connect(loadSessionCB, SIGNAL(clicked()),
1595                 this, SIGNAL(changed()));
1596         connect(loadWindowSizeCB, SIGNAL(clicked()),
1597                 this, SIGNAL(changed()));
1598         connect(loadWindowLocationCB, SIGNAL(clicked()),
1599                 this, SIGNAL(changed()));
1600         connect(windowWidthSB, SIGNAL(valueChanged(int)),
1601                 this, SIGNAL(changed()));
1602         connect(windowHeightSB, SIGNAL(valueChanged(int)),
1603                 this, SIGNAL(changed()));
1604         connect(cursorFollowsCB, SIGNAL(clicked()),
1605                 this, SIGNAL(changed()));
1606         connect(autoSaveSB, SIGNAL(valueChanged(int)),
1607                 this, SIGNAL(changed()));
1608         connect(autoSaveCB, SIGNAL(clicked()),
1609                 this, SIGNAL(changed()));
1610         connect(lastfilesSB, SIGNAL(valueChanged(int)),
1611                 this, SIGNAL(changed()));
1612         lastfilesSB->setMaximum(maxlastfiles);
1613 }
1614
1615
1616 void PrefUserInterface::apply(LyXRC & rc) const
1617 {
1618         rc.ui_file = internal_path(fromqstr(uiFileED->text()));
1619         rc.bind_file = internal_path(fromqstr(bindFileED->text()));
1620         rc.use_lastfilepos = restoreCursorCB->isChecked();
1621         rc.load_session = loadSessionCB->isChecked();
1622         if (loadWindowSizeCB->isChecked()) {
1623                 rc.geometry_width = 0;
1624                 rc.geometry_height = 0;
1625         } else {
1626                 rc.geometry_width = windowWidthSB->value();
1627                 rc.geometry_height = windowHeightSB->value();
1628         }
1629         rc.geometry_xysaved = loadWindowLocationCB->isChecked();
1630         rc.cursor_follows_scrollbar = cursorFollowsCB->isChecked();
1631         rc.autosave = autoSaveSB->value() * 60;
1632         rc.make_backup = autoSaveCB->isChecked();
1633         rc.num_lastfiles = lastfilesSB->value();
1634 }
1635
1636
1637 void PrefUserInterface::update(LyXRC const & rc)
1638 {
1639         uiFileED->setText(toqstr(external_path(rc.ui_file)));
1640         bindFileED->setText(toqstr(external_path(rc.bind_file)));
1641         restoreCursorCB->setChecked(rc.use_lastfilepos);
1642         loadSessionCB->setChecked(rc.load_session);
1643         bool loadWindowSize = rc.geometry_width == 0 && rc.geometry_height == 0;
1644         loadWindowSizeCB->setChecked(loadWindowSize);
1645         if (!loadWindowSize) {
1646                 windowWidthSB->setValue(rc.geometry_width);
1647                 windowHeightSB->setValue(rc.geometry_height);
1648         }
1649         loadWindowLocationCB->setChecked(rc.geometry_xysaved);
1650         cursorFollowsCB->setChecked(rc.cursor_follows_scrollbar);
1651         // convert to minutes
1652         int mins(rc.autosave / 60);
1653         if (rc.autosave && !mins)
1654                 mins = 1;
1655         autoSaveSB->setValue(mins);
1656         autoSaveCB->setChecked(rc.make_backup);
1657         lastfilesSB->setValue(rc.num_lastfiles);
1658 }
1659
1660
1661 void PrefUserInterface::select_ui()
1662 {
1663         docstring const name =
1664                 from_utf8(internal_path(fromqstr(uiFileED->text())));
1665         docstring file = form_->browseUI(name);
1666         if (!file.empty())
1667                 uiFileED->setText(toqstr(file));
1668 }
1669
1670
1671 void PrefUserInterface::select_bind()
1672 {
1673         docstring const name =
1674                 from_utf8(internal_path(fromqstr(bindFileED->text())));
1675         docstring file = form_->browsebind(name);
1676         if (!file.empty())
1677                 bindFileED->setText(toqstr(file));
1678 }
1679
1680
1681 void PrefUserInterface::on_loadWindowSizeCB_toggled(bool loadwindowsize)
1682 {
1683         windowWidthLA->setDisabled(loadwindowsize);
1684         windowHeightLA->setDisabled(loadwindowsize);
1685         windowWidthSB->setDisabled(loadwindowsize);
1686         windowHeightSB->setDisabled(loadwindowsize);
1687 }
1688
1689
1690 PrefIdentity::PrefIdentity(QWidget * parent)
1691         : PrefModule(_("Identity"), 0, parent)
1692 {
1693         setupUi(this);
1694
1695         connect(nameED, SIGNAL(textChanged(const QString&)),
1696                 this, SIGNAL(changed()));
1697         connect(emailED, SIGNAL(textChanged(const QString&)),
1698                 this, SIGNAL(changed()));
1699 }
1700
1701
1702 void PrefIdentity::apply(LyXRC & rc) const
1703 {
1704         rc.user_name = fromqstr(nameED->text());
1705         rc.user_email = fromqstr(emailED->text());
1706 }
1707
1708
1709 void PrefIdentity::update(LyXRC const & rc)
1710 {
1711         nameED->setText(toqstr(rc.user_name));
1712         emailED->setText(toqstr(rc.user_email));
1713 }
1714
1715
1716
1717 /////////////////////////////////////////////////////////////////////
1718 //
1719 // GuiPreferences
1720 //
1721 /////////////////////////////////////////////////////////////////////
1722
1723 GuiPreferences::GuiPreferences(LyXView & lv)
1724         : GuiDialog(lv, "prefs"), Controller(this), update_screen_font_(false)
1725 {
1726         setupUi(this);
1727         setViewTitle(_("Preferences"));
1728         setController(this, false);
1729
1730         QDialog::setModal(false);
1731
1732         connect(savePB, SIGNAL(clicked()), this, SLOT(slotOK()));
1733         connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
1734         connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
1735         connect(restorePB, SIGNAL(clicked()), this, SLOT(slotRestore()));
1736
1737         add(new PrefUserInterface(this));
1738         add(new PrefScreenFonts(this));
1739         add(new PrefColors(this));
1740         add(new PrefDisplay);
1741         add(new PrefKeyboard(this));
1742
1743         add(new PrefPaths(this));
1744
1745         add(new PrefIdentity);
1746
1747         add(new PrefLanguage);
1748         add(new PrefSpellchecker(this));
1749
1750         add(new PrefPrinter);
1751         add(new PrefDate);
1752         add(new PrefPlaintext);
1753         add(new PrefLatex(this));
1754
1755         PrefConverters * converters = new PrefConverters(this);
1756         PrefFileformats * formats = new PrefFileformats(this);
1757         connect(formats, SIGNAL(formatsChanged()),
1758                         converters, SLOT(updateGui()));
1759         add(converters);
1760         add(formats);
1761
1762         prefsPS->setCurrentPanel(_("User interface"));
1763 // FIXME: hack to work around resizing bug in Qt >= 4.2
1764 // bug verified with Qt 4.2.{0-3} (JSpitzm)
1765 #if QT_VERSION >= 0x040200
1766         prefsPS->updateGeometry();
1767 #endif
1768
1769         bc().setPolicy(ButtonPolicy::PreferencesPolicy);
1770         bc().setOK(savePB);
1771         bc().setApply(applyPB);
1772         bc().setCancel(closePB);
1773         bc().setRestore(restorePB);
1774 }
1775
1776
1777 void GuiPreferences::add(PrefModule * module)
1778 {
1779         BOOST_ASSERT(module);
1780         prefsPS->addPanel(module, module->title());
1781         connect(module, SIGNAL(changed()), this, SLOT(change_adaptor()));
1782         modules_.push_back(module);
1783 }
1784
1785
1786 void GuiPreferences::closeEvent(QCloseEvent * e)
1787 {
1788         slotClose();
1789         e->accept();
1790 }
1791
1792
1793 void GuiPreferences::change_adaptor()
1794 {
1795         changed();
1796 }
1797
1798
1799 void GuiPreferences::apply(LyXRC & rc) const
1800 {
1801         size_t end = modules_.size();
1802         for (size_t i = 0; i != end; ++i)
1803                 modules_[i]->apply(rc);
1804 }
1805
1806
1807 void GuiPreferences::updateRc(LyXRC const & rc)
1808 {
1809         size_t const end = modules_.size();
1810         for (size_t i = 0; i != end; ++i)
1811                 modules_[i]->update(rc);
1812 }
1813
1814
1815 void GuiPreferences::applyView()
1816 {
1817         apply(rc());
1818 }
1819
1820
1821 void GuiPreferences::updateContents()
1822 {
1823         updateRc(rc());
1824 }
1825
1826
1827 bool GuiPreferences::initialiseParams(std::string const &)
1828 {
1829         rc_ = lyxrc;
1830         formats_ = lyx::formats;
1831         converters_ = theConverters();
1832         converters_.update(formats_);
1833         movers_ = theMovers();
1834         colors_.clear();
1835         update_screen_font_ = false;
1836
1837         return true;
1838 }
1839
1840
1841 void GuiPreferences::dispatchParams()
1842 {
1843         ostringstream ss;
1844         rc_.write(ss, true);
1845         dispatch(FuncRequest(LFUN_LYXRC_APPLY, ss.str())); 
1846         // FIXME: these need lfuns
1847         // FIXME UNICODE
1848         theBufferList().setCurrentAuthor(from_utf8(rc_.user_name), from_utf8(rc_.user_email));
1849
1850         lyx::formats = formats_;
1851
1852         theConverters() = converters_;
1853         theConverters().update(lyx::formats);
1854         theConverters().buildGraph();
1855
1856         theMovers() = movers_;
1857
1858         vector<string>::const_iterator it = colors_.begin();
1859         vector<string>::const_iterator const end = colors_.end();
1860         for (; it != end; ++it)
1861                 dispatch(FuncRequest(LFUN_SET_COLOR, *it));
1862         colors_.clear();
1863
1864         if (update_screen_font_) {
1865                 dispatch(FuncRequest(LFUN_SCREEN_FONT_UPDATE));
1866                 update_screen_font_ = false;
1867         }
1868
1869         // The Save button has been pressed
1870         if (dialog().isClosing()) {
1871                 dispatch(FuncRequest(LFUN_PREFERENCES_SAVE));
1872         }
1873 }
1874
1875
1876 void GuiPreferences::setColor(Color_color col, string const & hex)
1877 {
1878         colors_.push_back(lcolor.getLyXName(col) + ' ' + hex);
1879 }
1880
1881
1882 void GuiPreferences::updateScreenFonts()
1883 {
1884         update_screen_font_ = true;
1885 }
1886
1887
1888 docstring const GuiPreferences::browsebind(docstring const & file) const
1889 {
1890         return browseLibFile(from_ascii("bind"), file, from_ascii("bind"),
1891                              _("Choose bind file"),
1892                              FileFilterList(_("LyX bind files (*.bind)")));
1893 }
1894
1895
1896 docstring const GuiPreferences::browseUI(docstring const & file) const
1897 {
1898         return browseLibFile(from_ascii("ui"), file, from_ascii("ui"),
1899                              _("Choose UI file"),
1900                              FileFilterList(_("LyX UI files (*.ui)")));
1901 }
1902
1903
1904 docstring const GuiPreferences::browsekbmap(docstring const & file) const
1905 {
1906         return browseLibFile(from_ascii("kbd"), file, from_ascii("kmap"),
1907                              _("Choose keyboard map"),
1908                              FileFilterList(_("LyX keyboard maps (*.kmap)")));
1909 }
1910
1911
1912 docstring const GuiPreferences::browsedict(docstring const & file) const
1913 {
1914         if (lyxrc.use_spell_lib)
1915                 return browseFile(file,
1916                                   _("Choose personal dictionary"),
1917                                   FileFilterList(_("*.pws")));
1918         else
1919                 return browseFile(file,
1920                                   _("Choose personal dictionary"),
1921                                   FileFilterList(_("*.ispell")));
1922 }
1923
1924
1925 docstring const GuiPreferences::browse(docstring const & file,
1926                                   docstring const & title) const
1927 {
1928         return browseFile(file, title, FileFilterList(), true);
1929 }
1930
1931
1932 docstring const GuiPreferences::browsedir(docstring const & path,
1933                                      docstring const & title) const
1934 {
1935         return browseDir(path, title);
1936 }
1937
1938
1939 // We support less paper sizes than the document dialog
1940 // Therefore this adjustment is needed.
1941 PAPER_SIZE GuiPreferences::toPaperSize(int i) const
1942 {
1943         switch (i) {
1944         case 0:
1945                 return PAPER_DEFAULT;
1946         case 1:
1947                 return PAPER_USLETTER;
1948         case 2:
1949                 return PAPER_USLEGAL;
1950         case 3:
1951                 return PAPER_USEXECUTIVE;
1952         case 4:
1953                 return PAPER_A3;
1954         case 5:
1955                 return PAPER_A4;
1956         case 6:
1957                 return PAPER_A5;
1958         case 7:
1959                 return PAPER_B5;
1960         default:
1961                 // should not happen
1962                 return PAPER_DEFAULT;
1963         }
1964 }
1965
1966
1967 int GuiPreferences::fromPaperSize(PAPER_SIZE papersize) const
1968 {
1969         switch (papersize) {
1970         case PAPER_DEFAULT:
1971                 return 0;
1972         case PAPER_USLETTER:
1973                 return 1;
1974         case PAPER_USLEGAL:
1975                 return 2;
1976         case PAPER_USEXECUTIVE:
1977                 return 3;
1978         case PAPER_A3:
1979                 return 4;
1980         case PAPER_A4:
1981                 return 5;
1982         case PAPER_A5:
1983                 return 6;
1984         case PAPER_B5:
1985                 return 7;
1986         default:
1987                 // should not happen
1988                 return 0;
1989         }
1990 }
1991
1992
1993 Dialog * createGuiPreferences(LyXView & lv) { return new GuiPreferences(lv); }
1994
1995
1996 } // namespace frontend
1997 } // namespace lyx
1998
1999 #include "GuiPrefs_moc.cpp"