3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
8 * Full author contact details are available in file CREDITS.
15 #include "qt_helpers.h"
16 #include "GuiApplication.h"
17 #include "GuiFontLoader.h"
19 #include "BufferList.h"
21 #include "ConverterCache.h"
24 #include "FuncRequest.h"
26 #include "GuiFontExample.h"
28 #include "KeySequence.h"
29 #include "LyXAction.h"
30 #include "PanelStack.h"
34 #include "support/lstrings.h"
35 #include "support/os.h"
36 #include "support/FileFilterList.h"
38 #include "frontend_helpers.h"
40 #include "frontends/alert.h"
41 #include "frontends/Application.h"
44 #include <QColorDialog>
45 #include <QFontDatabase>
46 #include <QHeaderView>
48 #include <QPixmapCache>
49 #include <QPushButton>
52 #include <QTreeWidget>
53 #include <QTreeWidgetItem>
55 #include <QCloseEvent>
65 using std::ostringstream;
73 using support::compare_ascii_no_case;
74 using support::os::external_path;
75 using support::os::external_path_list;
76 using support::os::internal_path;
77 using support::os::internal_path_list;
78 using support::FileFilterList;
81 /////////////////////////////////////////////////////////////////////
85 /////////////////////////////////////////////////////////////////////
88 static size_t findPos_helper(std::vector<A> const & vec, A const & val)
90 typedef typename std::vector<A>::const_iterator Cit;
92 Cit it = std::find(vec.begin(), vec.end(), val);
95 return std::distance(vec.begin(), it);
99 static std::pair<string, string> parseFontName(string const & name)
101 string::size_type const idx = name.find('[');
102 if (idx == string::npos || idx == 0)
103 return make_pair(name, string());
104 return make_pair(name.substr(0, idx - 1),
105 name.substr(idx + 1, name.size() - idx - 2));
109 static void setComboxFont(QComboBox * cb, string const & family,
110 string const & foundry)
112 QString fontname = toqstr(family);
113 if (!foundry.empty())
114 fontname += " [" + toqstr(foundry) + ']';
116 for (int i = 0; i < cb->count(); ++i) {
117 if (cb->itemText(i) == fontname) {
118 cb->setCurrentIndex(i);
123 // Try matching without foundry name
125 // We count in reverse in order to prefer the Xft foundry
126 for (int i = cb->count(); --i >= 0;) {
127 pair<string, string> tmp = parseFontName(fromqstr(cb->itemText(i)));
128 if (compare_ascii_no_case(tmp.first, family) == 0) {
129 cb->setCurrentIndex(i);
134 // family alone can contain e.g. "Helvetica [Adobe]"
135 pair<string, string> tmpfam = parseFontName(family);
137 // We count in reverse in order to prefer the Xft foundry
138 for (int i = cb->count() - 1; i >= 0; --i) {
139 pair<string, string> tmp = parseFontName(fromqstr(cb->itemText(i)));
140 if (compare_ascii_no_case(tmp.first, tmpfam.first) == 0) {
141 cb->setCurrentIndex(i);
146 // Bleh, default fonts, and the names couldn't be found. Hack
150 font.setKerning(false);
152 if (family == theApp()->romanFontName()) {
153 font.setStyleHint(QFont::Serif);
154 font.setFamily(family.c_str());
155 } else if (family == theApp()->sansFontName()) {
156 font.setStyleHint(QFont::SansSerif);
157 font.setFamily(family.c_str());
158 } else if (family == theApp()->typewriterFontName()) {
159 font.setStyleHint(QFont::TypeWriter);
160 font.setFamily(family.c_str());
162 lyxerr << "FAILED to find the default font: '"
163 << foundry << "', '" << family << '\''<< endl;
167 QFontInfo info(font);
168 pair<string, string> tmp = parseFontName(fromqstr(info.family()));
169 string const & default_font_name = tmp.first;
170 lyxerr << "Apparent font is " << default_font_name << endl;
172 for (int i = 0; i < cb->count(); ++i) {
173 lyxerr << "Looking at " << fromqstr(cb->itemText(i)) << endl;
174 if (compare_ascii_no_case(fromqstr(cb->itemText(i)),
175 default_font_name) == 0) {
176 cb->setCurrentIndex(i);
181 lyxerr << "FAILED to find the font: '"
182 << foundry << "', '" << family << '\'' <<endl;
186 /////////////////////////////////////////////////////////////////////
190 /////////////////////////////////////////////////////////////////////
192 PrefPlaintext::PrefPlaintext(QWidget * parent)
193 : PrefModule(_("Plain text"), 0, parent)
196 connect(plaintextLinelengthSB, SIGNAL(valueChanged(int)),
197 this, SIGNAL(changed()));
198 connect(plaintextRoffED, SIGNAL(textChanged(const QString&)),
199 this, SIGNAL(changed()));
203 void PrefPlaintext::apply(LyXRC & rc) const
205 rc.plaintext_linelen = plaintextLinelengthSB->value();
206 rc.plaintext_roff_command = fromqstr(plaintextRoffED->text());
210 void PrefPlaintext::update(LyXRC const & rc)
212 plaintextLinelengthSB->setValue(rc.plaintext_linelen);
213 plaintextRoffED->setText(toqstr(rc.plaintext_roff_command));
217 /////////////////////////////////////////////////////////////////////
221 /////////////////////////////////////////////////////////////////////
223 PrefDate::PrefDate(QWidget * parent)
224 : PrefModule(_("Date format"), 0, parent)
227 connect(DateED, SIGNAL(textChanged(const QString &)),
228 this, SIGNAL(changed()));
232 void PrefDate::apply(LyXRC & rc) const
234 rc.date_insert_format = fromqstr(DateED->text());
238 void PrefDate::update(LyXRC const & rc)
240 DateED->setText(toqstr(rc.date_insert_format));
244 /////////////////////////////////////////////////////////////////////
248 /////////////////////////////////////////////////////////////////////
250 PrefKeyboard::PrefKeyboard(GuiPreferences * form, QWidget * parent)
251 : PrefModule(_("Keyboard"), form, parent)
255 connect(keymapCB, SIGNAL(clicked()),
256 this, SIGNAL(changed()));
257 connect(firstKeymapED, SIGNAL(textChanged(const QString&)),
258 this, SIGNAL(changed()));
259 connect(secondKeymapED, SIGNAL(textChanged(const QString&)),
260 this, SIGNAL(changed()));
264 void PrefKeyboard::apply(LyXRC & rc) const
266 // FIXME: can derive CB from the two EDs
267 rc.use_kbmap = keymapCB->isChecked();
268 rc.primary_kbmap = internal_path(fromqstr(firstKeymapED->text()));
269 rc.secondary_kbmap = internal_path(fromqstr(secondKeymapED->text()));
273 void PrefKeyboard::update(LyXRC const & rc)
275 // FIXME: can derive CB from the two EDs
276 keymapCB->setChecked(rc.use_kbmap);
277 firstKeymapED->setText(toqstr(external_path(rc.primary_kbmap)));
278 secondKeymapED->setText(toqstr(external_path(rc.secondary_kbmap)));
282 QString PrefKeyboard::testKeymap(QString keymap)
284 return toqstr(form_->browsekbmap(from_utf8(internal_path(fromqstr(keymap)))));
288 void PrefKeyboard::on_firstKeymapPB_clicked(bool)
290 QString const file = testKeymap(firstKeymapED->text());
292 firstKeymapED->setText(file);
296 void PrefKeyboard::on_secondKeymapPB_clicked(bool)
298 QString const file = testKeymap(secondKeymapED->text());
300 secondKeymapED->setText(file);
304 void PrefKeyboard::on_keymapCB_toggled(bool keymap)
306 firstKeymapLA->setEnabled(keymap);
307 secondKeymapLA->setEnabled(keymap);
308 firstKeymapED->setEnabled(keymap);
309 secondKeymapED->setEnabled(keymap);
310 firstKeymapPB->setEnabled(keymap);
311 secondKeymapPB->setEnabled(keymap);
315 /////////////////////////////////////////////////////////////////////
319 /////////////////////////////////////////////////////////////////////
321 PrefLatex::PrefLatex(GuiPreferences * form, QWidget * parent)
322 : PrefModule(_("LaTeX"), form, parent)
325 connect(latexEncodingED, SIGNAL(textChanged(const QString&)),
326 this, SIGNAL(changed()));
327 connect(latexChecktexED, SIGNAL(textChanged(const QString&)),
328 this, SIGNAL(changed()));
329 connect(latexBibtexED, SIGNAL(textChanged(const QString&)),
330 this, SIGNAL(changed()));
331 connect(latexIndexED, SIGNAL(textChanged(const QString&)),
332 this, SIGNAL(changed()));
333 connect(latexAutoresetCB, SIGNAL(clicked()),
334 this, SIGNAL(changed()));
335 connect(latexDviPaperED, SIGNAL(textChanged(const QString&)),
336 this, SIGNAL(changed()));
337 connect(latexPaperSizeCO, SIGNAL(activated(int)),
338 this, SIGNAL(changed()));
340 #if defined(__CYGWIN__) || defined(_WIN32)
341 pathCB->setVisible(true);
342 connect(pathCB, SIGNAL(clicked()),
343 this, SIGNAL(changed()));
345 pathCB->setVisible(false);
350 void PrefLatex::apply(LyXRC & rc) const
352 rc.fontenc = fromqstr(latexEncodingED->text());
353 rc.chktex_command = fromqstr(latexChecktexED->text());
354 rc.bibtex_command = fromqstr(latexBibtexED->text());
355 rc.index_command = fromqstr(latexIndexED->text());
356 rc.auto_reset_options = latexAutoresetCB->isChecked();
357 rc.view_dvi_paper_option = fromqstr(latexDviPaperED->text());
358 rc.default_papersize =
359 form_->toPaperSize(latexPaperSizeCO->currentIndex());
360 #if defined(__CYGWIN__) || defined(_WIN32)
361 rc.windows_style_tex_paths = pathCB->isChecked();
366 void PrefLatex::update(LyXRC const & rc)
368 latexEncodingED->setText(toqstr(rc.fontenc));
369 latexChecktexED->setText(toqstr(rc.chktex_command));
370 latexBibtexED->setText(toqstr(rc.bibtex_command));
371 latexIndexED->setText(toqstr(rc.index_command));
372 latexAutoresetCB->setChecked(rc.auto_reset_options);
373 latexDviPaperED->setText(toqstr(rc.view_dvi_paper_option));
374 latexPaperSizeCO->setCurrentIndex(
375 form_->fromPaperSize(rc.default_papersize));
376 #if defined(__CYGWIN__) || defined(_WIN32)
377 pathCB->setChecked(rc.windows_style_tex_paths);
382 /////////////////////////////////////////////////////////////////////
386 /////////////////////////////////////////////////////////////////////
388 PrefScreenFonts::PrefScreenFonts(GuiPreferences * form, QWidget * parent)
389 : PrefModule(_("Screen fonts"), form, parent)
393 connect(screenRomanCO, SIGNAL(activated(const QString&)),
394 this, SLOT(select_roman(const QString&)));
395 connect(screenSansCO, SIGNAL(activated(const QString&)),
396 this, SLOT(select_sans(const QString&)));
397 connect(screenTypewriterCO, SIGNAL(activated(const QString&)),
398 this, SLOT(select_typewriter(const QString&)));
400 QFontDatabase fontdb;
401 QStringList families(fontdb.families());
402 for (QStringList::Iterator it = families.begin(); it != families.end(); ++it) {
403 screenRomanCO->addItem(*it);
404 screenSansCO->addItem(*it);
405 screenTypewriterCO->addItem(*it);
407 connect(screenRomanCO, SIGNAL(activated(const QString&)),
408 this, SIGNAL(changed()));
409 connect(screenSansCO, SIGNAL(activated(const QString&)),
410 this, SIGNAL(changed()));
411 connect(screenTypewriterCO, SIGNAL(activated(const QString&)),
412 this, SIGNAL(changed()));
413 connect(screenZoomSB, SIGNAL(valueChanged(int)),
414 this, SIGNAL(changed()));
415 connect(screenDpiSB, SIGNAL(valueChanged(int)),
416 this, SIGNAL(changed()));
417 connect(screenTinyED, SIGNAL(textChanged(const QString&)),
418 this, SIGNAL(changed()));
419 connect(screenSmallestED, SIGNAL(textChanged(const QString&)),
420 this, SIGNAL(changed()));
421 connect(screenSmallerED, SIGNAL(textChanged(const QString&)),
422 this, SIGNAL(changed()));
423 connect(screenSmallED, SIGNAL(textChanged(const QString&)),
424 this, SIGNAL(changed()));
425 connect(screenNormalED, SIGNAL(textChanged(const QString&)),
426 this, SIGNAL(changed()));
427 connect(screenLargeED, SIGNAL(textChanged(const QString&)),
428 this, SIGNAL(changed()));
429 connect(screenLargerED, SIGNAL(textChanged(const QString&)),
430 this, SIGNAL(changed()));
431 connect(screenLargestED, SIGNAL(textChanged(const QString&)),
432 this, SIGNAL(changed()));
433 connect(screenHugeED, SIGNAL(textChanged(const QString&)),
434 this, SIGNAL(changed()));
435 connect(screenHugerED, SIGNAL(textChanged(const QString&)),
436 this, SIGNAL(changed()));
438 screenTinyED->setValidator(new QDoubleValidator(screenTinyED));
439 screenSmallestED->setValidator(new QDoubleValidator(screenSmallestED));
440 screenSmallerED->setValidator(new QDoubleValidator(screenSmallerED));
441 screenSmallED->setValidator(new QDoubleValidator(screenSmallED));
442 screenNormalED->setValidator(new QDoubleValidator(screenNormalED));
443 screenLargeED->setValidator(new QDoubleValidator(screenLargeED));
444 screenLargerED->setValidator(new QDoubleValidator(screenLargerED));
445 screenLargestED->setValidator(new QDoubleValidator(screenLargestED));
446 screenHugeED->setValidator(new QDoubleValidator(screenHugeED));
447 screenHugerED->setValidator(new QDoubleValidator(screenHugerED));
451 void PrefScreenFonts::apply(LyXRC & rc) const
453 LyXRC const oldrc(rc);
455 boost::tie(rc.roman_font_name, rc.roman_font_foundry)
456 = parseFontName(fromqstr(screenRomanCO->currentText()));
457 boost::tie(rc.sans_font_name, rc.sans_font_foundry) =
458 parseFontName(fromqstr(screenSansCO->currentText()));
459 boost::tie(rc.typewriter_font_name, rc.typewriter_font_foundry) =
460 parseFontName(fromqstr(screenTypewriterCO->currentText()));
462 rc.zoom = screenZoomSB->value();
463 rc.dpi = screenDpiSB->value();
464 rc.font_sizes[Font::SIZE_TINY] = fromqstr(screenTinyED->text());
465 rc.font_sizes[Font::SIZE_SCRIPT] = fromqstr(screenSmallestED->text());
466 rc.font_sizes[Font::SIZE_FOOTNOTE] = fromqstr(screenSmallerED->text());
467 rc.font_sizes[Font::SIZE_SMALL] = fromqstr(screenSmallED->text());
468 rc.font_sizes[Font::SIZE_NORMAL] = fromqstr(screenNormalED->text());
469 rc.font_sizes[Font::SIZE_LARGE] = fromqstr(screenLargeED->text());
470 rc.font_sizes[Font::SIZE_LARGER] = fromqstr(screenLargerED->text());
471 rc.font_sizes[Font::SIZE_LARGEST] = fromqstr(screenLargestED->text());
472 rc.font_sizes[Font::SIZE_HUGE] = fromqstr(screenHugeED->text());
473 rc.font_sizes[Font::SIZE_HUGER] = fromqstr(screenHugerED->text());
475 if (rc.font_sizes != oldrc.font_sizes
476 || rc.roman_font_name != oldrc.roman_font_name
477 || rc.sans_font_name != oldrc.sans_font_name
478 || rc.typewriter_font_name != oldrc.typewriter_font_name
479 || rc.zoom != oldrc.zoom || rc.dpi != oldrc.dpi) {
480 // The global QPixmapCache is used in GuiPainter to cache text
481 // painting so we must reset it in case any of the above
482 // parameter is changed.
483 QPixmapCache::clear();
484 guiApp->fontLoader().update();
485 form_->updateScreenFonts();
490 void PrefScreenFonts::update(LyXRC const & rc)
492 setComboxFont(screenRomanCO, rc.roman_font_name,
493 rc.roman_font_foundry);
494 setComboxFont(screenSansCO, rc.sans_font_name,
495 rc.sans_font_foundry);
496 setComboxFont(screenTypewriterCO, rc.typewriter_font_name,
497 rc.typewriter_font_foundry);
499 select_roman(screenRomanCO->currentText());
500 select_sans(screenSansCO->currentText());
501 select_typewriter(screenTypewriterCO->currentText());
503 screenZoomSB->setValue(rc.zoom);
504 screenDpiSB->setValue(rc.dpi);
505 screenTinyED->setText(toqstr(rc.font_sizes[Font::SIZE_TINY]));
506 screenSmallestED->setText(toqstr(rc.font_sizes[Font::SIZE_SCRIPT]));
507 screenSmallerED->setText(toqstr(rc.font_sizes[Font::SIZE_FOOTNOTE]));
508 screenSmallED->setText(toqstr(rc.font_sizes[Font::SIZE_SMALL]));
509 screenNormalED->setText(toqstr(rc.font_sizes[Font::SIZE_NORMAL]));
510 screenLargeED->setText(toqstr(rc.font_sizes[Font::SIZE_LARGE]));
511 screenLargerED->setText(toqstr(rc.font_sizes[Font::SIZE_LARGER]));
512 screenLargestED->setText(toqstr(rc.font_sizes[Font::SIZE_LARGEST]));
513 screenHugeED->setText(toqstr(rc.font_sizes[Font::SIZE_HUGE]));
514 screenHugerED->setText(toqstr(rc.font_sizes[Font::SIZE_HUGER]));
517 void PrefScreenFonts::select_roman(const QString& name)
519 screenRomanFE->set(QFont(name), name);
523 void PrefScreenFonts::select_sans(const QString& name)
525 screenSansFE->set(QFont(name), name);
529 void PrefScreenFonts::select_typewriter(const QString& name)
531 screenTypewriterFE->set(QFont(name), name);
535 /////////////////////////////////////////////////////////////////////
539 /////////////////////////////////////////////////////////////////////
545 bool operator()(Color::color const & lhs, Color::color const & rhs) const {
546 return lcolor.getGUIName(lhs) < lcolor.getGUIName(rhs);
552 PrefColors::PrefColors(GuiPreferences * form, QWidget * parent)
553 : PrefModule( _("Colors"), form, parent)
557 // FIXME: all of this initialization should be put into the controller.
558 // See http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg113301.html
559 // for some discussion of why that is not trivial.
560 QPixmap icon(32, 32);
561 for (int i = 0; i < Color::ignore; ++i) {
562 Color::color lc = static_cast<Color::color>(i);
563 if (lc == Color::none
564 || lc == Color::black
565 || lc == Color::white
567 || lc == Color::green
570 || lc == Color::magenta
571 || lc == Color::yellow
572 || lc == Color::inherit
573 || lc == Color::ignore) continue;
575 lcolors_.push_back(lc);
577 std::sort(lcolors_.begin(), lcolors_.end(), ColorSorter());
578 vector<Color_color>::const_iterator cit = lcolors_.begin();
579 vector<Color_color>::const_iterator const end = lcolors_.end();
580 for (; cit != end; ++cit) {
581 (void) new QListWidgetItem(QIcon(icon),
582 toqstr(lcolor.getGUIName(*cit)), lyxObjectsLW);
584 curcolors_.resize(lcolors_.size());
585 newcolors_.resize(lcolors_.size());
586 // End initialization
588 connect(colorChangePB, SIGNAL(clicked()),
589 this, SLOT(change_color()));
590 connect(lyxObjectsLW, SIGNAL(itemSelectionChanged()),
591 this, SLOT(change_lyxObjects_selection()));
592 connect(lyxObjectsLW, SIGNAL(itemActivated(QListWidgetItem*)),
593 this, SLOT(change_color()));
597 void PrefColors::apply(LyXRC & /*rc*/) const
599 for (unsigned int i = 0; i < lcolors_.size(); ++i)
600 if (curcolors_[i] != newcolors_[i])
601 form_->setColor(lcolors_[i], fromqstr(newcolors_[i]));
605 void PrefColors::update(LyXRC const & /*rc*/)
607 for (unsigned int i = 0; i < lcolors_.size(); ++i) {
608 QColor color = QColor(guiApp->colorCache().get(lcolors_[i]));
609 QPixmap coloritem(32, 32);
610 coloritem.fill(color);
611 lyxObjectsLW->item(i)->setIcon(QIcon(coloritem));
612 newcolors_[i] = curcolors_[i] = color.name();
614 change_lyxObjects_selection();
617 void PrefColors::change_color()
619 int const row = lyxObjectsLW->currentRow();
625 QString const color = newcolors_[row];
626 QColor c = QColorDialog::getColor(QColor(color), qApp->focusWidget());
628 if (c.isValid() && c.name() != color) {
629 newcolors_[row] = c.name();
630 QPixmap coloritem(32, 32);
632 lyxObjectsLW->currentItem()->setIcon(QIcon(coloritem));
638 void PrefColors::change_lyxObjects_selection()
640 colorChangePB->setDisabled(lyxObjectsLW->currentRow() < 0);
644 /////////////////////////////////////////////////////////////////////
648 /////////////////////////////////////////////////////////////////////
650 PrefDisplay::PrefDisplay(QWidget * parent)
651 : PrefModule(_("Graphics"), 0, parent)
654 connect(instantPreviewCO, SIGNAL(activated(int)),
655 this, SIGNAL(changed()));
656 connect(displayGraphicsCO, SIGNAL(activated(int)),
657 this, SIGNAL(changed()));
661 void PrefDisplay::apply(LyXRC & rc) const
663 switch (instantPreviewCO->currentIndex()) {
664 case 0: rc.preview = LyXRC::PREVIEW_OFF; break;
665 case 1: rc.preview = LyXRC::PREVIEW_NO_MATH; break;
666 case 2: rc.preview = LyXRC::PREVIEW_ON; break;
669 lyx::graphics::DisplayType dtype;
670 switch (displayGraphicsCO->currentIndex()) {
671 case 3: dtype = lyx::graphics::NoDisplay; break;
672 case 2: dtype = lyx::graphics::ColorDisplay; break;
673 case 1: dtype = lyx::graphics::GrayscaleDisplay; break;
674 case 0: dtype = lyx::graphics::MonochromeDisplay; break;
675 default: dtype = lyx::graphics::GrayscaleDisplay;
677 rc.display_graphics = dtype;
679 // FIXME!! The graphics cache no longer has a changeDisplay method.
681 if (old_value != rc.display_graphics) {
682 lyx::graphics::GCache & gc = lyx::graphics::GCache::get();
689 void PrefDisplay::update(LyXRC const & rc)
691 switch (rc.preview) {
692 case LyXRC::PREVIEW_OFF:
693 instantPreviewCO->setCurrentIndex(0);
695 case LyXRC::PREVIEW_NO_MATH :
696 instantPreviewCO->setCurrentIndex(1);
698 case LyXRC::PREVIEW_ON :
699 instantPreviewCO->setCurrentIndex(2);
704 switch (rc.display_graphics) {
705 case lyx::graphics::NoDisplay: item = 3; break;
706 case lyx::graphics::ColorDisplay: item = 2; break;
707 case lyx::graphics::GrayscaleDisplay: item = 1; break;
708 case lyx::graphics::MonochromeDisplay: item = 0; break;
711 displayGraphicsCO->setCurrentIndex(item);
715 /////////////////////////////////////////////////////////////////////
719 /////////////////////////////////////////////////////////////////////
721 PrefPaths::PrefPaths(GuiPreferences * form, QWidget * parent)
722 : PrefModule(_("Paths"), form, parent)
725 connect(templateDirPB, SIGNAL(clicked()), this, SLOT(select_templatedir()));
726 connect(tempDirPB, SIGNAL(clicked()), this, SLOT(select_tempdir()));
727 connect(backupDirPB, SIGNAL(clicked()), this, SLOT(select_backupdir()));
728 connect(workingDirPB, SIGNAL(clicked()), this, SLOT(select_workingdir()));
729 connect(lyxserverDirPB, SIGNAL(clicked()), this, SLOT(select_lyxpipe()));
730 connect(workingDirED, SIGNAL(textChanged(const QString&)),
731 this, SIGNAL(changed()));
732 connect(templateDirED, SIGNAL(textChanged(const QString&)),
733 this, SIGNAL(changed()));
734 connect(backupDirED, SIGNAL(textChanged(const QString&)),
735 this, SIGNAL(changed()));
736 connect(tempDirED, SIGNAL(textChanged(const QString&)),
737 this, SIGNAL(changed()));
738 connect(lyxserverDirED, SIGNAL(textChanged(const QString&)),
739 this, SIGNAL(changed()));
740 connect(pathPrefixED, SIGNAL(textChanged(const QString&)),
741 this, SIGNAL(changed()));
745 void PrefPaths::apply(LyXRC & rc) const
747 rc.document_path = internal_path(fromqstr(workingDirED->text()));
748 rc.template_path = internal_path(fromqstr(templateDirED->text()));
749 rc.backupdir_path = internal_path(fromqstr(backupDirED->text()));
750 rc.tempdir_path = internal_path(fromqstr(tempDirED->text()));
751 rc.path_prefix = internal_path_list(fromqstr(pathPrefixED->text()));
752 // FIXME: should be a checkbox only
753 rc.lyxpipes = internal_path(fromqstr(lyxserverDirED->text()));
757 void PrefPaths::update(LyXRC const & rc)
759 workingDirED->setText(toqstr(external_path(rc.document_path)));
760 templateDirED->setText(toqstr(external_path(rc.template_path)));
761 backupDirED->setText(toqstr(external_path(rc.backupdir_path)));
762 tempDirED->setText(toqstr(external_path(rc.tempdir_path)));
763 pathPrefixED->setText(toqstr(external_path_list(rc.path_prefix)));
764 // FIXME: should be a checkbox only
765 lyxserverDirED->setText(toqstr(external_path(rc.lyxpipes)));
769 void PrefPaths::select_templatedir()
771 docstring file(form_->browsedir(
772 from_utf8(internal_path(fromqstr(templateDirED->text()))),
773 _("Select a document templates directory")));
775 templateDirED->setText(toqstr(file));
779 void PrefPaths::select_tempdir()
781 docstring file(form_->browsedir(
782 from_utf8(internal_path(fromqstr(tempDirED->text()))),
783 _("Select a temporary directory")));
785 tempDirED->setText(toqstr(file));
789 void PrefPaths::select_backupdir()
791 docstring file(form_->browsedir(
792 from_utf8(internal_path(fromqstr(backupDirED->text()))),
793 _("Select a backups directory")));
795 backupDirED->setText(toqstr(file));
799 void PrefPaths::select_workingdir()
801 docstring file(form_->browsedir(
802 from_utf8(internal_path(fromqstr(workingDirED->text()))),
803 _("Select a document directory")));
805 workingDirED->setText(toqstr(file));
809 void PrefPaths::select_lyxpipe()
811 docstring file(form_->browse(
812 from_utf8(internal_path(fromqstr(lyxserverDirED->text()))),
813 _("Give a filename for the LyX server pipe")));
815 lyxserverDirED->setText(toqstr(file));
819 /////////////////////////////////////////////////////////////////////
823 /////////////////////////////////////////////////////////////////////
825 PrefSpellchecker::PrefSpellchecker(GuiPreferences * form, QWidget * parent)
826 : PrefModule(_("Spellchecker"), form, parent)
830 connect(persDictionaryPB, SIGNAL(clicked()), this, SLOT(select_dict()));
831 #if defined (USE_ISPELL)
832 connect(spellCommandCO, SIGNAL(activated(int)),
833 this, SIGNAL(changed()));
835 spellCommandCO->setEnabled(false);
837 connect(altLanguageED, SIGNAL(textChanged(const QString&)),
838 this, SIGNAL(changed()));
839 connect(escapeCharactersED, SIGNAL(textChanged(const QString&)),
840 this, SIGNAL(changed()));
841 connect(persDictionaryED, SIGNAL(textChanged(const QString&)),
842 this, SIGNAL(changed()));
843 connect(compoundWordCB, SIGNAL(clicked()),
844 this, SIGNAL(changed()));
845 connect(inputEncodingCB, SIGNAL(clicked()),
846 this, SIGNAL(changed()));
848 spellCommandCO->addItem(qt_("ispell"));
849 spellCommandCO->addItem(qt_("aspell"));
850 spellCommandCO->addItem(qt_("hspell"));
852 spellCommandCO->addItem(qt_("pspell (library)"));
855 spellCommandCO->addItem(qt_("aspell (library)"));
861 void PrefSpellchecker::apply(LyXRC & rc) const
863 switch (spellCommandCO->currentIndex()) {
867 rc.use_spell_lib = false;
868 rc.isp_command = fromqstr(spellCommandCO->currentText());
871 rc.use_spell_lib = true;
875 // FIXME: remove isp_use_alt_lang
876 rc.isp_alt_lang = fromqstr(altLanguageED->text());
877 rc.isp_use_alt_lang = !rc.isp_alt_lang.empty();
878 // FIXME: remove isp_use_esc_chars
879 rc.isp_esc_chars = fromqstr(escapeCharactersED->text());
880 rc.isp_use_esc_chars = !rc.isp_esc_chars.empty();
881 // FIXME: remove isp_use_pers_dict
882 rc.isp_pers_dict = internal_path(fromqstr(persDictionaryED->text()));
883 rc.isp_use_pers_dict = !rc.isp_pers_dict.empty();
884 rc.isp_accept_compound = compoundWordCB->isChecked();
885 rc.isp_use_input_encoding = inputEncodingCB->isChecked();
889 void PrefSpellchecker::update(LyXRC const & rc)
891 spellCommandCO->setCurrentIndex(0);
893 if (rc.isp_command == "ispell") {
894 spellCommandCO->setCurrentIndex(0);
895 } else if (rc.isp_command == "aspell") {
896 spellCommandCO->setCurrentIndex(1);
897 } else if (rc.isp_command == "hspell") {
898 spellCommandCO->setCurrentIndex(2);
901 if (rc.use_spell_lib) {
902 #if defined(USE_ASPELL) || defined(USE_PSPELL)
903 spellCommandCO->setCurrentIndex(3);
907 // FIXME: remove isp_use_alt_lang
908 altLanguageED->setText(toqstr(rc.isp_alt_lang));
909 // FIXME: remove isp_use_esc_chars
910 escapeCharactersED->setText(toqstr(rc.isp_esc_chars));
911 // FIXME: remove isp_use_pers_dict
912 persDictionaryED->setText(toqstr(external_path(rc.isp_pers_dict)));
913 compoundWordCB->setChecked(rc.isp_accept_compound);
914 inputEncodingCB->setChecked(rc.isp_use_input_encoding);
918 void PrefSpellchecker::select_dict()
920 docstring file(form_->browsedict(
921 from_utf8(internal_path(fromqstr(persDictionaryED->text())))));
923 persDictionaryED->setText(toqstr(file));
928 /////////////////////////////////////////////////////////////////////
932 /////////////////////////////////////////////////////////////////////
935 PrefConverters::PrefConverters(GuiPreferences * form, QWidget * parent)
936 : PrefModule(_("Converters"), form, parent)
940 connect(converterNewPB, SIGNAL(clicked()),
941 this, SLOT(update_converter()));
942 connect(converterRemovePB, SIGNAL(clicked()),
943 this, SLOT(remove_converter()));
944 connect(converterModifyPB, SIGNAL(clicked()),
945 this, SLOT(update_converter()));
946 connect(convertersLW, SIGNAL(currentRowChanged(int)),
947 this, SLOT(switch_converter()));
948 connect(converterFromCO, SIGNAL(activated(const QString&)),
949 this, SLOT(converter_changed()));
950 connect(converterToCO, SIGNAL(activated(const QString&)),
951 this, SLOT(converter_changed()));
952 connect(converterED, SIGNAL(textEdited(const QString&)),
953 this, SLOT(converter_changed()));
954 connect(converterFlagED, SIGNAL(textEdited(const QString&)),
955 this, SLOT(converter_changed()));
956 connect(converterNewPB, SIGNAL(clicked()),
957 this, SIGNAL(changed()));
958 connect(converterRemovePB, SIGNAL(clicked()),
959 this, SIGNAL(changed()));
960 connect(converterModifyPB, SIGNAL(clicked()),
961 this, SIGNAL(changed()));
962 connect(maxAgeLE, SIGNAL(textEdited(const QString&)),
963 this, SIGNAL(changed()));
965 maxAgeLE->setValidator(new QDoubleValidator(maxAgeLE));
966 //converterDefGB->setFocusProxy(convertersLW);
970 void PrefConverters::apply(LyXRC & rc) const
972 rc.use_converter_cache = cacheCB->isChecked();
973 rc.converter_cache_maxage = int(maxAgeLE->text().toDouble() * 86400.0);
977 void PrefConverters::update(LyXRC const & rc)
979 cacheCB->setChecked(rc.use_converter_cache);
981 max_age.setNum(double(rc.converter_cache_maxage) / 86400.0, 'g', 6);
982 maxAgeLE->setText(max_age);
987 void PrefConverters::updateGui()
989 form_->formats().sort();
990 form_->converters().update(form_->formats());
991 // save current selection
992 QString current = converterFromCO->currentText()
993 + " -> " + converterToCO->currentText();
995 converterFromCO->clear();
996 converterToCO->clear();
998 Formats::const_iterator cit = form_->formats().begin();
999 Formats::const_iterator end = form_->formats().end();
1000 for (; cit != end; ++cit) {
1001 converterFromCO->addItem(toqstr(cit->prettyname()));
1002 converterToCO->addItem(toqstr(cit->prettyname()));
1005 // currentRowChanged(int) is also triggered when updating the listwidget
1006 // block signals to avoid unnecessary calls to switch_converter()
1007 convertersLW->blockSignals(true);
1008 convertersLW->clear();
1010 Converters::const_iterator ccit = form_->converters().begin();
1011 Converters::const_iterator cend = form_->converters().end();
1012 for (; ccit != cend; ++ccit) {
1013 std::string const name =
1014 ccit->From->prettyname() + " -> " + ccit->To->prettyname();
1015 int type = form_->converters().getNumber(ccit->From->name(), ccit->To->name());
1016 new QListWidgetItem(toqstr(name), convertersLW, type);
1018 convertersLW->sortItems(Qt::AscendingOrder);
1019 convertersLW->blockSignals(false);
1021 // restore selection
1022 if (!current.isEmpty()) {
1023 QList<QListWidgetItem *> const item =
1024 convertersLW->findItems(current, Qt::MatchExactly);
1025 if (!item.isEmpty())
1026 convertersLW->setCurrentItem(item.at(0));
1029 // select first element if restoring failed
1030 if (convertersLW->currentRow() == -1)
1031 convertersLW->setCurrentRow(0);
1037 void PrefConverters::switch_converter()
1039 int const cnr = convertersLW->currentItem()->type();
1040 Converter const & c(form_->converters().get(cnr));
1041 converterFromCO->setCurrentIndex(form_->formats().getNumber(c.from));
1042 converterToCO->setCurrentIndex(form_->formats().getNumber(c.to));
1043 converterED->setText(toqstr(c.command));
1044 converterFlagED->setText(toqstr(c.flags));
1050 void PrefConverters::converter_changed()
1056 void PrefConverters::updateButtons()
1058 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1059 Format const & to = form_->formats().get(converterToCO->currentIndex());
1060 int const sel = form_->converters().getNumber(from.name(), to.name());
1061 bool const known = !(sel < 0);
1062 bool const valid = !(converterED->text().isEmpty()
1063 || from.name() == to.name());
1065 int const cnr = convertersLW->currentItem()->type();
1066 Converter const & c(form_->converters().get(cnr));
1067 string const old_command = c.command;
1068 string const old_flag = c.flags;
1069 string const new_command(fromqstr(converterED->text()));
1070 string const new_flag(fromqstr(converterFlagED->text()));
1072 bool modified = ((old_command != new_command) || (old_flag != new_flag));
1074 converterModifyPB->setEnabled(valid && known && modified);
1075 converterNewPB->setEnabled(valid && !known);
1076 converterRemovePB->setEnabled(known);
1078 maxAgeLE->setEnabled(cacheCB->isChecked());
1079 maxAgeLA->setEnabled(cacheCB->isChecked());
1084 // specify unique from/to or it doesn't appear. This is really bad UI
1085 // this is why we can use the same function for both new and modify
1086 void PrefConverters::update_converter()
1088 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1089 Format const & to = form_->formats().get(converterToCO->currentIndex());
1090 string const flags = fromqstr(converterFlagED->text());
1091 string const command = fromqstr(converterED->text());
1093 Converter const * old =
1094 form_->converters().getConverter(from.name(), to.name());
1095 form_->converters().add(from.name(), to.name(), command, flags);
1098 form_->converters().updateLast(form_->formats());
1102 // Remove all files created by this converter from the cache, since
1103 // the modified converter might create different files.
1104 ConverterCache::get().remove_all(from.name(), to.name());
1108 void PrefConverters::remove_converter()
1110 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1111 Format const & to = form_->formats().get(converterToCO->currentIndex());
1112 form_->converters().erase(from.name(), to.name());
1116 // Remove all files created by this converter from the cache, since
1117 // a possible new converter might create different files.
1118 ConverterCache::get().remove_all(from.name(), to.name());
1122 void PrefConverters::on_cacheCB_stateChanged(int state)
1124 maxAgeLE->setEnabled(state == Qt::Checked);
1125 maxAgeLA->setEnabled(state == Qt::Checked);
1130 /////////////////////////////////////////////////////////////////////
1134 /////////////////////////////////////////////////////////////////////
1135 FormatValidator::FormatValidator(QWidget * parent, Formats const & f)
1136 : QValidator(parent), formats_(f)
1141 void FormatValidator::fixup(QString & input) const
1143 Formats::const_iterator cit = formats_.begin();
1144 Formats::const_iterator end = formats_.end();
1145 for (; cit != end; ++cit) {
1146 string const name = str(cit);
1147 if (distance(formats_.begin(), cit) == nr()) {
1148 input = toqstr(name);
1156 QValidator::State FormatValidator::validate(QString & input, int & /*pos*/) const
1158 Formats::const_iterator cit = formats_.begin();
1159 Formats::const_iterator end = formats_.end();
1160 bool unknown = true;
1161 for (; unknown && cit != end; ++cit) {
1162 string const name = str(cit);
1163 if (distance(formats_.begin(), cit) != nr())
1164 unknown = toqstr(name) != input;
1167 if (unknown && !input.isEmpty())
1168 return QValidator::Acceptable;
1170 return QValidator::Intermediate;
1174 int FormatValidator::nr() const
1176 QComboBox * p = qobject_cast<QComboBox *>(parent());
1177 return p->itemData(p->currentIndex()).toInt();
1181 FormatNameValidator::FormatNameValidator(QWidget * parent, Formats const & f)
1182 : FormatValidator(parent, f)
1186 std::string FormatNameValidator::str(Formats::const_iterator it) const
1192 FormatPrettynameValidator::FormatPrettynameValidator(QWidget * parent, Formats const & f)
1193 : FormatValidator(parent, f)
1198 std::string FormatPrettynameValidator::str(Formats::const_iterator it) const
1200 return it->prettyname();
1204 PrefFileformats::PrefFileformats(GuiPreferences * form, QWidget * parent)
1205 : PrefModule(_("File formats"), form, parent)
1208 formatED->setValidator(new FormatNameValidator(formatsCB, form_->formats()));
1209 formatsCB->setValidator(new FormatPrettynameValidator(formatsCB, form_->formats()));
1211 connect(documentCB, SIGNAL(clicked()),
1212 this, SLOT(setFlags()));
1213 connect(vectorCB, SIGNAL(clicked()),
1214 this, SLOT(setFlags()));
1215 connect(formatsCB->lineEdit(), SIGNAL(editingFinished()),
1216 this, SLOT(updatePrettyname()));
1217 connect(formatsCB->lineEdit(), SIGNAL(textEdited(const QString &)),
1218 this, SIGNAL(changed()));
1222 void PrefFileformats::apply(LyXRC & /*rc*/) const
1227 void PrefFileformats::update(LyXRC const & /*rc*/)
1233 void PrefFileformats::updateView()
1235 QString const current = formatsCB->currentText();
1237 // update combobox with formats
1238 formatsCB->blockSignals(true);
1240 form_->formats().sort();
1241 Formats::const_iterator cit = form_->formats().begin();
1242 Formats::const_iterator end = form_->formats().end();
1243 for (; cit != end; ++cit)
1244 formatsCB->addItem(toqstr(cit->prettyname()),
1245 QVariant(form_->formats().getNumber(cit->name())) );
1247 // restore selection
1248 int const item = formatsCB->findText(current, Qt::MatchExactly);
1249 formatsCB->setCurrentIndex(item < 0 ? 0 : item);
1250 on_formatsCB_currentIndexChanged(item < 0 ? 0 : item);
1251 formatsCB->blockSignals(false);
1255 void PrefFileformats::on_formatsCB_currentIndexChanged(int i)
1257 int const nr = formatsCB->itemData(i).toInt();
1258 Format const f = form_->formats().get(nr);
1260 formatED->setText(toqstr(f.name()));
1261 copierED->setText(toqstr(form_->movers().command(f.name())));
1262 extensionED->setText(toqstr(f.extension()));
1263 shortcutED->setText(toqstr(f.shortcut()));
1264 viewerED->setText(toqstr(f.viewer()));
1265 editorED->setText(toqstr(f.editor()));
1266 documentCB->setChecked((f.documentFormat()));
1267 vectorCB->setChecked((f.vectorFormat()));
1271 void PrefFileformats::setFlags()
1273 int flags = Format::none;
1274 if (documentCB->isChecked())
1275 flags |= Format::document;
1276 if (vectorCB->isChecked())
1277 flags |= Format::vector;
1278 currentFormat().setFlags(flags);
1283 void PrefFileformats::on_copierED_textEdited(const QString & s)
1285 string const fmt = fromqstr(formatED->text());
1286 form_->movers().set(fmt, fromqstr(s));
1291 void PrefFileformats::on_extensionED_textEdited(const QString & s)
1293 currentFormat().setExtension(fromqstr(s));
1297 void PrefFileformats::on_viewerED_textEdited(const QString & s)
1299 currentFormat().setViewer(fromqstr(s));
1304 void PrefFileformats::on_editorED_textEdited(const QString & s)
1306 currentFormat().setEditor(fromqstr(s));
1311 void PrefFileformats::on_shortcutED_textEdited(const QString & s)
1313 currentFormat().setShortcut(fromqstr(s));
1318 void PrefFileformats::on_formatED_editingFinished()
1320 string const newname = fromqstr(formatED->displayText());
1321 if (newname == currentFormat().name())
1324 currentFormat().setName(newname);
1329 void PrefFileformats::on_formatED_textChanged(const QString &)
1331 QString t = formatED->text();
1333 bool valid = formatED->validator()->validate(t, p) == QValidator::Acceptable;
1334 setValid(formatLA, valid);
1338 void PrefFileformats::on_formatsCB_editTextChanged(const QString &)
1340 QString t = formatsCB->currentText();
1342 bool valid = formatsCB->validator()->validate(t, p) == QValidator::Acceptable;
1343 setValid(formatsLA, valid);
1347 void PrefFileformats::updatePrettyname()
1349 string const newname = fromqstr(formatsCB->currentText());
1350 if (newname == currentFormat().prettyname())
1353 currentFormat().setPrettyname(newname);
1360 Format & PrefFileformats::currentFormat()
1362 int const i = formatsCB->currentIndex();
1363 int const nr = formatsCB->itemData(i).toInt();
1364 return form_->formats().get(nr);
1368 void PrefFileformats::on_formatNewPB_clicked()
1370 form_->formats().add("", "", "", "", "", "", Format::none);
1372 formatsCB->setCurrentIndex(0);
1373 formatsCB->setFocus(Qt::OtherFocusReason);
1377 void PrefFileformats::on_formatRemovePB_clicked()
1379 int const i = formatsCB->currentIndex();
1380 int const nr = formatsCB->itemData(i).toInt();
1381 string const current_text = form_->formats().get(nr).name();
1382 if (form_->converters().formatIsUsed(current_text)) {
1383 Alert::error(_("Format in use"),
1384 _("Cannot remove a Format used by a Converter. "
1385 "Remove the converter first."));
1389 form_->formats().erase(current_text);
1392 on_formatsCB_editTextChanged(formatsCB->currentText());
1397 /////////////////////////////////////////////////////////////////////
1401 /////////////////////////////////////////////////////////////////////
1403 PrefLanguage::PrefLanguage(QWidget * parent)
1404 : PrefModule(_("Language"), 0, parent)
1408 connect(rtlCB, SIGNAL(clicked()),
1409 this, SIGNAL(changed()));
1410 connect(markForeignCB, SIGNAL(clicked()),
1411 this, SIGNAL(changed()));
1412 connect(autoBeginCB, SIGNAL(clicked()),
1413 this, SIGNAL(changed()));
1414 connect(autoEndCB, SIGNAL(clicked()),
1415 this, SIGNAL(changed()));
1416 connect(useBabelCB, SIGNAL(clicked()),
1417 this, SIGNAL(changed()));
1418 connect(globalCB, SIGNAL(clicked()),
1419 this, SIGNAL(changed()));
1420 connect(languagePackageED, SIGNAL(textChanged(const QString&)),
1421 this, SIGNAL(changed()));
1422 connect(startCommandED, SIGNAL(textChanged(const QString&)),
1423 this, SIGNAL(changed()));
1424 connect(endCommandED, SIGNAL(textChanged(const QString&)),
1425 this, SIGNAL(changed()));
1426 connect(defaultLanguageCO, SIGNAL(activated(int)),
1427 this, SIGNAL(changed()));
1429 defaultLanguageCO->clear();
1431 // store the lang identifiers for later
1432 std::vector<LanguagePair> const langs = frontend::getLanguageData(false);
1433 std::vector<LanguagePair>::const_iterator lit = langs.begin();
1434 std::vector<LanguagePair>::const_iterator lend = langs.end();
1436 for (; lit != lend; ++lit) {
1437 defaultLanguageCO->addItem(toqstr(lit->first));
1438 lang_.push_back(lit->second);
1443 void PrefLanguage::apply(LyXRC & rc) const
1445 // FIXME: remove rtl_support bool
1446 rc.rtl_support = rtlCB->isChecked();
1447 rc.mark_foreign_language = markForeignCB->isChecked();
1448 rc.language_auto_begin = autoBeginCB->isChecked();
1449 rc.language_auto_end = autoEndCB->isChecked();
1450 rc.language_use_babel = useBabelCB->isChecked();
1451 rc.language_global_options = globalCB->isChecked();
1452 rc.language_package = fromqstr(languagePackageED->text());
1453 rc.language_command_begin = fromqstr(startCommandED->text());
1454 rc.language_command_end = fromqstr(endCommandED->text());
1455 rc.default_language = lang_[defaultLanguageCO->currentIndex()];
1459 void PrefLanguage::update(LyXRC const & rc)
1461 // FIXME: remove rtl_support bool
1462 rtlCB->setChecked(rc.rtl_support);
1463 markForeignCB->setChecked(rc.mark_foreign_language);
1464 autoBeginCB->setChecked(rc.language_auto_begin);
1465 autoEndCB->setChecked(rc.language_auto_end);
1466 useBabelCB->setChecked(rc.language_use_babel);
1467 globalCB->setChecked(rc.language_global_options);
1468 languagePackageED->setText(toqstr(rc.language_package));
1469 startCommandED->setText(toqstr(rc.language_command_begin));
1470 endCommandED->setText(toqstr(rc.language_command_end));
1472 int const pos = int(findPos_helper(lang_, rc.default_language));
1473 defaultLanguageCO->setCurrentIndex(pos);
1477 /////////////////////////////////////////////////////////////////////
1481 /////////////////////////////////////////////////////////////////////
1483 PrefPrinter::PrefPrinter(QWidget * parent)
1484 : PrefModule(_("Printer"), 0, parent)
1488 connect(printerAdaptCB, SIGNAL(clicked()),
1489 this, SIGNAL(changed()));
1490 connect(printerCommandED, SIGNAL(textChanged(const QString&)),
1491 this, SIGNAL(changed()));
1492 connect(printerNameED, SIGNAL(textChanged(const QString&)),
1493 this, SIGNAL(changed()));
1494 connect(printerPageRangeED, SIGNAL(textChanged(const QString&)),
1495 this, SIGNAL(changed()));
1496 connect(printerCopiesED, SIGNAL(textChanged(const QString&)),
1497 this, SIGNAL(changed()));
1498 connect(printerReverseED, SIGNAL(textChanged(const QString&)),
1499 this, SIGNAL(changed()));
1500 connect(printerToPrinterED, SIGNAL(textChanged(const QString&)),
1501 this, SIGNAL(changed()));
1502 connect(printerExtensionED, SIGNAL(textChanged(const QString&)),
1503 this, SIGNAL(changed()));
1504 connect(printerSpoolCommandED, SIGNAL(textChanged(const QString&)),
1505 this, SIGNAL(changed()));
1506 connect(printerPaperTypeED, SIGNAL(textChanged(const QString&)),
1507 this, SIGNAL(changed()));
1508 connect(printerEvenED, SIGNAL(textChanged(const QString&)),
1509 this, SIGNAL(changed()));
1510 connect(printerOddED, SIGNAL(textChanged(const QString&)),
1511 this, SIGNAL(changed()));
1512 connect(printerCollatedED, SIGNAL(textChanged(const QString&)),
1513 this, SIGNAL(changed()));
1514 connect(printerLandscapeED, SIGNAL(textChanged(const QString&)),
1515 this, SIGNAL(changed()));
1516 connect(printerToFileED, SIGNAL(textChanged(const QString&)),
1517 this, SIGNAL(changed()));
1518 connect(printerExtraED, SIGNAL(textChanged(const QString&)),
1519 this, SIGNAL(changed()));
1520 connect(printerSpoolPrefixED, SIGNAL(textChanged(const QString&)),
1521 this, SIGNAL(changed()));
1522 connect(printerPaperSizeED, SIGNAL(textChanged(const QString&)),
1523 this, SIGNAL(changed()));
1527 void PrefPrinter::apply(LyXRC & rc) const
1529 rc.print_adapt_output = printerAdaptCB->isChecked();
1530 rc.print_command = fromqstr(printerCommandED->text());
1531 rc.printer = fromqstr(printerNameED->text());
1533 rc.print_pagerange_flag = fromqstr(printerPageRangeED->text());
1534 rc.print_copies_flag = fromqstr(printerCopiesED->text());
1535 rc.print_reverse_flag = fromqstr(printerReverseED->text());
1536 rc.print_to_printer = fromqstr(printerToPrinterED->text());
1537 rc.print_file_extension = fromqstr(printerExtensionED->text());
1538 rc.print_spool_command = fromqstr(printerSpoolCommandED->text());
1539 rc.print_paper_flag = fromqstr(printerPaperTypeED->text());
1540 rc.print_evenpage_flag = fromqstr(printerEvenED->text());
1541 rc.print_oddpage_flag = fromqstr(printerOddED->text());
1542 rc.print_collcopies_flag = fromqstr(printerCollatedED->text());
1543 rc.print_landscape_flag = fromqstr(printerLandscapeED->text());
1544 rc.print_to_file = internal_path(fromqstr(printerToFileED->text()));
1545 rc.print_extra_options = fromqstr(printerExtraED->text());
1546 rc.print_spool_printerprefix = fromqstr(printerSpoolPrefixED->text());
1547 rc.print_paper_dimension_flag = fromqstr(printerPaperSizeED->text());
1551 void PrefPrinter::update(LyXRC const & rc)
1553 printerAdaptCB->setChecked(rc.print_adapt_output);
1554 printerCommandED->setText(toqstr(rc.print_command));
1555 printerNameED->setText(toqstr(rc.printer));
1557 printerPageRangeED->setText(toqstr(rc.print_pagerange_flag));
1558 printerCopiesED->setText(toqstr(rc.print_copies_flag));
1559 printerReverseED->setText(toqstr(rc.print_reverse_flag));
1560 printerToPrinterED->setText(toqstr(rc.print_to_printer));
1561 printerExtensionED->setText(toqstr(rc.print_file_extension));
1562 printerSpoolCommandED->setText(toqstr(rc.print_spool_command));
1563 printerPaperTypeED->setText(toqstr(rc.print_paper_flag));
1564 printerEvenED->setText(toqstr(rc.print_evenpage_flag));
1565 printerOddED->setText(toqstr(rc.print_oddpage_flag));
1566 printerCollatedED->setText(toqstr(rc.print_collcopies_flag));
1567 printerLandscapeED->setText(toqstr(rc.print_landscape_flag));
1568 printerToFileED->setText(toqstr(external_path(rc.print_to_file)));
1569 printerExtraED->setText(toqstr(rc.print_extra_options));
1570 printerSpoolPrefixED->setText(toqstr(rc.print_spool_printerprefix));
1571 printerPaperSizeED->setText(toqstr(rc.print_paper_dimension_flag));
1575 /////////////////////////////////////////////////////////////////////
1577 // PrefUserInterface
1579 /////////////////////////////////////////////////////////////////////
1581 PrefUserInterface::PrefUserInterface(GuiPreferences * form, QWidget * parent)
1582 : PrefModule(_("User interface"), form, parent)
1586 connect(autoSaveCB, SIGNAL(toggled(bool)),
1587 autoSaveSB, SLOT(setEnabled(bool)));
1588 connect(autoSaveCB, SIGNAL(toggled(bool)),
1589 TextLabel1, SLOT(setEnabled(bool)));
1590 connect(uiFilePB, SIGNAL(clicked()),
1591 this, SLOT(select_ui()));
1592 connect(uiFileED, SIGNAL(textChanged(const QString &)),
1593 this, SIGNAL(changed()));
1594 connect(restoreCursorCB, SIGNAL(clicked()),
1595 this, SIGNAL(changed()));
1596 connect(loadSessionCB, SIGNAL(clicked()),
1597 this, SIGNAL(changed()));
1598 connect(loadWindowSizeCB, SIGNAL(clicked()),
1599 this, SIGNAL(changed()));
1600 connect(loadWindowLocationCB, SIGNAL(clicked()),
1601 this, SIGNAL(changed()));
1602 connect(windowWidthSB, SIGNAL(valueChanged(int)),
1603 this, SIGNAL(changed()));
1604 connect(windowHeightSB, SIGNAL(valueChanged(int)),
1605 this, SIGNAL(changed()));
1606 connect(cursorFollowsCB, SIGNAL(clicked()),
1607 this, SIGNAL(changed()));
1608 connect(autoSaveSB, SIGNAL(valueChanged(int)),
1609 this, SIGNAL(changed()));
1610 connect(autoSaveCB, SIGNAL(clicked()),
1611 this, SIGNAL(changed()));
1612 connect(lastfilesSB, SIGNAL(valueChanged(int)),
1613 this, SIGNAL(changed()));
1614 lastfilesSB->setMaximum(maxlastfiles);
1618 void PrefUserInterface::apply(LyXRC & rc) const
1620 rc.ui_file = internal_path(fromqstr(uiFileED->text()));
1621 rc.use_lastfilepos = restoreCursorCB->isChecked();
1622 rc.load_session = loadSessionCB->isChecked();
1623 if (loadWindowSizeCB->isChecked()) {
1624 rc.geometry_width = 0;
1625 rc.geometry_height = 0;
1627 rc.geometry_width = windowWidthSB->value();
1628 rc.geometry_height = windowHeightSB->value();
1630 rc.geometry_xysaved = loadWindowLocationCB->isChecked();
1631 rc.cursor_follows_scrollbar = cursorFollowsCB->isChecked();
1632 rc.autosave = autoSaveSB->value() * 60;
1633 rc.make_backup = autoSaveCB->isChecked();
1634 rc.num_lastfiles = lastfilesSB->value();
1638 void PrefUserInterface::update(LyXRC const & rc)
1640 uiFileED->setText(toqstr(external_path(rc.ui_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);
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)
1655 autoSaveSB->setValue(mins);
1656 autoSaveCB->setChecked(rc.make_backup);
1657 lastfilesSB->setValue(rc.num_lastfiles);
1661 void PrefUserInterface::select_ui()
1663 docstring const name =
1664 from_utf8(internal_path(fromqstr(uiFileED->text())));
1665 docstring file = form_->browseUI(name);
1667 uiFileED->setText(toqstr(file));
1671 void PrefUserInterface::on_loadWindowSizeCB_toggled(bool loadwindowsize)
1673 windowWidthLA->setDisabled(loadwindowsize);
1674 windowHeightLA->setDisabled(loadwindowsize);
1675 windowWidthSB->setDisabled(loadwindowsize);
1676 windowHeightSB->setDisabled(loadwindowsize);
1680 /////////////////////////////////////////////////////////////////////
1684 /////////////////////////////////////////////////////////////////////
1686 PrefShortcuts::PrefShortcuts(GuiPreferences * form, QWidget * parent)
1687 : PrefModule(_("Shortcuts"), form, parent)
1691 shortcutsTW->setColumnCount(2);
1692 shortcutsTW->headerItem()->setText(0, qt_("Function"));
1693 shortcutsTW->headerItem()->setText(1, qt_("Shortcut"));
1694 shortcutsTW->setSortingEnabled(true);
1695 // Multi-selection can be annoying.
1696 // shortcutsTW->setSelectionMode(QAbstractItemView::MultiSelection);
1697 shortcutsTW->header()->resizeSection(0, 200);
1699 connect(bindFilePB, SIGNAL(clicked()),
1700 this, SLOT(select_bind()));
1701 connect(bindFileED, SIGNAL(textChanged(const QString &)),
1702 this, SIGNAL(changed()));
1704 shortcut_ = new GuiShortcutDialog(this);
1705 shortcut_bc_.setPolicy(ButtonPolicy::OkCancelPolicy);
1706 shortcut_bc_.setOK(shortcut_->okPB);
1707 shortcut_bc_.setCancel(shortcut_->cancelPB);
1709 connect(shortcut_->okPB, SIGNAL(clicked()),
1710 shortcut_, SLOT(accept()));
1711 connect(shortcut_->cancelPB, SIGNAL(clicked()),
1712 shortcut_, SLOT(reject()));
1713 connect(shortcut_->okPB, SIGNAL(clicked()),
1714 shortcut_, SLOT(setShortcut()));
1718 void PrefShortcuts::apply(LyXRC & rc) const
1720 rc.bind_file = internal_path(fromqstr(bindFileED->text()));
1724 void PrefShortcuts::update(LyXRC const & rc)
1726 bindFileED->setText(toqstr(external_path(rc.bind_file)));
1727 shortcutsTW->clear();
1729 QTreeWidgetItem * editItem = new QTreeWidgetItem(shortcutsTW);
1730 editItem->setText(0, toqstr("Cursor, Mouse and Editing functions"));
1731 editItem->setFlags(editItem->flags() & ~Qt::ItemIsSelectable);
1733 // first insert a few categories
1734 QTreeWidgetItem * mathItem = new QTreeWidgetItem(shortcutsTW);
1735 mathItem->setText(0, toqstr("Mathematical Symbols"));
1736 mathItem->setFlags(mathItem->flags() & ~Qt::ItemIsSelectable);
1738 QTreeWidgetItem * bufferItem = new QTreeWidgetItem(shortcutsTW);
1739 bufferItem->setText(0, toqstr("Buffer and Window"));
1740 bufferItem->setFlags(bufferItem->flags() & ~Qt::ItemIsSelectable);
1742 QTreeWidgetItem * layoutItem = new QTreeWidgetItem(shortcutsTW);
1743 layoutItem->setText(0, toqstr("Font, Layouts and Textclasses"));
1744 layoutItem->setFlags(layoutItem->flags() & ~Qt::ItemIsSelectable);
1746 QTreeWidgetItem * systemItem = new QTreeWidgetItem(shortcutsTW);
1747 systemItem->setText(0, toqstr("System and Miscellaneous"));
1748 systemItem->setFlags(systemItem->flags() & ~Qt::ItemIsSelectable);
1750 // listBindings(unbound=true) lists all bound and unbound lfuns
1751 KeyMap::BindingList const bindinglist = theTopLevelKeymap().listBindings(true);
1753 KeyMap::BindingList::const_iterator it = bindinglist.begin();
1754 KeyMap::BindingList::const_iterator it_end = bindinglist.end();
1755 for (; it != it_end; ++it) {
1756 kb_action action = it->first.action;
1757 string const action_name = lyxaction.getActionName(action);
1758 QString const lfun = toqstr(from_utf8(action_name)
1759 + " " + it->first.argument());
1760 QString const shortcut = toqstr(it->second.print(KeySequence::Portable));
1762 QTreeWidgetItem * newItem = NULL;
1763 // if an item with the same lfun already exists, insert as a
1764 // child item to that item.
1765 // WARNING: this can be slow.
1766 QList<QTreeWidgetItem*> const items = shortcutsTW->findItems(lfun,
1767 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 0);
1769 newItem = new QTreeWidgetItem(items[0]);
1771 switch(lyxaction.getActionType(action)) {
1772 case LyXAction::Hidden:
1774 case LyXAction::Edit:
1775 newItem = new QTreeWidgetItem(editItem);
1777 case LyXAction::Math:
1778 newItem = new QTreeWidgetItem(mathItem);
1780 case LyXAction::Buffer:
1781 newItem = new QTreeWidgetItem(bufferItem);
1783 case LyXAction::Layout:
1784 newItem = new QTreeWidgetItem(layoutItem);
1786 case LyXAction::System:
1787 newItem = new QTreeWidgetItem(systemItem);
1790 // this should not happen
1791 newItem = new QTreeWidgetItem(shortcutsTW);
1795 newItem->setText(0, lfun);
1796 newItem->setText(1, shortcut);
1798 //newItem->setFlags(newItem->flags() | Qt::ItemIsEditable
1799 // | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable);
1801 shortcutsTW->sortItems(0, Qt::AscendingOrder);
1802 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
1803 modifyPB->setEnabled(!items.isEmpty());
1804 removePB->setEnabled(!items.isEmpty() && !items[0]->text(1).isEmpty());
1805 searchPB->setEnabled(!searchLE->text().isEmpty());
1809 void PrefShortcuts::on_shortcutsTW_itemSelectionChanged()
1811 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
1812 modifyPB->setEnabled(!items.isEmpty());
1813 removePB->setEnabled(!items.isEmpty() && !items[0]->text(1).isEmpty());
1817 void PrefShortcuts::on_shortcutsTW_itemDoubleClicked()
1819 on_modifyPB_pressed();
1823 void PrefShortcuts::select_bind()
1825 docstring const name =
1826 from_utf8(internal_path(fromqstr(bindFileED->text())));
1827 docstring file = form_->browsebind(name);
1829 bindFileED->setText(toqstr(file));
1833 void PrefShortcuts::on_newPB_pressed()
1835 shortcut_->lfunED->clear();
1836 shortcut_->shortcutED->clear();
1837 shortcut_->setWindowTitle(toqstr("Create new shortcut"));
1842 void PrefShortcuts::on_modifyPB_pressed()
1844 QTreeWidgetItem * item = shortcutsTW->currentItem();
1845 shortcut_->lfunED->setText(item->text(0));
1846 shortcut_->shortcutED->setText(item->text(1));
1847 shortcut_->setWindowTitle(toqstr("Modify shortcut"));
1852 void PrefShortcuts::on_removePB_pressed()
1854 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
1855 for (int i = 0; i < items.size(); ++i)
1856 items[i]->setText(1, QString());
1860 void PrefShortcuts::on_searchPB_pressed()
1862 QList<QTreeWidgetItem *> matched = shortcutsTW->findItems(
1864 Qt::MatchFlags(Qt::MatchContains | Qt::MatchRecursive));
1866 // hide everyone (to avoid searching in matched QList repeatedly
1867 QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Selectable);
1869 shortcutsTW->setItemHidden(*it++, true);
1870 // show matched items
1871 for (int i = 0; i < matched.size(); ++i) {
1872 shortcutsTW->setItemHidden(matched[i], false);
1873 shortcutsTW->setItemExpanded(matched[i], true);
1878 void PrefShortcuts::on_searchLE_textChanged()
1880 searchPB->setEnabled(!searchLE->text().isEmpty());
1881 if (searchLE->text().isEmpty()) {
1882 // show all hidden items
1883 QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Hidden);
1885 shortcutsTW->setItemHidden(*it++, false);
1890 void PrefShortcuts::setShortcut()
1895 /////////////////////////////////////////////////////////////////////
1899 /////////////////////////////////////////////////////////////////////
1901 PrefIdentity::PrefIdentity(QWidget * parent)
1902 : PrefModule(_("Identity"), 0, parent)
1906 connect(nameED, SIGNAL(textChanged(const QString&)),
1907 this, SIGNAL(changed()));
1908 connect(emailED, SIGNAL(textChanged(const QString&)),
1909 this, SIGNAL(changed()));
1913 void PrefIdentity::apply(LyXRC & rc) const
1915 rc.user_name = fromqstr(nameED->text());
1916 rc.user_email = fromqstr(emailED->text());
1920 void PrefIdentity::update(LyXRC const & rc)
1922 nameED->setText(toqstr(rc.user_name));
1923 emailED->setText(toqstr(rc.user_email));
1928 /////////////////////////////////////////////////////////////////////
1932 /////////////////////////////////////////////////////////////////////
1934 GuiPreferences::GuiPreferences(LyXView & lv)
1935 : GuiDialog(lv, "prefs"), update_screen_font_(false)
1938 setViewTitle(_("Preferences"));
1940 QDialog::setModal(false);
1942 connect(savePB, SIGNAL(clicked()), this, SLOT(slotOK()));
1943 connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
1944 connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
1945 connect(restorePB, SIGNAL(clicked()), this, SLOT(slotRestore()));
1947 add(new PrefUserInterface(this));
1948 add(new PrefShortcuts(this));
1949 add(new PrefScreenFonts(this));
1950 add(new PrefColors(this));
1951 add(new PrefDisplay);
1952 add(new PrefKeyboard(this));
1954 add(new PrefPaths(this));
1956 add(new PrefIdentity);
1958 add(new PrefLanguage);
1959 add(new PrefSpellchecker(this));
1961 add(new PrefPrinter);
1963 add(new PrefPlaintext);
1964 add(new PrefLatex(this));
1966 PrefConverters * converters = new PrefConverters(this);
1967 PrefFileformats * formats = new PrefFileformats(this);
1968 connect(formats, SIGNAL(formatsChanged()),
1969 converters, SLOT(updateGui()));
1973 prefsPS->setCurrentPanel(_("User interface"));
1974 // FIXME: hack to work around resizing bug in Qt >= 4.2
1975 // bug verified with Qt 4.2.{0-3} (JSpitzm)
1976 #if QT_VERSION >= 0x040200
1977 prefsPS->updateGeometry();
1980 bc().setPolicy(ButtonPolicy::PreferencesPolicy);
1982 bc().setApply(applyPB);
1983 bc().setCancel(closePB);
1984 bc().setRestore(restorePB);
1988 void GuiPreferences::add(PrefModule * module)
1990 BOOST_ASSERT(module);
1991 prefsPS->addPanel(module, module->title());
1992 connect(module, SIGNAL(changed()), this, SLOT(change_adaptor()));
1993 modules_.push_back(module);
1997 void GuiPreferences::closeEvent(QCloseEvent * e)
2004 void GuiPreferences::change_adaptor()
2010 void GuiPreferences::apply(LyXRC & rc) const
2012 size_t end = modules_.size();
2013 for (size_t i = 0; i != end; ++i)
2014 modules_[i]->apply(rc);
2018 void GuiPreferences::updateRc(LyXRC const & rc)
2020 size_t const end = modules_.size();
2021 for (size_t i = 0; i != end; ++i)
2022 modules_[i]->update(rc);
2026 void GuiPreferences::applyView()
2032 void GuiPreferences::updateContents()
2038 bool GuiPreferences::initialiseParams(std::string const &)
2041 formats_ = lyx::formats;
2042 converters_ = theConverters();
2043 converters_.update(formats_);
2044 movers_ = theMovers();
2046 update_screen_font_ = false;
2052 void GuiPreferences::dispatchParams()
2055 rc_.write(ss, true);
2056 dispatch(FuncRequest(LFUN_LYXRC_APPLY, ss.str()));
2057 // FIXME: these need lfuns
2059 theBufferList().setCurrentAuthor(from_utf8(rc_.user_name), from_utf8(rc_.user_email));
2061 lyx::formats = formats_;
2063 theConverters() = converters_;
2064 theConverters().update(lyx::formats);
2065 theConverters().buildGraph();
2067 theMovers() = movers_;
2069 vector<string>::const_iterator it = colors_.begin();
2070 vector<string>::const_iterator const end = colors_.end();
2071 for (; it != end; ++it)
2072 dispatch(FuncRequest(LFUN_SET_COLOR, *it));
2075 if (update_screen_font_) {
2076 dispatch(FuncRequest(LFUN_SCREEN_FONT_UPDATE));
2077 update_screen_font_ = false;
2080 // The Save button has been pressed
2082 dispatch(FuncRequest(LFUN_PREFERENCES_SAVE));
2086 void GuiPreferences::setColor(Color_color col, string const & hex)
2088 colors_.push_back(lcolor.getLyXName(col) + ' ' + hex);
2092 void GuiPreferences::updateScreenFonts()
2094 update_screen_font_ = true;
2098 docstring const GuiPreferences::browsebind(docstring const & file) const
2100 return browseLibFile(from_ascii("bind"), file, from_ascii("bind"),
2101 _("Choose bind file"),
2102 FileFilterList(_("LyX bind files (*.bind)")));
2106 docstring const GuiPreferences::browseUI(docstring const & file) const
2108 return browseLibFile(from_ascii("ui"), file, from_ascii("ui"),
2109 _("Choose UI file"),
2110 FileFilterList(_("LyX UI files (*.ui)")));
2114 docstring const GuiPreferences::browsekbmap(docstring const & file) const
2116 return browseLibFile(from_ascii("kbd"), file, from_ascii("kmap"),
2117 _("Choose keyboard map"),
2118 FileFilterList(_("LyX keyboard maps (*.kmap)")));
2122 docstring const GuiPreferences::browsedict(docstring const & file) const
2124 if (lyxrc.use_spell_lib)
2125 return browseFile(file,
2126 _("Choose personal dictionary"),
2127 FileFilterList(_("*.pws")));
2129 return browseFile(file,
2130 _("Choose personal dictionary"),
2131 FileFilterList(_("*.ispell")));
2135 docstring const GuiPreferences::browse(docstring const & file,
2136 docstring const & title) const
2138 return browseFile(file, title, FileFilterList(), true);
2142 docstring const GuiPreferences::browsedir(docstring const & path,
2143 docstring const & title) const
2145 return browseDir(path, title);
2149 // We support less paper sizes than the document dialog
2150 // Therefore this adjustment is needed.
2151 PAPER_SIZE GuiPreferences::toPaperSize(int i) const
2155 return PAPER_DEFAULT;
2157 return PAPER_USLETTER;
2159 return PAPER_USLEGAL;
2161 return PAPER_USEXECUTIVE;
2171 // should not happen
2172 return PAPER_DEFAULT;
2177 int GuiPreferences::fromPaperSize(PAPER_SIZE papersize) const
2179 switch (papersize) {
2182 case PAPER_USLETTER:
2186 case PAPER_USEXECUTIVE:
2197 // should not happen
2203 Dialog * createGuiPreferences(LyXView & lv) { return new GuiPreferences(lv); }
2206 } // namespace frontend
2209 #include "GuiPrefs_moc.cpp"