3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
10 * Full author contact details are available in file CREDITS.
14 The code for the ShortcutEdit class was adapted from
15 kkeysequencewidget.cpp, which is part of the KDE libraries.
16 Copyright (C) 1998 Mark Donohoe <donohoe@kde.org>
17 Copyright (C) 2001 Ellis Whitehead <ellis@kde.org>
18 Copyright (C) 2007 Andreas Hartmetz <ahartmetz@gmail.com>
19 Licensed under version 2 of the General Public License and
20 used here in accordance with the terms of that license.
27 #include "qt_helpers.h"
28 #include "GuiApplication.h"
29 #include "GuiFontLoader.h"
31 #include "BufferList.h"
33 #include "ConverterCache.h"
36 #include "FuncRequest.h"
38 #include "GuiFontExample.h"
39 #include "GuiKeySymbol.h"
41 #include "KeySequence.h"
42 #include "LyXAction.h"
43 #include "PanelStack.h"
47 #include "support/FileName.h"
48 #include "support/filetools.h"
49 #include "support/lstrings.h"
50 #include "support/lyxlib.h"
51 #include "support/os.h"
52 #include "support/Package.h"
53 #include "support/FileFilterList.h"
55 #include "frontend_helpers.h"
57 #include "frontends/alert.h"
58 #include "frontends/Application.h"
61 #include <QColorDialog>
62 #include <QFontDatabase>
63 #include <QHeaderView>
65 #include <QPixmapCache>
66 #include <QPushButton>
69 #include <QTreeWidget>
70 #include <QTreeWidgetItem>
72 #include <QCloseEvent>
82 using std::ostringstream;
90 using support::compare_ascii_no_case;
91 using support::os::external_path;
92 using support::os::external_path_list;
93 using support::os::internal_path;
94 using support::os::internal_path_list;
95 using support::FileName;
96 using support::FileFilterList;
97 using support::addPath;
98 using support::addName;
100 using support::package;
103 /////////////////////////////////////////////////////////////////////
107 /////////////////////////////////////////////////////////////////////
110 static size_t findPos_helper(std::vector<A> const & vec, A const & val)
112 typedef typename std::vector<A>::const_iterator Cit;
114 Cit it = std::find(vec.begin(), vec.end(), val);
117 return std::distance(vec.begin(), it);
121 static std::pair<string, string> parseFontName(string const & name)
123 string::size_type const idx = name.find('[');
124 if (idx == string::npos || idx == 0)
125 return make_pair(name, string());
126 return make_pair(name.substr(0, idx - 1),
127 name.substr(idx + 1, name.size() - idx - 2));
131 static void setComboxFont(QComboBox * cb, string const & family,
132 string const & foundry)
134 QString fontname = toqstr(family);
135 if (!foundry.empty())
136 fontname += " [" + toqstr(foundry) + ']';
138 for (int i = 0; i < cb->count(); ++i) {
139 if (cb->itemText(i) == fontname) {
140 cb->setCurrentIndex(i);
145 // Try matching without foundry name
147 // We count in reverse in order to prefer the Xft foundry
148 for (int i = cb->count(); --i >= 0;) {
149 pair<string, string> tmp = parseFontName(fromqstr(cb->itemText(i)));
150 if (compare_ascii_no_case(tmp.first, family) == 0) {
151 cb->setCurrentIndex(i);
156 // family alone can contain e.g. "Helvetica [Adobe]"
157 pair<string, string> tmpfam = parseFontName(family);
159 // We count in reverse in order to prefer the Xft foundry
160 for (int i = cb->count() - 1; i >= 0; --i) {
161 pair<string, string> tmp = parseFontName(fromqstr(cb->itemText(i)));
162 if (compare_ascii_no_case(tmp.first, tmpfam.first) == 0) {
163 cb->setCurrentIndex(i);
168 // Bleh, default fonts, and the names couldn't be found. Hack
172 font.setKerning(false);
174 if (family == theApp()->romanFontName()) {
175 font.setStyleHint(QFont::Serif);
176 font.setFamily(family.c_str());
177 } else if (family == theApp()->sansFontName()) {
178 font.setStyleHint(QFont::SansSerif);
179 font.setFamily(family.c_str());
180 } else if (family == theApp()->typewriterFontName()) {
181 font.setStyleHint(QFont::TypeWriter);
182 font.setFamily(family.c_str());
184 lyxerr << "FAILED to find the default font: '"
185 << foundry << "', '" << family << '\''<< endl;
189 QFontInfo info(font);
190 pair<string, string> tmp = parseFontName(fromqstr(info.family()));
191 string const & default_font_name = tmp.first;
192 lyxerr << "Apparent font is " << default_font_name << endl;
194 for (int i = 0; i < cb->count(); ++i) {
195 lyxerr << "Looking at " << fromqstr(cb->itemText(i)) << endl;
196 if (compare_ascii_no_case(fromqstr(cb->itemText(i)),
197 default_font_name) == 0) {
198 cb->setCurrentIndex(i);
203 lyxerr << "FAILED to find the font: '"
204 << foundry << "', '" << family << '\'' <<endl;
208 /////////////////////////////////////////////////////////////////////
212 /////////////////////////////////////////////////////////////////////
214 PrefPlaintext::PrefPlaintext(QWidget * parent)
215 : PrefModule(_("Plain text"), 0, parent)
218 connect(plaintextLinelengthSB, SIGNAL(valueChanged(int)),
219 this, SIGNAL(changed()));
220 connect(plaintextRoffED, SIGNAL(textChanged(const QString&)),
221 this, SIGNAL(changed()));
225 void PrefPlaintext::apply(LyXRC & rc) const
227 rc.plaintext_linelen = plaintextLinelengthSB->value();
228 rc.plaintext_roff_command = fromqstr(plaintextRoffED->text());
232 void PrefPlaintext::update(LyXRC const & rc)
234 plaintextLinelengthSB->setValue(rc.plaintext_linelen);
235 plaintextRoffED->setText(toqstr(rc.plaintext_roff_command));
239 /////////////////////////////////////////////////////////////////////
243 /////////////////////////////////////////////////////////////////////
245 PrefDate::PrefDate(QWidget * parent)
246 : PrefModule(_("Date format"), 0, parent)
249 connect(DateED, SIGNAL(textChanged(const QString &)),
250 this, SIGNAL(changed()));
254 void PrefDate::apply(LyXRC & rc) const
256 rc.date_insert_format = fromqstr(DateED->text());
260 void PrefDate::update(LyXRC const & rc)
262 DateED->setText(toqstr(rc.date_insert_format));
266 /////////////////////////////////////////////////////////////////////
270 /////////////////////////////////////////////////////////////////////
272 PrefKeyboard::PrefKeyboard(GuiPreferences * form, QWidget * parent)
273 : PrefModule(_("Keyboard"), form, parent)
277 connect(keymapCB, SIGNAL(clicked()),
278 this, SIGNAL(changed()));
279 connect(firstKeymapED, SIGNAL(textChanged(const QString&)),
280 this, SIGNAL(changed()));
281 connect(secondKeymapED, SIGNAL(textChanged(const QString&)),
282 this, SIGNAL(changed()));
286 void PrefKeyboard::apply(LyXRC & rc) const
288 // FIXME: can derive CB from the two EDs
289 rc.use_kbmap = keymapCB->isChecked();
290 rc.primary_kbmap = internal_path(fromqstr(firstKeymapED->text()));
291 rc.secondary_kbmap = internal_path(fromqstr(secondKeymapED->text()));
295 void PrefKeyboard::update(LyXRC const & rc)
297 // FIXME: can derive CB from the two EDs
298 keymapCB->setChecked(rc.use_kbmap);
299 firstKeymapED->setText(toqstr(external_path(rc.primary_kbmap)));
300 secondKeymapED->setText(toqstr(external_path(rc.secondary_kbmap)));
304 QString PrefKeyboard::testKeymap(QString keymap)
306 return toqstr(form_->browsekbmap(from_utf8(internal_path(fromqstr(keymap)))));
310 void PrefKeyboard::on_firstKeymapPB_clicked(bool)
312 QString const file = testKeymap(firstKeymapED->text());
314 firstKeymapED->setText(file);
318 void PrefKeyboard::on_secondKeymapPB_clicked(bool)
320 QString const file = testKeymap(secondKeymapED->text());
322 secondKeymapED->setText(file);
326 void PrefKeyboard::on_keymapCB_toggled(bool keymap)
328 firstKeymapLA->setEnabled(keymap);
329 secondKeymapLA->setEnabled(keymap);
330 firstKeymapED->setEnabled(keymap);
331 secondKeymapED->setEnabled(keymap);
332 firstKeymapPB->setEnabled(keymap);
333 secondKeymapPB->setEnabled(keymap);
337 /////////////////////////////////////////////////////////////////////
341 /////////////////////////////////////////////////////////////////////
343 PrefLatex::PrefLatex(GuiPreferences * form, QWidget * parent)
344 : PrefModule(_("LaTeX"), form, parent)
347 connect(latexEncodingED, SIGNAL(textChanged(const QString&)),
348 this, SIGNAL(changed()));
349 connect(latexChecktexED, SIGNAL(textChanged(const QString&)),
350 this, SIGNAL(changed()));
351 connect(latexBibtexED, SIGNAL(textChanged(const QString&)),
352 this, SIGNAL(changed()));
353 connect(latexIndexED, SIGNAL(textChanged(const QString&)),
354 this, SIGNAL(changed()));
355 connect(latexAutoresetCB, SIGNAL(clicked()),
356 this, SIGNAL(changed()));
357 connect(latexDviPaperED, SIGNAL(textChanged(const QString&)),
358 this, SIGNAL(changed()));
359 connect(latexPaperSizeCO, SIGNAL(activated(int)),
360 this, SIGNAL(changed()));
362 #if defined(__CYGWIN__) || defined(_WIN32)
363 pathCB->setVisible(true);
364 connect(pathCB, SIGNAL(clicked()),
365 this, SIGNAL(changed()));
367 pathCB->setVisible(false);
372 void PrefLatex::apply(LyXRC & rc) const
374 rc.fontenc = fromqstr(latexEncodingED->text());
375 rc.chktex_command = fromqstr(latexChecktexED->text());
376 rc.bibtex_command = fromqstr(latexBibtexED->text());
377 rc.index_command = fromqstr(latexIndexED->text());
378 rc.auto_reset_options = latexAutoresetCB->isChecked();
379 rc.view_dvi_paper_option = fromqstr(latexDviPaperED->text());
380 rc.default_papersize =
381 form_->toPaperSize(latexPaperSizeCO->currentIndex());
382 #if defined(__CYGWIN__) || defined(_WIN32)
383 rc.windows_style_tex_paths = pathCB->isChecked();
388 void PrefLatex::update(LyXRC const & rc)
390 latexEncodingED->setText(toqstr(rc.fontenc));
391 latexChecktexED->setText(toqstr(rc.chktex_command));
392 latexBibtexED->setText(toqstr(rc.bibtex_command));
393 latexIndexED->setText(toqstr(rc.index_command));
394 latexAutoresetCB->setChecked(rc.auto_reset_options);
395 latexDviPaperED->setText(toqstr(rc.view_dvi_paper_option));
396 latexPaperSizeCO->setCurrentIndex(
397 form_->fromPaperSize(rc.default_papersize));
398 #if defined(__CYGWIN__) || defined(_WIN32)
399 pathCB->setChecked(rc.windows_style_tex_paths);
404 /////////////////////////////////////////////////////////////////////
408 /////////////////////////////////////////////////////////////////////
410 PrefScreenFonts::PrefScreenFonts(GuiPreferences * form, QWidget * parent)
411 : PrefModule(_("Screen fonts"), form, parent)
415 connect(screenRomanCO, SIGNAL(activated(const QString&)),
416 this, SLOT(select_roman(const QString&)));
417 connect(screenSansCO, SIGNAL(activated(const QString&)),
418 this, SLOT(select_sans(const QString&)));
419 connect(screenTypewriterCO, SIGNAL(activated(const QString&)),
420 this, SLOT(select_typewriter(const QString&)));
422 QFontDatabase fontdb;
423 QStringList families(fontdb.families());
424 for (QStringList::Iterator it = families.begin(); it != families.end(); ++it) {
425 screenRomanCO->addItem(*it);
426 screenSansCO->addItem(*it);
427 screenTypewriterCO->addItem(*it);
429 connect(screenRomanCO, SIGNAL(activated(const QString&)),
430 this, SIGNAL(changed()));
431 connect(screenSansCO, SIGNAL(activated(const QString&)),
432 this, SIGNAL(changed()));
433 connect(screenTypewriterCO, SIGNAL(activated(const QString&)),
434 this, SIGNAL(changed()));
435 connect(screenZoomSB, SIGNAL(valueChanged(int)),
436 this, SIGNAL(changed()));
437 connect(screenDpiSB, SIGNAL(valueChanged(int)),
438 this, SIGNAL(changed()));
439 connect(screenTinyED, SIGNAL(textChanged(const QString&)),
440 this, SIGNAL(changed()));
441 connect(screenSmallestED, SIGNAL(textChanged(const QString&)),
442 this, SIGNAL(changed()));
443 connect(screenSmallerED, SIGNAL(textChanged(const QString&)),
444 this, SIGNAL(changed()));
445 connect(screenSmallED, SIGNAL(textChanged(const QString&)),
446 this, SIGNAL(changed()));
447 connect(screenNormalED, SIGNAL(textChanged(const QString&)),
448 this, SIGNAL(changed()));
449 connect(screenLargeED, SIGNAL(textChanged(const QString&)),
450 this, SIGNAL(changed()));
451 connect(screenLargerED, SIGNAL(textChanged(const QString&)),
452 this, SIGNAL(changed()));
453 connect(screenLargestED, SIGNAL(textChanged(const QString&)),
454 this, SIGNAL(changed()));
455 connect(screenHugeED, SIGNAL(textChanged(const QString&)),
456 this, SIGNAL(changed()));
457 connect(screenHugerED, SIGNAL(textChanged(const QString&)),
458 this, SIGNAL(changed()));
460 screenTinyED->setValidator(new QDoubleValidator(screenTinyED));
461 screenSmallestED->setValidator(new QDoubleValidator(screenSmallestED));
462 screenSmallerED->setValidator(new QDoubleValidator(screenSmallerED));
463 screenSmallED->setValidator(new QDoubleValidator(screenSmallED));
464 screenNormalED->setValidator(new QDoubleValidator(screenNormalED));
465 screenLargeED->setValidator(new QDoubleValidator(screenLargeED));
466 screenLargerED->setValidator(new QDoubleValidator(screenLargerED));
467 screenLargestED->setValidator(new QDoubleValidator(screenLargestED));
468 screenHugeED->setValidator(new QDoubleValidator(screenHugeED));
469 screenHugerED->setValidator(new QDoubleValidator(screenHugerED));
473 void PrefScreenFonts::apply(LyXRC & rc) const
475 LyXRC const oldrc(rc);
477 boost::tie(rc.roman_font_name, rc.roman_font_foundry)
478 = parseFontName(fromqstr(screenRomanCO->currentText()));
479 boost::tie(rc.sans_font_name, rc.sans_font_foundry) =
480 parseFontName(fromqstr(screenSansCO->currentText()));
481 boost::tie(rc.typewriter_font_name, rc.typewriter_font_foundry) =
482 parseFontName(fromqstr(screenTypewriterCO->currentText()));
484 rc.zoom = screenZoomSB->value();
485 rc.dpi = screenDpiSB->value();
486 rc.font_sizes[Font::SIZE_TINY] = fromqstr(screenTinyED->text());
487 rc.font_sizes[Font::SIZE_SCRIPT] = fromqstr(screenSmallestED->text());
488 rc.font_sizes[Font::SIZE_FOOTNOTE] = fromqstr(screenSmallerED->text());
489 rc.font_sizes[Font::SIZE_SMALL] = fromqstr(screenSmallED->text());
490 rc.font_sizes[Font::SIZE_NORMAL] = fromqstr(screenNormalED->text());
491 rc.font_sizes[Font::SIZE_LARGE] = fromqstr(screenLargeED->text());
492 rc.font_sizes[Font::SIZE_LARGER] = fromqstr(screenLargerED->text());
493 rc.font_sizes[Font::SIZE_LARGEST] = fromqstr(screenLargestED->text());
494 rc.font_sizes[Font::SIZE_HUGE] = fromqstr(screenHugeED->text());
495 rc.font_sizes[Font::SIZE_HUGER] = fromqstr(screenHugerED->text());
497 if (rc.font_sizes != oldrc.font_sizes
498 || rc.roman_font_name != oldrc.roman_font_name
499 || rc.sans_font_name != oldrc.sans_font_name
500 || rc.typewriter_font_name != oldrc.typewriter_font_name
501 || rc.zoom != oldrc.zoom || rc.dpi != oldrc.dpi) {
502 // The global QPixmapCache is used in GuiPainter to cache text
503 // painting so we must reset it in case any of the above
504 // parameter is changed.
505 QPixmapCache::clear();
506 guiApp->fontLoader().update();
507 form_->updateScreenFonts();
512 void PrefScreenFonts::update(LyXRC const & rc)
514 setComboxFont(screenRomanCO, rc.roman_font_name,
515 rc.roman_font_foundry);
516 setComboxFont(screenSansCO, rc.sans_font_name,
517 rc.sans_font_foundry);
518 setComboxFont(screenTypewriterCO, rc.typewriter_font_name,
519 rc.typewriter_font_foundry);
521 select_roman(screenRomanCO->currentText());
522 select_sans(screenSansCO->currentText());
523 select_typewriter(screenTypewriterCO->currentText());
525 screenZoomSB->setValue(rc.zoom);
526 screenDpiSB->setValue(rc.dpi);
527 screenTinyED->setText(toqstr(rc.font_sizes[Font::SIZE_TINY]));
528 screenSmallestED->setText(toqstr(rc.font_sizes[Font::SIZE_SCRIPT]));
529 screenSmallerED->setText(toqstr(rc.font_sizes[Font::SIZE_FOOTNOTE]));
530 screenSmallED->setText(toqstr(rc.font_sizes[Font::SIZE_SMALL]));
531 screenNormalED->setText(toqstr(rc.font_sizes[Font::SIZE_NORMAL]));
532 screenLargeED->setText(toqstr(rc.font_sizes[Font::SIZE_LARGE]));
533 screenLargerED->setText(toqstr(rc.font_sizes[Font::SIZE_LARGER]));
534 screenLargestED->setText(toqstr(rc.font_sizes[Font::SIZE_LARGEST]));
535 screenHugeED->setText(toqstr(rc.font_sizes[Font::SIZE_HUGE]));
536 screenHugerED->setText(toqstr(rc.font_sizes[Font::SIZE_HUGER]));
539 void PrefScreenFonts::select_roman(const QString& name)
541 screenRomanFE->set(QFont(name), name);
545 void PrefScreenFonts::select_sans(const QString& name)
547 screenSansFE->set(QFont(name), name);
551 void PrefScreenFonts::select_typewriter(const QString& name)
553 screenTypewriterFE->set(QFont(name), name);
557 /////////////////////////////////////////////////////////////////////
561 /////////////////////////////////////////////////////////////////////
567 bool operator()(Color::color const & lhs, Color::color const & rhs) const {
568 return lcolor.getGUIName(lhs) < lcolor.getGUIName(rhs);
574 PrefColors::PrefColors(GuiPreferences * form, QWidget * parent)
575 : PrefModule( _("Colors"), form, parent)
579 // FIXME: all of this initialization should be put into the controller.
580 // See http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg113301.html
581 // for some discussion of why that is not trivial.
582 QPixmap icon(32, 32);
583 for (int i = 0; i < Color::ignore; ++i) {
584 Color::color lc = static_cast<Color::color>(i);
585 if (lc == Color::none
586 || lc == Color::black
587 || lc == Color::white
589 || lc == Color::green
592 || lc == Color::magenta
593 || lc == Color::yellow
594 || lc == Color::inherit
595 || lc == Color::ignore) continue;
597 lcolors_.push_back(lc);
599 std::sort(lcolors_.begin(), lcolors_.end(), ColorSorter());
600 vector<Color_color>::const_iterator cit = lcolors_.begin();
601 vector<Color_color>::const_iterator const end = lcolors_.end();
602 for (; cit != end; ++cit) {
603 (void) new QListWidgetItem(QIcon(icon),
604 toqstr(lcolor.getGUIName(*cit)), lyxObjectsLW);
606 curcolors_.resize(lcolors_.size());
607 newcolors_.resize(lcolors_.size());
608 // End initialization
610 connect(colorChangePB, SIGNAL(clicked()),
611 this, SLOT(change_color()));
612 connect(lyxObjectsLW, SIGNAL(itemSelectionChanged()),
613 this, SLOT(change_lyxObjects_selection()));
614 connect(lyxObjectsLW, SIGNAL(itemActivated(QListWidgetItem*)),
615 this, SLOT(change_color()));
619 void PrefColors::apply(LyXRC & /*rc*/) const
621 for (unsigned int i = 0; i < lcolors_.size(); ++i)
622 if (curcolors_[i] != newcolors_[i])
623 form_->setColor(lcolors_[i], fromqstr(newcolors_[i]));
627 void PrefColors::update(LyXRC const & /*rc*/)
629 for (unsigned int i = 0; i < lcolors_.size(); ++i) {
630 QColor color = QColor(guiApp->colorCache().get(lcolors_[i]));
631 QPixmap coloritem(32, 32);
632 coloritem.fill(color);
633 lyxObjectsLW->item(i)->setIcon(QIcon(coloritem));
634 newcolors_[i] = curcolors_[i] = color.name();
636 change_lyxObjects_selection();
639 void PrefColors::change_color()
641 int const row = lyxObjectsLW->currentRow();
647 QString const color = newcolors_[row];
648 QColor c = QColorDialog::getColor(QColor(color), qApp->focusWidget());
650 if (c.isValid() && c.name() != color) {
651 newcolors_[row] = c.name();
652 QPixmap coloritem(32, 32);
654 lyxObjectsLW->currentItem()->setIcon(QIcon(coloritem));
660 void PrefColors::change_lyxObjects_selection()
662 colorChangePB->setDisabled(lyxObjectsLW->currentRow() < 0);
666 /////////////////////////////////////////////////////////////////////
670 /////////////////////////////////////////////////////////////////////
672 PrefDisplay::PrefDisplay(QWidget * parent)
673 : PrefModule(_("Graphics"), 0, parent)
676 connect(instantPreviewCO, SIGNAL(activated(int)),
677 this, SIGNAL(changed()));
678 connect(displayGraphicsCO, SIGNAL(activated(int)),
679 this, SIGNAL(changed()));
683 void PrefDisplay::apply(LyXRC & rc) const
685 switch (instantPreviewCO->currentIndex()) {
686 case 0: rc.preview = LyXRC::PREVIEW_OFF; break;
687 case 1: rc.preview = LyXRC::PREVIEW_NO_MATH; break;
688 case 2: rc.preview = LyXRC::PREVIEW_ON; break;
691 lyx::graphics::DisplayType dtype;
692 switch (displayGraphicsCO->currentIndex()) {
693 case 3: dtype = lyx::graphics::NoDisplay; break;
694 case 2: dtype = lyx::graphics::ColorDisplay; break;
695 case 1: dtype = lyx::graphics::GrayscaleDisplay; break;
696 case 0: dtype = lyx::graphics::MonochromeDisplay; break;
697 default: dtype = lyx::graphics::GrayscaleDisplay;
699 rc.display_graphics = dtype;
701 // FIXME!! The graphics cache no longer has a changeDisplay method.
703 if (old_value != rc.display_graphics) {
704 lyx::graphics::GCache & gc = lyx::graphics::GCache::get();
711 void PrefDisplay::update(LyXRC const & rc)
713 switch (rc.preview) {
714 case LyXRC::PREVIEW_OFF:
715 instantPreviewCO->setCurrentIndex(0);
717 case LyXRC::PREVIEW_NO_MATH :
718 instantPreviewCO->setCurrentIndex(1);
720 case LyXRC::PREVIEW_ON :
721 instantPreviewCO->setCurrentIndex(2);
726 switch (rc.display_graphics) {
727 case lyx::graphics::NoDisplay: item = 3; break;
728 case lyx::graphics::ColorDisplay: item = 2; break;
729 case lyx::graphics::GrayscaleDisplay: item = 1; break;
730 case lyx::graphics::MonochromeDisplay: item = 0; break;
733 displayGraphicsCO->setCurrentIndex(item);
737 /////////////////////////////////////////////////////////////////////
741 /////////////////////////////////////////////////////////////////////
743 PrefPaths::PrefPaths(GuiPreferences * form, QWidget * parent)
744 : PrefModule(_("Paths"), form, parent)
747 connect(templateDirPB, SIGNAL(clicked()), this, SLOT(select_templatedir()));
748 connect(tempDirPB, SIGNAL(clicked()), this, SLOT(select_tempdir()));
749 connect(backupDirPB, SIGNAL(clicked()), this, SLOT(select_backupdir()));
750 connect(workingDirPB, SIGNAL(clicked()), this, SLOT(select_workingdir()));
751 connect(lyxserverDirPB, SIGNAL(clicked()), this, SLOT(select_lyxpipe()));
752 connect(workingDirED, SIGNAL(textChanged(const QString&)),
753 this, SIGNAL(changed()));
754 connect(templateDirED, SIGNAL(textChanged(const QString&)),
755 this, SIGNAL(changed()));
756 connect(backupDirED, SIGNAL(textChanged(const QString&)),
757 this, SIGNAL(changed()));
758 connect(tempDirED, SIGNAL(textChanged(const QString&)),
759 this, SIGNAL(changed()));
760 connect(lyxserverDirED, SIGNAL(textChanged(const QString&)),
761 this, SIGNAL(changed()));
762 connect(pathPrefixED, SIGNAL(textChanged(const QString&)),
763 this, SIGNAL(changed()));
767 void PrefPaths::apply(LyXRC & rc) const
769 rc.document_path = internal_path(fromqstr(workingDirED->text()));
770 rc.template_path = internal_path(fromqstr(templateDirED->text()));
771 rc.backupdir_path = internal_path(fromqstr(backupDirED->text()));
772 rc.tempdir_path = internal_path(fromqstr(tempDirED->text()));
773 rc.path_prefix = internal_path_list(fromqstr(pathPrefixED->text()));
774 // FIXME: should be a checkbox only
775 rc.lyxpipes = internal_path(fromqstr(lyxserverDirED->text()));
779 void PrefPaths::update(LyXRC const & rc)
781 workingDirED->setText(toqstr(external_path(rc.document_path)));
782 templateDirED->setText(toqstr(external_path(rc.template_path)));
783 backupDirED->setText(toqstr(external_path(rc.backupdir_path)));
784 tempDirED->setText(toqstr(external_path(rc.tempdir_path)));
785 pathPrefixED->setText(toqstr(external_path_list(rc.path_prefix)));
786 // FIXME: should be a checkbox only
787 lyxserverDirED->setText(toqstr(external_path(rc.lyxpipes)));
791 void PrefPaths::select_templatedir()
793 docstring file(form_->browsedir(
794 from_utf8(internal_path(fromqstr(templateDirED->text()))),
795 _("Select a document templates directory")));
797 templateDirED->setText(toqstr(file));
801 void PrefPaths::select_tempdir()
803 docstring file(form_->browsedir(
804 from_utf8(internal_path(fromqstr(tempDirED->text()))),
805 _("Select a temporary directory")));
807 tempDirED->setText(toqstr(file));
811 void PrefPaths::select_backupdir()
813 docstring file(form_->browsedir(
814 from_utf8(internal_path(fromqstr(backupDirED->text()))),
815 _("Select a backups directory")));
817 backupDirED->setText(toqstr(file));
821 void PrefPaths::select_workingdir()
823 docstring file(form_->browsedir(
824 from_utf8(internal_path(fromqstr(workingDirED->text()))),
825 _("Select a document directory")));
827 workingDirED->setText(toqstr(file));
831 void PrefPaths::select_lyxpipe()
833 docstring file(form_->browse(
834 from_utf8(internal_path(fromqstr(lyxserverDirED->text()))),
835 _("Give a filename for the LyX server pipe")));
837 lyxserverDirED->setText(toqstr(file));
841 /////////////////////////////////////////////////////////////////////
845 /////////////////////////////////////////////////////////////////////
847 PrefSpellchecker::PrefSpellchecker(GuiPreferences * form, QWidget * parent)
848 : PrefModule(_("Spellchecker"), form, parent)
852 connect(persDictionaryPB, SIGNAL(clicked()), this, SLOT(select_dict()));
853 #if defined (USE_ISPELL)
854 connect(spellCommandCO, SIGNAL(activated(int)),
855 this, SIGNAL(changed()));
857 spellCommandCO->setEnabled(false);
859 connect(altLanguageED, SIGNAL(textChanged(const QString&)),
860 this, SIGNAL(changed()));
861 connect(escapeCharactersED, SIGNAL(textChanged(const QString&)),
862 this, SIGNAL(changed()));
863 connect(persDictionaryED, SIGNAL(textChanged(const QString&)),
864 this, SIGNAL(changed()));
865 connect(compoundWordCB, SIGNAL(clicked()),
866 this, SIGNAL(changed()));
867 connect(inputEncodingCB, SIGNAL(clicked()),
868 this, SIGNAL(changed()));
870 spellCommandCO->addItem(qt_("ispell"));
871 spellCommandCO->addItem(qt_("aspell"));
872 spellCommandCO->addItem(qt_("hspell"));
874 spellCommandCO->addItem(qt_("pspell (library)"));
877 spellCommandCO->addItem(qt_("aspell (library)"));
883 void PrefSpellchecker::apply(LyXRC & rc) const
885 switch (spellCommandCO->currentIndex()) {
889 rc.use_spell_lib = false;
890 rc.isp_command = fromqstr(spellCommandCO->currentText());
893 rc.use_spell_lib = true;
897 // FIXME: remove isp_use_alt_lang
898 rc.isp_alt_lang = fromqstr(altLanguageED->text());
899 rc.isp_use_alt_lang = !rc.isp_alt_lang.empty();
900 // FIXME: remove isp_use_esc_chars
901 rc.isp_esc_chars = fromqstr(escapeCharactersED->text());
902 rc.isp_use_esc_chars = !rc.isp_esc_chars.empty();
903 // FIXME: remove isp_use_pers_dict
904 rc.isp_pers_dict = internal_path(fromqstr(persDictionaryED->text()));
905 rc.isp_use_pers_dict = !rc.isp_pers_dict.empty();
906 rc.isp_accept_compound = compoundWordCB->isChecked();
907 rc.isp_use_input_encoding = inputEncodingCB->isChecked();
911 void PrefSpellchecker::update(LyXRC const & rc)
913 spellCommandCO->setCurrentIndex(0);
915 if (rc.isp_command == "ispell") {
916 spellCommandCO->setCurrentIndex(0);
917 } else if (rc.isp_command == "aspell") {
918 spellCommandCO->setCurrentIndex(1);
919 } else if (rc.isp_command == "hspell") {
920 spellCommandCO->setCurrentIndex(2);
923 if (rc.use_spell_lib) {
924 #if defined(USE_ASPELL) || defined(USE_PSPELL)
925 spellCommandCO->setCurrentIndex(3);
929 // FIXME: remove isp_use_alt_lang
930 altLanguageED->setText(toqstr(rc.isp_alt_lang));
931 // FIXME: remove isp_use_esc_chars
932 escapeCharactersED->setText(toqstr(rc.isp_esc_chars));
933 // FIXME: remove isp_use_pers_dict
934 persDictionaryED->setText(toqstr(external_path(rc.isp_pers_dict)));
935 compoundWordCB->setChecked(rc.isp_accept_compound);
936 inputEncodingCB->setChecked(rc.isp_use_input_encoding);
940 void PrefSpellchecker::select_dict()
942 docstring file(form_->browsedict(
943 from_utf8(internal_path(fromqstr(persDictionaryED->text())))));
945 persDictionaryED->setText(toqstr(file));
950 /////////////////////////////////////////////////////////////////////
954 /////////////////////////////////////////////////////////////////////
957 PrefConverters::PrefConverters(GuiPreferences * form, QWidget * parent)
958 : PrefModule(_("Converters"), form, parent)
962 connect(converterNewPB, SIGNAL(clicked()),
963 this, SLOT(update_converter()));
964 connect(converterRemovePB, SIGNAL(clicked()),
965 this, SLOT(remove_converter()));
966 connect(converterModifyPB, SIGNAL(clicked()),
967 this, SLOT(update_converter()));
968 connect(convertersLW, SIGNAL(currentRowChanged(int)),
969 this, SLOT(switch_converter()));
970 connect(converterFromCO, SIGNAL(activated(const QString&)),
971 this, SLOT(converter_changed()));
972 connect(converterToCO, SIGNAL(activated(const QString&)),
973 this, SLOT(converter_changed()));
974 connect(converterED, SIGNAL(textEdited(const QString&)),
975 this, SLOT(converter_changed()));
976 connect(converterFlagED, SIGNAL(textEdited(const QString&)),
977 this, SLOT(converter_changed()));
978 connect(converterNewPB, SIGNAL(clicked()),
979 this, SIGNAL(changed()));
980 connect(converterRemovePB, SIGNAL(clicked()),
981 this, SIGNAL(changed()));
982 connect(converterModifyPB, SIGNAL(clicked()),
983 this, SIGNAL(changed()));
984 connect(maxAgeLE, SIGNAL(textEdited(const QString&)),
985 this, SIGNAL(changed()));
987 maxAgeLE->setValidator(new QDoubleValidator(maxAgeLE));
988 //converterDefGB->setFocusProxy(convertersLW);
992 void PrefConverters::apply(LyXRC & rc) const
994 rc.use_converter_cache = cacheCB->isChecked();
995 rc.converter_cache_maxage = int(maxAgeLE->text().toDouble() * 86400.0);
999 void PrefConverters::update(LyXRC const & rc)
1001 cacheCB->setChecked(rc.use_converter_cache);
1003 max_age.setNum(double(rc.converter_cache_maxage) / 86400.0, 'g', 6);
1004 maxAgeLE->setText(max_age);
1009 void PrefConverters::updateGui()
1011 form_->formats().sort();
1012 form_->converters().update(form_->formats());
1013 // save current selection
1014 QString current = converterFromCO->currentText()
1015 + " -> " + converterToCO->currentText();
1017 converterFromCO->clear();
1018 converterToCO->clear();
1020 Formats::const_iterator cit = form_->formats().begin();
1021 Formats::const_iterator end = form_->formats().end();
1022 for (; cit != end; ++cit) {
1023 converterFromCO->addItem(toqstr(cit->prettyname()));
1024 converterToCO->addItem(toqstr(cit->prettyname()));
1027 // currentRowChanged(int) is also triggered when updating the listwidget
1028 // block signals to avoid unnecessary calls to switch_converter()
1029 convertersLW->blockSignals(true);
1030 convertersLW->clear();
1032 Converters::const_iterator ccit = form_->converters().begin();
1033 Converters::const_iterator cend = form_->converters().end();
1034 for (; ccit != cend; ++ccit) {
1035 std::string const name =
1036 ccit->From->prettyname() + " -> " + ccit->To->prettyname();
1037 int type = form_->converters().getNumber(ccit->From->name(), ccit->To->name());
1038 new QListWidgetItem(toqstr(name), convertersLW, type);
1040 convertersLW->sortItems(Qt::AscendingOrder);
1041 convertersLW->blockSignals(false);
1043 // restore selection
1044 if (!current.isEmpty()) {
1045 QList<QListWidgetItem *> const item =
1046 convertersLW->findItems(current, Qt::MatchExactly);
1047 if (!item.isEmpty())
1048 convertersLW->setCurrentItem(item.at(0));
1051 // select first element if restoring failed
1052 if (convertersLW->currentRow() == -1)
1053 convertersLW->setCurrentRow(0);
1059 void PrefConverters::switch_converter()
1061 int const cnr = convertersLW->currentItem()->type();
1062 Converter const & c(form_->converters().get(cnr));
1063 converterFromCO->setCurrentIndex(form_->formats().getNumber(c.from));
1064 converterToCO->setCurrentIndex(form_->formats().getNumber(c.to));
1065 converterED->setText(toqstr(c.command));
1066 converterFlagED->setText(toqstr(c.flags));
1072 void PrefConverters::converter_changed()
1078 void PrefConverters::updateButtons()
1080 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1081 Format const & to = form_->formats().get(converterToCO->currentIndex());
1082 int const sel = form_->converters().getNumber(from.name(), to.name());
1083 bool const known = !(sel < 0);
1084 bool const valid = !(converterED->text().isEmpty()
1085 || from.name() == to.name());
1087 int const cnr = convertersLW->currentItem()->type();
1088 Converter const & c(form_->converters().get(cnr));
1089 string const old_command = c.command;
1090 string const old_flag = c.flags;
1091 string const new_command(fromqstr(converterED->text()));
1092 string const new_flag(fromqstr(converterFlagED->text()));
1094 bool modified = ((old_command != new_command) || (old_flag != new_flag));
1096 converterModifyPB->setEnabled(valid && known && modified);
1097 converterNewPB->setEnabled(valid && !known);
1098 converterRemovePB->setEnabled(known);
1100 maxAgeLE->setEnabled(cacheCB->isChecked());
1101 maxAgeLA->setEnabled(cacheCB->isChecked());
1106 // specify unique from/to or it doesn't appear. This is really bad UI
1107 // this is why we can use the same function for both new and modify
1108 void PrefConverters::update_converter()
1110 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1111 Format const & to = form_->formats().get(converterToCO->currentIndex());
1112 string const flags = fromqstr(converterFlagED->text());
1113 string const command = fromqstr(converterED->text());
1115 Converter const * old =
1116 form_->converters().getConverter(from.name(), to.name());
1117 form_->converters().add(from.name(), to.name(), command, flags);
1120 form_->converters().updateLast(form_->formats());
1124 // Remove all files created by this converter from the cache, since
1125 // the modified converter might create different files.
1126 ConverterCache::get().remove_all(from.name(), to.name());
1130 void PrefConverters::remove_converter()
1132 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1133 Format const & to = form_->formats().get(converterToCO->currentIndex());
1134 form_->converters().erase(from.name(), to.name());
1138 // Remove all files created by this converter from the cache, since
1139 // a possible new converter might create different files.
1140 ConverterCache::get().remove_all(from.name(), to.name());
1144 void PrefConverters::on_cacheCB_stateChanged(int state)
1146 maxAgeLE->setEnabled(state == Qt::Checked);
1147 maxAgeLA->setEnabled(state == Qt::Checked);
1152 /////////////////////////////////////////////////////////////////////
1156 /////////////////////////////////////////////////////////////////////
1157 FormatValidator::FormatValidator(QWidget * parent, Formats const & f)
1158 : QValidator(parent), formats_(f)
1163 void FormatValidator::fixup(QString & input) const
1165 Formats::const_iterator cit = formats_.begin();
1166 Formats::const_iterator end = formats_.end();
1167 for (; cit != end; ++cit) {
1168 string const name = str(cit);
1169 if (distance(formats_.begin(), cit) == nr()) {
1170 input = toqstr(name);
1178 QValidator::State FormatValidator::validate(QString & input, int & /*pos*/) const
1180 Formats::const_iterator cit = formats_.begin();
1181 Formats::const_iterator end = formats_.end();
1182 bool unknown = true;
1183 for (; unknown && cit != end; ++cit) {
1184 string const name = str(cit);
1185 if (distance(formats_.begin(), cit) != nr())
1186 unknown = toqstr(name) != input;
1189 if (unknown && !input.isEmpty())
1190 return QValidator::Acceptable;
1192 return QValidator::Intermediate;
1196 int FormatValidator::nr() const
1198 QComboBox * p = qobject_cast<QComboBox *>(parent());
1199 return p->itemData(p->currentIndex()).toInt();
1203 FormatNameValidator::FormatNameValidator(QWidget * parent, Formats const & f)
1204 : FormatValidator(parent, f)
1208 std::string FormatNameValidator::str(Formats::const_iterator it) const
1214 FormatPrettynameValidator::FormatPrettynameValidator(QWidget * parent, Formats const & f)
1215 : FormatValidator(parent, f)
1220 std::string FormatPrettynameValidator::str(Formats::const_iterator it) const
1222 return it->prettyname();
1226 PrefFileformats::PrefFileformats(GuiPreferences * form, QWidget * parent)
1227 : PrefModule(_("File formats"), form, parent)
1230 formatED->setValidator(new FormatNameValidator(formatsCB, form_->formats()));
1231 formatsCB->setValidator(new FormatPrettynameValidator(formatsCB, form_->formats()));
1233 connect(documentCB, SIGNAL(clicked()),
1234 this, SLOT(setFlags()));
1235 connect(vectorCB, SIGNAL(clicked()),
1236 this, SLOT(setFlags()));
1237 connect(formatsCB->lineEdit(), SIGNAL(editingFinished()),
1238 this, SLOT(updatePrettyname()));
1239 connect(formatsCB->lineEdit(), SIGNAL(textEdited(const QString &)),
1240 this, SIGNAL(changed()));
1244 void PrefFileformats::apply(LyXRC & /*rc*/) const
1249 void PrefFileformats::update(LyXRC const & /*rc*/)
1255 void PrefFileformats::updateView()
1257 QString const current = formatsCB->currentText();
1259 // update combobox with formats
1260 formatsCB->blockSignals(true);
1262 form_->formats().sort();
1263 Formats::const_iterator cit = form_->formats().begin();
1264 Formats::const_iterator end = form_->formats().end();
1265 for (; cit != end; ++cit)
1266 formatsCB->addItem(toqstr(cit->prettyname()),
1267 QVariant(form_->formats().getNumber(cit->name())) );
1269 // restore selection
1270 int const item = formatsCB->findText(current, Qt::MatchExactly);
1271 formatsCB->setCurrentIndex(item < 0 ? 0 : item);
1272 on_formatsCB_currentIndexChanged(item < 0 ? 0 : item);
1273 formatsCB->blockSignals(false);
1277 void PrefFileformats::on_formatsCB_currentIndexChanged(int i)
1279 int const nr = formatsCB->itemData(i).toInt();
1280 Format const f = form_->formats().get(nr);
1282 formatED->setText(toqstr(f.name()));
1283 copierED->setText(toqstr(form_->movers().command(f.name())));
1284 extensionED->setText(toqstr(f.extension()));
1285 shortcutED->setText(toqstr(f.shortcut()));
1286 viewerED->setText(toqstr(f.viewer()));
1287 editorED->setText(toqstr(f.editor()));
1288 documentCB->setChecked((f.documentFormat()));
1289 vectorCB->setChecked((f.vectorFormat()));
1293 void PrefFileformats::setFlags()
1295 int flags = Format::none;
1296 if (documentCB->isChecked())
1297 flags |= Format::document;
1298 if (vectorCB->isChecked())
1299 flags |= Format::vector;
1300 currentFormat().setFlags(flags);
1305 void PrefFileformats::on_copierED_textEdited(const QString & s)
1307 string const fmt = fromqstr(formatED->text());
1308 form_->movers().set(fmt, fromqstr(s));
1313 void PrefFileformats::on_extensionED_textEdited(const QString & s)
1315 currentFormat().setExtension(fromqstr(s));
1319 void PrefFileformats::on_viewerED_textEdited(const QString & s)
1321 currentFormat().setViewer(fromqstr(s));
1326 void PrefFileformats::on_editorED_textEdited(const QString & s)
1328 currentFormat().setEditor(fromqstr(s));
1333 void PrefFileformats::on_shortcutED_textEdited(const QString & s)
1335 currentFormat().setShortcut(fromqstr(s));
1340 void PrefFileformats::on_formatED_editingFinished()
1342 string const newname = fromqstr(formatED->displayText());
1343 if (newname == currentFormat().name())
1346 currentFormat().setName(newname);
1351 void PrefFileformats::on_formatED_textChanged(const QString &)
1353 QString t = formatED->text();
1355 bool valid = formatED->validator()->validate(t, p) == QValidator::Acceptable;
1356 setValid(formatLA, valid);
1360 void PrefFileformats::on_formatsCB_editTextChanged(const QString &)
1362 QString t = formatsCB->currentText();
1364 bool valid = formatsCB->validator()->validate(t, p) == QValidator::Acceptable;
1365 setValid(formatsLA, valid);
1369 void PrefFileformats::updatePrettyname()
1371 string const newname = fromqstr(formatsCB->currentText());
1372 if (newname == currentFormat().prettyname())
1375 currentFormat().setPrettyname(newname);
1382 Format & PrefFileformats::currentFormat()
1384 int const i = formatsCB->currentIndex();
1385 int const nr = formatsCB->itemData(i).toInt();
1386 return form_->formats().get(nr);
1390 void PrefFileformats::on_formatNewPB_clicked()
1392 form_->formats().add("", "", "", "", "", "", Format::none);
1394 formatsCB->setCurrentIndex(0);
1395 formatsCB->setFocus(Qt::OtherFocusReason);
1399 void PrefFileformats::on_formatRemovePB_clicked()
1401 int const i = formatsCB->currentIndex();
1402 int const nr = formatsCB->itemData(i).toInt();
1403 string const current_text = form_->formats().get(nr).name();
1404 if (form_->converters().formatIsUsed(current_text)) {
1405 Alert::error(_("Format in use"),
1406 _("Cannot remove a Format used by a Converter. "
1407 "Remove the converter first."));
1411 form_->formats().erase(current_text);
1414 on_formatsCB_editTextChanged(formatsCB->currentText());
1419 /////////////////////////////////////////////////////////////////////
1423 /////////////////////////////////////////////////////////////////////
1425 PrefLanguage::PrefLanguage(QWidget * parent)
1426 : PrefModule(_("Language"), 0, parent)
1430 connect(rtlCB, SIGNAL(clicked()),
1431 this, SIGNAL(changed()));
1432 connect(markForeignCB, SIGNAL(clicked()),
1433 this, SIGNAL(changed()));
1434 connect(autoBeginCB, SIGNAL(clicked()),
1435 this, SIGNAL(changed()));
1436 connect(autoEndCB, SIGNAL(clicked()),
1437 this, SIGNAL(changed()));
1438 connect(useBabelCB, SIGNAL(clicked()),
1439 this, SIGNAL(changed()));
1440 connect(globalCB, SIGNAL(clicked()),
1441 this, SIGNAL(changed()));
1442 connect(languagePackageED, SIGNAL(textChanged(const QString&)),
1443 this, SIGNAL(changed()));
1444 connect(startCommandED, SIGNAL(textChanged(const QString&)),
1445 this, SIGNAL(changed()));
1446 connect(endCommandED, SIGNAL(textChanged(const QString&)),
1447 this, SIGNAL(changed()));
1448 connect(defaultLanguageCO, SIGNAL(activated(int)),
1449 this, SIGNAL(changed()));
1451 defaultLanguageCO->clear();
1453 // store the lang identifiers for later
1454 std::vector<LanguagePair> const langs = frontend::getLanguageData(false);
1455 std::vector<LanguagePair>::const_iterator lit = langs.begin();
1456 std::vector<LanguagePair>::const_iterator lend = langs.end();
1458 for (; lit != lend; ++lit) {
1459 defaultLanguageCO->addItem(toqstr(lit->first));
1460 lang_.push_back(lit->second);
1465 void PrefLanguage::apply(LyXRC & rc) const
1467 // FIXME: remove rtl_support bool
1468 rc.rtl_support = rtlCB->isChecked();
1469 rc.mark_foreign_language = markForeignCB->isChecked();
1470 rc.language_auto_begin = autoBeginCB->isChecked();
1471 rc.language_auto_end = autoEndCB->isChecked();
1472 rc.language_use_babel = useBabelCB->isChecked();
1473 rc.language_global_options = globalCB->isChecked();
1474 rc.language_package = fromqstr(languagePackageED->text());
1475 rc.language_command_begin = fromqstr(startCommandED->text());
1476 rc.language_command_end = fromqstr(endCommandED->text());
1477 rc.default_language = lang_[defaultLanguageCO->currentIndex()];
1481 void PrefLanguage::update(LyXRC const & rc)
1483 // FIXME: remove rtl_support bool
1484 rtlCB->setChecked(rc.rtl_support);
1485 markForeignCB->setChecked(rc.mark_foreign_language);
1486 autoBeginCB->setChecked(rc.language_auto_begin);
1487 autoEndCB->setChecked(rc.language_auto_end);
1488 useBabelCB->setChecked(rc.language_use_babel);
1489 globalCB->setChecked(rc.language_global_options);
1490 languagePackageED->setText(toqstr(rc.language_package));
1491 startCommandED->setText(toqstr(rc.language_command_begin));
1492 endCommandED->setText(toqstr(rc.language_command_end));
1494 int const pos = int(findPos_helper(lang_, rc.default_language));
1495 defaultLanguageCO->setCurrentIndex(pos);
1499 /////////////////////////////////////////////////////////////////////
1503 /////////////////////////////////////////////////////////////////////
1505 PrefPrinter::PrefPrinter(QWidget * parent)
1506 : PrefModule(_("Printer"), 0, parent)
1510 connect(printerAdaptCB, SIGNAL(clicked()),
1511 this, SIGNAL(changed()));
1512 connect(printerCommandED, SIGNAL(textChanged(const QString&)),
1513 this, SIGNAL(changed()));
1514 connect(printerNameED, SIGNAL(textChanged(const QString&)),
1515 this, SIGNAL(changed()));
1516 connect(printerPageRangeED, SIGNAL(textChanged(const QString&)),
1517 this, SIGNAL(changed()));
1518 connect(printerCopiesED, SIGNAL(textChanged(const QString&)),
1519 this, SIGNAL(changed()));
1520 connect(printerReverseED, SIGNAL(textChanged(const QString&)),
1521 this, SIGNAL(changed()));
1522 connect(printerToPrinterED, SIGNAL(textChanged(const QString&)),
1523 this, SIGNAL(changed()));
1524 connect(printerExtensionED, SIGNAL(textChanged(const QString&)),
1525 this, SIGNAL(changed()));
1526 connect(printerSpoolCommandED, SIGNAL(textChanged(const QString&)),
1527 this, SIGNAL(changed()));
1528 connect(printerPaperTypeED, SIGNAL(textChanged(const QString&)),
1529 this, SIGNAL(changed()));
1530 connect(printerEvenED, SIGNAL(textChanged(const QString&)),
1531 this, SIGNAL(changed()));
1532 connect(printerOddED, SIGNAL(textChanged(const QString&)),
1533 this, SIGNAL(changed()));
1534 connect(printerCollatedED, SIGNAL(textChanged(const QString&)),
1535 this, SIGNAL(changed()));
1536 connect(printerLandscapeED, SIGNAL(textChanged(const QString&)),
1537 this, SIGNAL(changed()));
1538 connect(printerToFileED, SIGNAL(textChanged(const QString&)),
1539 this, SIGNAL(changed()));
1540 connect(printerExtraED, SIGNAL(textChanged(const QString&)),
1541 this, SIGNAL(changed()));
1542 connect(printerSpoolPrefixED, SIGNAL(textChanged(const QString&)),
1543 this, SIGNAL(changed()));
1544 connect(printerPaperSizeED, SIGNAL(textChanged(const QString&)),
1545 this, SIGNAL(changed()));
1549 void PrefPrinter::apply(LyXRC & rc) const
1551 rc.print_adapt_output = printerAdaptCB->isChecked();
1552 rc.print_command = fromqstr(printerCommandED->text());
1553 rc.printer = fromqstr(printerNameED->text());
1555 rc.print_pagerange_flag = fromqstr(printerPageRangeED->text());
1556 rc.print_copies_flag = fromqstr(printerCopiesED->text());
1557 rc.print_reverse_flag = fromqstr(printerReverseED->text());
1558 rc.print_to_printer = fromqstr(printerToPrinterED->text());
1559 rc.print_file_extension = fromqstr(printerExtensionED->text());
1560 rc.print_spool_command = fromqstr(printerSpoolCommandED->text());
1561 rc.print_paper_flag = fromqstr(printerPaperTypeED->text());
1562 rc.print_evenpage_flag = fromqstr(printerEvenED->text());
1563 rc.print_oddpage_flag = fromqstr(printerOddED->text());
1564 rc.print_collcopies_flag = fromqstr(printerCollatedED->text());
1565 rc.print_landscape_flag = fromqstr(printerLandscapeED->text());
1566 rc.print_to_file = internal_path(fromqstr(printerToFileED->text()));
1567 rc.print_extra_options = fromqstr(printerExtraED->text());
1568 rc.print_spool_printerprefix = fromqstr(printerSpoolPrefixED->text());
1569 rc.print_paper_dimension_flag = fromqstr(printerPaperSizeED->text());
1573 void PrefPrinter::update(LyXRC const & rc)
1575 printerAdaptCB->setChecked(rc.print_adapt_output);
1576 printerCommandED->setText(toqstr(rc.print_command));
1577 printerNameED->setText(toqstr(rc.printer));
1579 printerPageRangeED->setText(toqstr(rc.print_pagerange_flag));
1580 printerCopiesED->setText(toqstr(rc.print_copies_flag));
1581 printerReverseED->setText(toqstr(rc.print_reverse_flag));
1582 printerToPrinterED->setText(toqstr(rc.print_to_printer));
1583 printerExtensionED->setText(toqstr(rc.print_file_extension));
1584 printerSpoolCommandED->setText(toqstr(rc.print_spool_command));
1585 printerPaperTypeED->setText(toqstr(rc.print_paper_flag));
1586 printerEvenED->setText(toqstr(rc.print_evenpage_flag));
1587 printerOddED->setText(toqstr(rc.print_oddpage_flag));
1588 printerCollatedED->setText(toqstr(rc.print_collcopies_flag));
1589 printerLandscapeED->setText(toqstr(rc.print_landscape_flag));
1590 printerToFileED->setText(toqstr(external_path(rc.print_to_file)));
1591 printerExtraED->setText(toqstr(rc.print_extra_options));
1592 printerSpoolPrefixED->setText(toqstr(rc.print_spool_printerprefix));
1593 printerPaperSizeED->setText(toqstr(rc.print_paper_dimension_flag));
1597 /////////////////////////////////////////////////////////////////////
1599 // PrefUserInterface
1601 /////////////////////////////////////////////////////////////////////
1603 PrefUserInterface::PrefUserInterface(GuiPreferences * form, QWidget * parent)
1604 : PrefModule(_("User interface"), form, parent)
1608 connect(autoSaveCB, SIGNAL(toggled(bool)),
1609 autoSaveSB, SLOT(setEnabled(bool)));
1610 connect(autoSaveCB, SIGNAL(toggled(bool)),
1611 TextLabel1, SLOT(setEnabled(bool)));
1612 connect(uiFilePB, SIGNAL(clicked()),
1613 this, SLOT(select_ui()));
1614 connect(uiFileED, SIGNAL(textChanged(const QString &)),
1615 this, SIGNAL(changed()));
1616 connect(restoreCursorCB, SIGNAL(clicked()),
1617 this, SIGNAL(changed()));
1618 connect(loadSessionCB, SIGNAL(clicked()),
1619 this, SIGNAL(changed()));
1620 connect(loadWindowSizeCB, SIGNAL(clicked()),
1621 this, SIGNAL(changed()));
1622 connect(loadWindowLocationCB, SIGNAL(clicked()),
1623 this, SIGNAL(changed()));
1624 connect(windowWidthSB, SIGNAL(valueChanged(int)),
1625 this, SIGNAL(changed()));
1626 connect(windowHeightSB, SIGNAL(valueChanged(int)),
1627 this, SIGNAL(changed()));
1628 connect(cursorFollowsCB, SIGNAL(clicked()),
1629 this, SIGNAL(changed()));
1630 connect(autoSaveSB, SIGNAL(valueChanged(int)),
1631 this, SIGNAL(changed()));
1632 connect(autoSaveCB, SIGNAL(clicked()),
1633 this, SIGNAL(changed()));
1634 connect(lastfilesSB, SIGNAL(valueChanged(int)),
1635 this, SIGNAL(changed()));
1636 lastfilesSB->setMaximum(maxlastfiles);
1640 void PrefUserInterface::apply(LyXRC & rc) const
1642 rc.ui_file = internal_path(fromqstr(uiFileED->text()));
1643 rc.use_lastfilepos = restoreCursorCB->isChecked();
1644 rc.load_session = loadSessionCB->isChecked();
1645 if (loadWindowSizeCB->isChecked()) {
1646 rc.geometry_width = 0;
1647 rc.geometry_height = 0;
1649 rc.geometry_width = windowWidthSB->value();
1650 rc.geometry_height = windowHeightSB->value();
1652 rc.geometry_xysaved = loadWindowLocationCB->isChecked();
1653 rc.cursor_follows_scrollbar = cursorFollowsCB->isChecked();
1654 rc.autosave = autoSaveSB->value() * 60;
1655 rc.make_backup = autoSaveCB->isChecked();
1656 rc.num_lastfiles = lastfilesSB->value();
1660 void PrefUserInterface::update(LyXRC const & rc)
1662 uiFileED->setText(toqstr(external_path(rc.ui_file)));
1663 restoreCursorCB->setChecked(rc.use_lastfilepos);
1664 loadSessionCB->setChecked(rc.load_session);
1665 bool loadWindowSize = rc.geometry_width == 0 && rc.geometry_height == 0;
1666 loadWindowSizeCB->setChecked(loadWindowSize);
1667 if (!loadWindowSize) {
1668 windowWidthSB->setValue(rc.geometry_width);
1669 windowHeightSB->setValue(rc.geometry_height);
1671 loadWindowLocationCB->setChecked(rc.geometry_xysaved);
1672 cursorFollowsCB->setChecked(rc.cursor_follows_scrollbar);
1673 // convert to minutes
1674 int mins(rc.autosave / 60);
1675 if (rc.autosave && !mins)
1677 autoSaveSB->setValue(mins);
1678 autoSaveCB->setChecked(rc.make_backup);
1679 lastfilesSB->setValue(rc.num_lastfiles);
1683 void PrefUserInterface::select_ui()
1685 docstring const name =
1686 from_utf8(internal_path(fromqstr(uiFileED->text())));
1687 docstring file = form_->browseUI(name);
1689 uiFileED->setText(toqstr(file));
1693 void PrefUserInterface::on_loadWindowSizeCB_toggled(bool loadwindowsize)
1695 windowWidthLA->setDisabled(loadwindowsize);
1696 windowHeightLA->setDisabled(loadwindowsize);
1697 windowWidthSB->setDisabled(loadwindowsize);
1698 windowHeightSB->setDisabled(loadwindowsize);
1702 /////////////////////////////////////////////////////////////////////
1706 /////////////////////////////////////////////////////////////////////
1709 void ShortcutEdit::keyPressEvent(QKeyEvent * e)
1711 int keyQt = e->key();
1713 case Qt::Key_AltGr: //or else we get unicode salad
1715 case Qt::Key_Control:
1721 uint modifierKeys = e->modifiers();
1724 if (modifierKeys & Qt::SHIFT)
1726 if (modifierKeys & Qt::CTRL)
1728 if (modifierKeys & Qt::ALT)
1732 setKeySymbol(&sym, e);
1733 txt += toqstr(sym.getSymbolName());
1735 if (text().isEmpty())
1738 setText(text() + " " + txt);
1744 //prevent Qt from special casing Tab and Backtab
1745 bool ShortcutEdit::event(QEvent* e)
1747 if (e->type() == QEvent::ShortcutOverride)
1750 if (e->type() == QEvent::KeyPress) {
1751 keyPressEvent(static_cast<QKeyEvent *>(e));
1755 return QLineEdit::event(e);
1759 GuiShortcutDialog::GuiShortcutDialog(QWidget * parent) : QDialog(parent)
1761 Ui::shortcutUi::setupUi(this);
1762 QDialog::setModal(true);
1763 // adapted from ui_ShortcutUi.h
1764 shortcutLE = new ShortcutEdit(parent);
1765 shortcutLE->setObjectName(QString::fromUtf8("shortcutLE"));
1766 QSizePolicy sp(static_cast<QSizePolicy::Policy>(7), static_cast<QSizePolicy::Policy>(0));
1767 sp.setHorizontalStretch(0);
1768 sp.setVerticalStretch(0);
1769 sp.setHeightForWidth(shortcutLE->sizePolicy().hasHeightForWidth());
1770 shortcutLE->setSizePolicy(sp);
1771 gridLayout->addWidget(shortcutLE, 1, 1, 1, 1);
1772 QWidget::setTabOrder(shortcutLE, okPB);
1776 PrefShortcuts::PrefShortcuts(GuiPreferences * form, QWidget * parent)
1777 : PrefModule(_("Shortcuts"), form, parent)
1781 shortcutsTW->setColumnCount(2);
1782 shortcutsTW->headerItem()->setText(0, qt_("Function"));
1783 shortcutsTW->headerItem()->setText(1, qt_("Shortcut"));
1784 shortcutsTW->setSortingEnabled(true);
1785 // Multi-selection can be annoying.
1786 // shortcutsTW->setSelectionMode(QAbstractItemView::MultiSelection);
1787 shortcutsTW->header()->resizeSection(0, 200);
1789 connect(bindFilePB, SIGNAL(clicked()),
1790 this, SLOT(select_bind()));
1791 connect(bindFileED, SIGNAL(textChanged(const QString &)),
1792 this, SIGNAL(changed()));
1793 connect(removePB, SIGNAL(clicked()),
1794 this, SIGNAL(changed()));
1796 shortcut_ = new GuiShortcutDialog(this);
1797 shortcut_bc_.setPolicy(ButtonPolicy::OkCancelPolicy);
1798 shortcut_bc_.setOK(shortcut_->okPB);
1799 shortcut_bc_.setCancel(shortcut_->cancelPB);
1801 connect(shortcut_->okPB, SIGNAL(clicked()),
1802 shortcut_, SLOT(accept()));
1803 connect(shortcut_->okPB, SIGNAL(clicked()),
1804 this, SIGNAL(changed()));
1805 connect(shortcut_->cancelPB, SIGNAL(clicked()),
1806 shortcut_, SLOT(reject()));
1807 connect(shortcut_->clearPB, SIGNAL(clicked()),
1808 this, SLOT(shortcut_clearPB_pressed()));
1809 connect(shortcut_->okPB, SIGNAL(clicked()),
1810 this, SLOT(shortcut_okPB_pressed()));
1814 void PrefShortcuts::apply(LyXRC & rc) const
1816 rc.bind_file = internal_path(fromqstr(bindFileED->text()));
1817 // write user_bind and user_unbind to .lyx/bind/user.bind
1818 string bind_dir = addPath(package().user_support().absFilename(), "bind");
1819 if (!FileName(bind_dir).exists() && mkdir(FileName(bind_dir), 0777)) {
1820 lyxerr << "LyX could not create the user bind directory '"
1821 << bind_dir << "'. All user-defined key bindings will be lost." << endl;
1824 if (!FileName(bind_dir).isDirWritable()) {
1825 lyxerr << "LyX could not write to the user bind directory '"
1826 << bind_dir << "'. All user-defined key bindings will be lost." << endl;
1829 FileName user_bind_file = FileName(addName(bind_dir, "user.bind"));
1830 user_bind_.write(user_bind_file.toFilesystemEncoding(), false, false);
1831 user_unbind_.write(user_bind_file.toFilesystemEncoding(), true, true);
1832 // immediately apply the keybindings. Why this is not done before?
1833 // The good thing is that the menus are updated automatically.
1834 theTopLevelKeymap().clear();
1835 theTopLevelKeymap().read(rc.bind_file);
1836 theTopLevelKeymap().read("user");
1840 void PrefShortcuts::update(LyXRC const & rc)
1842 bindFileED->setText(toqstr(external_path(rc.bind_file)));
1844 system_bind_.clear();
1846 user_unbind_.clear();
1847 system_bind_.read(rc.bind_file);
1848 // \unbind in user.bind is added to user_unbind_
1849 user_bind_.read("user", &user_unbind_);
1850 updateShortcutsTW();
1854 void PrefShortcuts::updateShortcutsTW()
1856 shortcutsTW->clear();
1858 editItem_ = new QTreeWidgetItem(shortcutsTW);
1859 editItem_->setText(0, toqstr("Cursor, Mouse and Editing functions"));
1860 editItem_->setFlags(editItem_->flags() & ~Qt::ItemIsSelectable);
1862 mathItem_ = new QTreeWidgetItem(shortcutsTW);
1863 mathItem_->setText(0, toqstr("Mathematical Symbols"));
1864 mathItem_->setFlags(mathItem_->flags() & ~Qt::ItemIsSelectable);
1866 bufferItem_ = new QTreeWidgetItem(shortcutsTW);
1867 bufferItem_->setText(0, toqstr("Buffer and Window"));
1868 bufferItem_->setFlags(bufferItem_->flags() & ~Qt::ItemIsSelectable);
1870 layoutItem_ = new QTreeWidgetItem(shortcutsTW);
1871 layoutItem_->setText(0, toqstr("Font, Layouts and Textclasses"));
1872 layoutItem_->setFlags(layoutItem_->flags() & ~Qt::ItemIsSelectable);
1874 systemItem_ = new QTreeWidgetItem(shortcutsTW);
1875 systemItem_->setText(0, toqstr("System and Miscellaneous"));
1876 systemItem_->setFlags(systemItem_->flags() & ~Qt::ItemIsSelectable);
1878 // listBindings(unbound=true) lists all bound and unbound lfuns
1879 // Items in this list is tagged by its source.
1880 KeyMap::BindingList bindinglist = system_bind_.listBindings(true,
1881 static_cast<int>(System));
1882 KeyMap::BindingList user_bindinglist = user_bind_.listBindings(false,
1883 static_cast<int>(UserBind));
1884 KeyMap::BindingList user_unbindinglist = user_unbind_.listBindings(false,
1885 static_cast<int>(UserUnbind));
1886 bindinglist.insert(bindinglist.end(), user_bindinglist.begin(),
1887 user_bindinglist.end());
1888 bindinglist.insert(bindinglist.end(), user_unbindinglist.begin(),
1889 user_unbindinglist.end());
1891 KeyMap::BindingList::const_iterator it = bindinglist.begin();
1892 KeyMap::BindingList::const_iterator it_end = bindinglist.end();
1893 for (; it != it_end; ++it)
1894 insertShortcutItem(it->get<0>(), it->get<1>(),
1895 static_cast<item_type>(it->get<2>()));
1897 shortcutsTW->sortItems(0, Qt::AscendingOrder);
1898 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
1899 removePB->setEnabled(!items.isEmpty() && !items[0]->text(1).isEmpty());
1900 searchPB->setEnabled(!searchLE->text().isEmpty());
1904 void PrefShortcuts::setItemType(QTreeWidgetItem * item, item_type tag)
1906 item->setData(0, Qt::UserRole, QVariant(tag));
1919 case UserExtraUnbind:
1924 #if QT_VERSION >= 0x040200
1925 item->setForeground(0, QBrush(QColor(color)));
1926 item->setForeground(1, QBrush(QColor(color)));
1928 item->setTextColor(0, QColor(color));
1929 item->setTextColor(1, QColor(color));
1934 QTreeWidgetItem * PrefShortcuts::insertShortcutItem(FuncRequest const & lfun,
1935 KeySequence const & seq, item_type tag)
1937 kb_action action = lfun.action;
1938 string const action_name = lyxaction.getActionName(action);
1939 QString const lfun_name = toqstr(from_utf8(action_name)
1940 + " " + lfun.argument());
1941 // use BindFile format instead of a more verbose form Portable
1942 // if the Shortcut dialog can hide all the bind file stuff,
1943 // Portable format can be used.
1944 QString const shortcut = toqstr(seq.print(KeySequence::BindFile));
1945 item_type item_tag = tag;
1947 QTreeWidgetItem * newItem = NULL;
1948 // for unbind items, try to find an existing item in the system bind list
1949 if (tag == UserUnbind) {
1950 QList<QTreeWidgetItem*> const items = shortcutsTW->findItems(lfun_name,
1951 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 0);
1952 for (int i = 0; i < items.size(); ++i) {
1953 if (items[i]->text(1) == shortcut)
1957 // if not found, this unbind item is UserExtraUnbind
1959 item_tag = UserExtraUnbind;
1962 switch(lyxaction.getActionType(action)) {
1963 case LyXAction::Hidden:
1965 case LyXAction::Edit:
1966 newItem = new QTreeWidgetItem(editItem_);
1968 case LyXAction::Math:
1969 newItem = new QTreeWidgetItem(mathItem_);
1971 case LyXAction::Buffer:
1972 newItem = new QTreeWidgetItem(bufferItem_);
1974 case LyXAction::Layout:
1975 newItem = new QTreeWidgetItem(layoutItem_);
1977 case LyXAction::System:
1978 newItem = new QTreeWidgetItem(systemItem_);
1981 // this should not happen
1982 newItem = new QTreeWidgetItem(shortcutsTW);
1986 newItem->setText(0, lfun_name);
1987 newItem->setText(1, shortcut);
1988 setItemType(newItem, item_tag);
1993 void PrefShortcuts::on_shortcutsTW_itemSelectionChanged()
1995 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
1996 removePB->setEnabled(!items.isEmpty() && !items[0]->text(1).isEmpty());
1997 if (items.isEmpty())
2000 item_type tag = static_cast<item_type>(items[0]->data(0, Qt::UserRole).toInt());
2001 if (tag == UserUnbind)
2002 removePB->setText(toqstr("Restore"));
2004 removePB->setText(toqstr("Remove"));
2008 void PrefShortcuts::on_shortcutsTW_itemDoubleClicked()
2010 QTreeWidgetItem * item = shortcutsTW->currentItem();
2011 if (item->flags() & Qt::ItemIsSelectable) {
2012 shortcut_->lfunLE->setText(item->text(0));
2013 shortcut_->shortcutLE->setText(item->text(1));
2019 void PrefShortcuts::select_bind()
2021 docstring const name =
2022 from_utf8(internal_path(fromqstr(bindFileED->text())));
2023 docstring file = form_->browsebind(name);
2024 if (!file.empty()) {
2025 bindFileED->setText(toqstr(file));
2026 system_bind_ = KeyMap();
2027 system_bind_.read(to_utf8(file));
2028 updateShortcutsTW();
2033 void PrefShortcuts::on_newPB_pressed()
2035 shortcut_->lfunLE->clear();
2036 shortcut_->shortcutLE->clear();
2041 void PrefShortcuts::on_removePB_pressed()
2043 // it seems that only one item can be selected, but I am
2044 // removing all selected items anyway.
2045 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
2046 for (int i = 0; i < items.size(); ++i) {
2047 string shortcut = fromqstr(items[i]->text(1));
2048 string lfun = fromqstr(items[i]->text(0));
2049 FuncRequest func = lyxaction.lookupFunc(lfun);
2050 item_type tag = static_cast<item_type>(items[i]->data(0, Qt::UserRole).toInt());
2054 // for system bind, we do not touch the item
2055 // but add an user unbind item
2056 user_unbind_.bind(shortcut, func);
2057 setItemType(items[i], UserUnbind);
2061 // for user_bind, we remove this bind
2062 QTreeWidgetItem * parent = items[i]->parent();
2063 parent->takeChild(parent->indexOfChild(items[i]));
2064 user_bind_.unbind(shortcut, func);
2068 // for user_unbind, we remove the unbind, and the item
2069 // become System again.
2070 user_unbind_.unbind(shortcut, func);
2071 setItemType(items[i], System);
2074 case UserExtraUnbind: {
2075 // for user unbind that is not in system bind file,
2076 // remove this unbind file
2077 QTreeWidgetItem * parent = items[i]->parent();
2078 parent->takeChild(parent->indexOfChild(items[i]));
2079 user_unbind_.unbind(shortcut, func);
2086 void PrefShortcuts::on_searchPB_pressed()
2088 // search both columns
2089 QList<QTreeWidgetItem *> matched = shortcutsTW->findItems(searchLE->text(),
2090 Qt::MatchFlags(Qt::MatchContains | Qt::MatchRecursive), 0);
2091 matched += shortcutsTW->findItems(searchLE->text(),
2092 Qt::MatchFlags(Qt::MatchContains | Qt::MatchRecursive), 1);
2094 // hide everyone (to avoid searching in matched QList repeatedly
2095 QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Selectable);
2097 shortcutsTW->setItemHidden(*it++, true);
2098 // show matched items
2099 for (int i = 0; i < matched.size(); ++i) {
2100 shortcutsTW->setItemHidden(matched[i], false);
2101 shortcutsTW->setItemExpanded(matched[i]->parent(), true);
2106 void PrefShortcuts::on_searchLE_textChanged()
2108 searchPB->setEnabled(!searchLE->text().isEmpty());
2109 if (searchLE->text().isEmpty()) {
2110 // show all hidden items
2111 QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Hidden);
2113 shortcutsTW->setItemHidden(*it++, false);
2118 void PrefShortcuts::shortcut_okPB_pressed()
2120 string shortcut = fromqstr(shortcut_->shortcutLE->text());
2121 string lfun = fromqstr(shortcut_->lfunLE->text());
2122 FuncRequest func = lyxaction.lookupFunc(lfun);
2124 if (func.action == LFUN_UNKNOWN_ACTION) {
2125 Alert::error(_("Failed to create shortcut"),
2126 _("Unknown or invalid lyx function"));
2130 KeySequence k(0, 0);
2131 string::size_type const res = k.parse(shortcut);
2132 if (res != string::npos) {
2133 Alert::error(_("Failed to create shortcut"),
2134 _("Invalid key sequence"));
2138 // if both lfun and shortcut is valid
2139 if (user_bind_.hasBinding(k, func) || system_bind_.hasBinding(k, func)) {
2140 Alert::error(_("Failed to create shortcut"),
2141 _("Shortcut is alreay defined"));
2145 QTreeWidgetItem * item = insertShortcutItem(func, k, UserBind);
2147 user_bind_.bind(shortcut, func);
2148 shortcutsTW->sortItems(0, Qt::AscendingOrder);
2149 shortcutsTW->setItemExpanded(item->parent(), true);
2150 shortcutsTW->scrollToItem(item);
2152 Alert::error(_("Failed to create shortcut"),
2153 _("Can not insert shortcut to the list"));
2159 void PrefShortcuts::shortcut_clearPB_pressed()
2161 shortcut_->shortcutLE->clear();
2162 shortcut_->shortcutLE->setFocus();
2166 /////////////////////////////////////////////////////////////////////
2170 /////////////////////////////////////////////////////////////////////
2172 PrefIdentity::PrefIdentity(QWidget * parent)
2173 : PrefModule(_("Identity"), 0, parent)
2177 connect(nameED, SIGNAL(textChanged(const QString&)),
2178 this, SIGNAL(changed()));
2179 connect(emailED, SIGNAL(textChanged(const QString&)),
2180 this, SIGNAL(changed()));
2184 void PrefIdentity::apply(LyXRC & rc) const
2186 rc.user_name = fromqstr(nameED->text());
2187 rc.user_email = fromqstr(emailED->text());
2191 void PrefIdentity::update(LyXRC const & rc)
2193 nameED->setText(toqstr(rc.user_name));
2194 emailED->setText(toqstr(rc.user_email));
2199 /////////////////////////////////////////////////////////////////////
2203 /////////////////////////////////////////////////////////////////////
2205 GuiPreferences::GuiPreferences(LyXView & lv)
2206 : GuiDialog(lv, "prefs"), update_screen_font_(false)
2209 setViewTitle(_("Preferences"));
2211 QDialog::setModal(false);
2213 connect(savePB, SIGNAL(clicked()), this, SLOT(slotOK()));
2214 connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
2215 connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
2216 connect(restorePB, SIGNAL(clicked()), this, SLOT(slotRestore()));
2218 add(new PrefUserInterface(this));
2219 add(new PrefShortcuts(this));
2220 add(new PrefScreenFonts(this));
2221 add(new PrefColors(this));
2222 add(new PrefDisplay);
2223 add(new PrefKeyboard(this));
2225 add(new PrefPaths(this));
2227 add(new PrefIdentity);
2229 add(new PrefLanguage);
2230 add(new PrefSpellchecker(this));
2232 add(new PrefPrinter);
2234 add(new PrefPlaintext);
2235 add(new PrefLatex(this));
2237 PrefConverters * converters = new PrefConverters(this);
2238 PrefFileformats * formats = new PrefFileformats(this);
2239 connect(formats, SIGNAL(formatsChanged()),
2240 converters, SLOT(updateGui()));
2244 prefsPS->setCurrentPanel(_("User interface"));
2245 // FIXME: hack to work around resizing bug in Qt >= 4.2
2246 // bug verified with Qt 4.2.{0-3} (JSpitzm)
2247 #if QT_VERSION >= 0x040200
2248 prefsPS->updateGeometry();
2251 bc().setPolicy(ButtonPolicy::PreferencesPolicy);
2253 bc().setApply(applyPB);
2254 bc().setCancel(closePB);
2255 bc().setRestore(restorePB);
2259 void GuiPreferences::add(PrefModule * module)
2261 BOOST_ASSERT(module);
2262 prefsPS->addPanel(module, module->title());
2263 connect(module, SIGNAL(changed()), this, SLOT(change_adaptor()));
2264 modules_.push_back(module);
2268 void GuiPreferences::closeEvent(QCloseEvent * e)
2275 void GuiPreferences::change_adaptor()
2281 void GuiPreferences::apply(LyXRC & rc) const
2283 size_t end = modules_.size();
2284 for (size_t i = 0; i != end; ++i)
2285 modules_[i]->apply(rc);
2289 void GuiPreferences::updateRc(LyXRC const & rc)
2291 size_t const end = modules_.size();
2292 for (size_t i = 0; i != end; ++i)
2293 modules_[i]->update(rc);
2297 void GuiPreferences::applyView()
2303 void GuiPreferences::updateContents()
2309 bool GuiPreferences::initialiseParams(std::string const &)
2312 formats_ = lyx::formats;
2313 converters_ = theConverters();
2314 converters_.update(formats_);
2315 movers_ = theMovers();
2317 update_screen_font_ = false;
2323 void GuiPreferences::dispatchParams()
2326 rc_.write(ss, true);
2327 dispatch(FuncRequest(LFUN_LYXRC_APPLY, ss.str()));
2328 // FIXME: these need lfuns
2330 theBufferList().setCurrentAuthor(from_utf8(rc_.user_name), from_utf8(rc_.user_email));
2332 lyx::formats = formats_;
2334 theConverters() = converters_;
2335 theConverters().update(lyx::formats);
2336 theConverters().buildGraph();
2338 theMovers() = movers_;
2340 vector<string>::const_iterator it = colors_.begin();
2341 vector<string>::const_iterator const end = colors_.end();
2342 for (; it != end; ++it)
2343 dispatch(FuncRequest(LFUN_SET_COLOR, *it));
2346 if (update_screen_font_) {
2347 dispatch(FuncRequest(LFUN_SCREEN_FONT_UPDATE));
2348 update_screen_font_ = false;
2351 // The Save button has been pressed
2353 dispatch(FuncRequest(LFUN_PREFERENCES_SAVE));
2357 void GuiPreferences::setColor(Color_color col, string const & hex)
2359 colors_.push_back(lcolor.getLyXName(col) + ' ' + hex);
2363 void GuiPreferences::updateScreenFonts()
2365 update_screen_font_ = true;
2369 docstring const GuiPreferences::browsebind(docstring const & file) const
2371 return browseLibFile(from_ascii("bind"), file, from_ascii("bind"),
2372 _("Choose bind file"),
2373 FileFilterList(_("LyX bind files (*.bind)")));
2377 docstring const GuiPreferences::browseUI(docstring const & file) const
2379 return browseLibFile(from_ascii("ui"), file, from_ascii("ui"),
2380 _("Choose UI file"),
2381 FileFilterList(_("LyX UI files (*.ui)")));
2385 docstring const GuiPreferences::browsekbmap(docstring const & file) const
2387 return browseLibFile(from_ascii("kbd"), file, from_ascii("kmap"),
2388 _("Choose keyboard map"),
2389 FileFilterList(_("LyX keyboard maps (*.kmap)")));
2393 docstring const GuiPreferences::browsedict(docstring const & file) const
2395 if (lyxrc.use_spell_lib)
2396 return browseFile(file,
2397 _("Choose personal dictionary"),
2398 FileFilterList(_("*.pws")));
2400 return browseFile(file,
2401 _("Choose personal dictionary"),
2402 FileFilterList(_("*.ispell")));
2406 docstring const GuiPreferences::browse(docstring const & file,
2407 docstring const & title) const
2409 return browseFile(file, title, FileFilterList(), true);
2413 docstring const GuiPreferences::browsedir(docstring const & path,
2414 docstring const & title) const
2416 return browseDir(path, title);
2420 // We support less paper sizes than the document dialog
2421 // Therefore this adjustment is needed.
2422 PAPER_SIZE GuiPreferences::toPaperSize(int i) const
2426 return PAPER_DEFAULT;
2428 return PAPER_USLETTER;
2430 return PAPER_USLEGAL;
2432 return PAPER_USEXECUTIVE;
2442 // should not happen
2443 return PAPER_DEFAULT;
2448 int GuiPreferences::fromPaperSize(PAPER_SIZE papersize) const
2450 switch (papersize) {
2453 case PAPER_USLETTER:
2457 case PAPER_USEXECUTIVE:
2468 // should not happen
2474 Dialog * createGuiPreferences(LyXView & lv) { return new GuiPreferences(lv); }
2477 } // namespace frontend
2480 #include "GuiPrefs_moc.cpp"