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 "LyXAction.h"
29 #include "PanelStack.h"
33 #include "support/lstrings.h"
34 #include "support/os.h"
35 #include "support/FileFilterList.h"
37 #include "frontend_helpers.h"
39 #include "frontends/alert.h"
40 #include "frontends/Application.h"
43 #include <QColorDialog>
44 #include <QFontDatabase>
46 #include <QPixmapCache>
47 #include <QPushButton>
50 #include <QTreeWidget>
51 #include <QTreeWidgetItem>
53 #include <QCloseEvent>
63 using std::ostringstream;
71 using support::compare_ascii_no_case;
72 using support::os::external_path;
73 using support::os::external_path_list;
74 using support::os::internal_path;
75 using support::os::internal_path_list;
76 using support::FileFilterList;
79 /////////////////////////////////////////////////////////////////////
83 /////////////////////////////////////////////////////////////////////
86 static size_t findPos_helper(std::vector<A> const & vec, A const & val)
88 typedef typename std::vector<A>::const_iterator Cit;
90 Cit it = std::find(vec.begin(), vec.end(), val);
93 return std::distance(vec.begin(), it);
97 static std::pair<string, string> parseFontName(string const & name)
99 string::size_type const idx = name.find('[');
100 if (idx == string::npos || idx == 0)
101 return make_pair(name, string());
102 return make_pair(name.substr(0, idx - 1),
103 name.substr(idx + 1, name.size() - idx - 2));
107 static void setComboxFont(QComboBox * cb, string const & family,
108 string const & foundry)
110 QString fontname = toqstr(family);
111 if (!foundry.empty())
112 fontname += " [" + toqstr(foundry) + ']';
114 for (int i = 0; i < cb->count(); ++i) {
115 if (cb->itemText(i) == fontname) {
116 cb->setCurrentIndex(i);
121 // Try matching without foundry name
123 // We count in reverse in order to prefer the Xft foundry
124 for (int i = cb->count(); --i >= 0;) {
125 pair<string, string> tmp = parseFontName(fromqstr(cb->itemText(i)));
126 if (compare_ascii_no_case(tmp.first, family) == 0) {
127 cb->setCurrentIndex(i);
132 // family alone can contain e.g. "Helvetica [Adobe]"
133 pair<string, string> tmpfam = parseFontName(family);
135 // We count in reverse in order to prefer the Xft foundry
136 for (int i = cb->count() - 1; i >= 0; --i) {
137 pair<string, string> tmp = parseFontName(fromqstr(cb->itemText(i)));
138 if (compare_ascii_no_case(tmp.first, tmpfam.first) == 0) {
139 cb->setCurrentIndex(i);
144 // Bleh, default fonts, and the names couldn't be found. Hack
148 font.setKerning(false);
150 if (family == theApp()->romanFontName()) {
151 font.setStyleHint(QFont::Serif);
152 font.setFamily(family.c_str());
153 } else if (family == theApp()->sansFontName()) {
154 font.setStyleHint(QFont::SansSerif);
155 font.setFamily(family.c_str());
156 } else if (family == theApp()->typewriterFontName()) {
157 font.setStyleHint(QFont::TypeWriter);
158 font.setFamily(family.c_str());
160 lyxerr << "FAILED to find the default font: '"
161 << foundry << "', '" << family << '\''<< endl;
165 QFontInfo info(font);
166 pair<string, string> tmp = parseFontName(fromqstr(info.family()));
167 string const & default_font_name = tmp.first;
168 lyxerr << "Apparent font is " << default_font_name << endl;
170 for (int i = 0; i < cb->count(); ++i) {
171 lyxerr << "Looking at " << fromqstr(cb->itemText(i)) << endl;
172 if (compare_ascii_no_case(fromqstr(cb->itemText(i)),
173 default_font_name) == 0) {
174 cb->setCurrentIndex(i);
179 lyxerr << "FAILED to find the font: '"
180 << foundry << "', '" << family << '\'' <<endl;
184 /////////////////////////////////////////////////////////////////////
188 /////////////////////////////////////////////////////////////////////
190 PrefPlaintext::PrefPlaintext(QWidget * parent)
191 : PrefModule(_("Plain text"), 0, parent)
194 connect(plaintextLinelengthSB, SIGNAL(valueChanged(int)),
195 this, SIGNAL(changed()));
196 connect(plaintextRoffED, SIGNAL(textChanged(const QString&)),
197 this, SIGNAL(changed()));
201 void PrefPlaintext::apply(LyXRC & rc) const
203 rc.plaintext_linelen = plaintextLinelengthSB->value();
204 rc.plaintext_roff_command = fromqstr(plaintextRoffED->text());
208 void PrefPlaintext::update(LyXRC const & rc)
210 plaintextLinelengthSB->setValue(rc.plaintext_linelen);
211 plaintextRoffED->setText(toqstr(rc.plaintext_roff_command));
215 /////////////////////////////////////////////////////////////////////
219 /////////////////////////////////////////////////////////////////////
221 PrefDate::PrefDate(QWidget * parent)
222 : PrefModule(_("Date format"), 0, parent)
225 connect(DateED, SIGNAL(textChanged(const QString &)),
226 this, SIGNAL(changed()));
230 void PrefDate::apply(LyXRC & rc) const
232 rc.date_insert_format = fromqstr(DateED->text());
236 void PrefDate::update(LyXRC const & rc)
238 DateED->setText(toqstr(rc.date_insert_format));
242 /////////////////////////////////////////////////////////////////////
246 /////////////////////////////////////////////////////////////////////
248 PrefKeyboard::PrefKeyboard(GuiPreferences * form, QWidget * parent)
249 : PrefModule(_("Keyboard"), form, parent)
253 connect(keymapCB, SIGNAL(clicked()),
254 this, SIGNAL(changed()));
255 connect(firstKeymapED, SIGNAL(textChanged(const QString&)),
256 this, SIGNAL(changed()));
257 connect(secondKeymapED, SIGNAL(textChanged(const QString&)),
258 this, SIGNAL(changed()));
262 void PrefKeyboard::apply(LyXRC & rc) const
264 // FIXME: can derive CB from the two EDs
265 rc.use_kbmap = keymapCB->isChecked();
266 rc.primary_kbmap = internal_path(fromqstr(firstKeymapED->text()));
267 rc.secondary_kbmap = internal_path(fromqstr(secondKeymapED->text()));
271 void PrefKeyboard::update(LyXRC const & rc)
273 // FIXME: can derive CB from the two EDs
274 keymapCB->setChecked(rc.use_kbmap);
275 firstKeymapED->setText(toqstr(external_path(rc.primary_kbmap)));
276 secondKeymapED->setText(toqstr(external_path(rc.secondary_kbmap)));
280 QString PrefKeyboard::testKeymap(QString keymap)
282 return toqstr(form_->browsekbmap(from_utf8(internal_path(fromqstr(keymap)))));
286 void PrefKeyboard::on_firstKeymapPB_clicked(bool)
288 QString const file = testKeymap(firstKeymapED->text());
290 firstKeymapED->setText(file);
294 void PrefKeyboard::on_secondKeymapPB_clicked(bool)
296 QString const file = testKeymap(secondKeymapED->text());
298 secondKeymapED->setText(file);
302 void PrefKeyboard::on_keymapCB_toggled(bool keymap)
304 firstKeymapLA->setEnabled(keymap);
305 secondKeymapLA->setEnabled(keymap);
306 firstKeymapED->setEnabled(keymap);
307 secondKeymapED->setEnabled(keymap);
308 firstKeymapPB->setEnabled(keymap);
309 secondKeymapPB->setEnabled(keymap);
313 /////////////////////////////////////////////////////////////////////
317 /////////////////////////////////////////////////////////////////////
319 PrefLatex::PrefLatex(GuiPreferences * form, QWidget * parent)
320 : PrefModule(_("LaTeX"), form, parent)
323 connect(latexEncodingED, SIGNAL(textChanged(const QString&)),
324 this, SIGNAL(changed()));
325 connect(latexChecktexED, SIGNAL(textChanged(const QString&)),
326 this, SIGNAL(changed()));
327 connect(latexBibtexED, SIGNAL(textChanged(const QString&)),
328 this, SIGNAL(changed()));
329 connect(latexIndexED, SIGNAL(textChanged(const QString&)),
330 this, SIGNAL(changed()));
331 connect(latexAutoresetCB, SIGNAL(clicked()),
332 this, SIGNAL(changed()));
333 connect(latexDviPaperED, SIGNAL(textChanged(const QString&)),
334 this, SIGNAL(changed()));
335 connect(latexPaperSizeCO, SIGNAL(activated(int)),
336 this, SIGNAL(changed()));
338 #if defined(__CYGWIN__) || defined(_WIN32)
339 pathCB->setVisible(true);
340 connect(pathCB, SIGNAL(clicked()),
341 this, SIGNAL(changed()));
343 pathCB->setVisible(false);
348 void PrefLatex::apply(LyXRC & rc) const
350 rc.fontenc = fromqstr(latexEncodingED->text());
351 rc.chktex_command = fromqstr(latexChecktexED->text());
352 rc.bibtex_command = fromqstr(latexBibtexED->text());
353 rc.index_command = fromqstr(latexIndexED->text());
354 rc.auto_reset_options = latexAutoresetCB->isChecked();
355 rc.view_dvi_paper_option = fromqstr(latexDviPaperED->text());
356 rc.default_papersize =
357 form_->toPaperSize(latexPaperSizeCO->currentIndex());
358 #if defined(__CYGWIN__) || defined(_WIN32)
359 rc.windows_style_tex_paths = pathCB->isChecked();
364 void PrefLatex::update(LyXRC const & rc)
366 latexEncodingED->setText(toqstr(rc.fontenc));
367 latexChecktexED->setText(toqstr(rc.chktex_command));
368 latexBibtexED->setText(toqstr(rc.bibtex_command));
369 latexIndexED->setText(toqstr(rc.index_command));
370 latexAutoresetCB->setChecked(rc.auto_reset_options);
371 latexDviPaperED->setText(toqstr(rc.view_dvi_paper_option));
372 latexPaperSizeCO->setCurrentIndex(
373 form_->fromPaperSize(rc.default_papersize));
374 #if defined(__CYGWIN__) || defined(_WIN32)
375 pathCB->setChecked(rc.windows_style_tex_paths);
380 /////////////////////////////////////////////////////////////////////
384 /////////////////////////////////////////////////////////////////////
386 PrefScreenFonts::PrefScreenFonts(GuiPreferences * form, QWidget * parent)
387 : PrefModule(_("Screen fonts"), form, parent)
391 connect(screenRomanCO, SIGNAL(activated(const QString&)),
392 this, SLOT(select_roman(const QString&)));
393 connect(screenSansCO, SIGNAL(activated(const QString&)),
394 this, SLOT(select_sans(const QString&)));
395 connect(screenTypewriterCO, SIGNAL(activated(const QString&)),
396 this, SLOT(select_typewriter(const QString&)));
398 QFontDatabase fontdb;
399 QStringList families(fontdb.families());
400 for (QStringList::Iterator it = families.begin(); it != families.end(); ++it) {
401 screenRomanCO->addItem(*it);
402 screenSansCO->addItem(*it);
403 screenTypewriterCO->addItem(*it);
405 connect(screenRomanCO, SIGNAL(activated(const QString&)),
406 this, SIGNAL(changed()));
407 connect(screenSansCO, SIGNAL(activated(const QString&)),
408 this, SIGNAL(changed()));
409 connect(screenTypewriterCO, SIGNAL(activated(const QString&)),
410 this, SIGNAL(changed()));
411 connect(screenZoomSB, SIGNAL(valueChanged(int)),
412 this, SIGNAL(changed()));
413 connect(screenDpiSB, SIGNAL(valueChanged(int)),
414 this, SIGNAL(changed()));
415 connect(screenTinyED, SIGNAL(textChanged(const QString&)),
416 this, SIGNAL(changed()));
417 connect(screenSmallestED, SIGNAL(textChanged(const QString&)),
418 this, SIGNAL(changed()));
419 connect(screenSmallerED, SIGNAL(textChanged(const QString&)),
420 this, SIGNAL(changed()));
421 connect(screenSmallED, SIGNAL(textChanged(const QString&)),
422 this, SIGNAL(changed()));
423 connect(screenNormalED, SIGNAL(textChanged(const QString&)),
424 this, SIGNAL(changed()));
425 connect(screenLargeED, SIGNAL(textChanged(const QString&)),
426 this, SIGNAL(changed()));
427 connect(screenLargerED, SIGNAL(textChanged(const QString&)),
428 this, SIGNAL(changed()));
429 connect(screenLargestED, SIGNAL(textChanged(const QString&)),
430 this, SIGNAL(changed()));
431 connect(screenHugeED, SIGNAL(textChanged(const QString&)),
432 this, SIGNAL(changed()));
433 connect(screenHugerED, SIGNAL(textChanged(const QString&)),
434 this, SIGNAL(changed()));
436 screenTinyED->setValidator(new QDoubleValidator(screenTinyED));
437 screenSmallestED->setValidator(new QDoubleValidator(screenSmallestED));
438 screenSmallerED->setValidator(new QDoubleValidator(screenSmallerED));
439 screenSmallED->setValidator(new QDoubleValidator(screenSmallED));
440 screenNormalED->setValidator(new QDoubleValidator(screenNormalED));
441 screenLargeED->setValidator(new QDoubleValidator(screenLargeED));
442 screenLargerED->setValidator(new QDoubleValidator(screenLargerED));
443 screenLargestED->setValidator(new QDoubleValidator(screenLargestED));
444 screenHugeED->setValidator(new QDoubleValidator(screenHugeED));
445 screenHugerED->setValidator(new QDoubleValidator(screenHugerED));
449 void PrefScreenFonts::apply(LyXRC & rc) const
451 LyXRC const oldrc(rc);
453 boost::tie(rc.roman_font_name, rc.roman_font_foundry)
454 = parseFontName(fromqstr(screenRomanCO->currentText()));
455 boost::tie(rc.sans_font_name, rc.sans_font_foundry) =
456 parseFontName(fromqstr(screenSansCO->currentText()));
457 boost::tie(rc.typewriter_font_name, rc.typewriter_font_foundry) =
458 parseFontName(fromqstr(screenTypewriterCO->currentText()));
460 rc.zoom = screenZoomSB->value();
461 rc.dpi = screenDpiSB->value();
462 rc.font_sizes[Font::SIZE_TINY] = fromqstr(screenTinyED->text());
463 rc.font_sizes[Font::SIZE_SCRIPT] = fromqstr(screenSmallestED->text());
464 rc.font_sizes[Font::SIZE_FOOTNOTE] = fromqstr(screenSmallerED->text());
465 rc.font_sizes[Font::SIZE_SMALL] = fromqstr(screenSmallED->text());
466 rc.font_sizes[Font::SIZE_NORMAL] = fromqstr(screenNormalED->text());
467 rc.font_sizes[Font::SIZE_LARGE] = fromqstr(screenLargeED->text());
468 rc.font_sizes[Font::SIZE_LARGER] = fromqstr(screenLargerED->text());
469 rc.font_sizes[Font::SIZE_LARGEST] = fromqstr(screenLargestED->text());
470 rc.font_sizes[Font::SIZE_HUGE] = fromqstr(screenHugeED->text());
471 rc.font_sizes[Font::SIZE_HUGER] = fromqstr(screenHugerED->text());
473 if (rc.font_sizes != oldrc.font_sizes
474 || rc.roman_font_name != oldrc.roman_font_name
475 || rc.sans_font_name != oldrc.sans_font_name
476 || rc.typewriter_font_name != oldrc.typewriter_font_name
477 || rc.zoom != oldrc.zoom || rc.dpi != oldrc.dpi) {
478 // The global QPixmapCache is used in GuiPainter to cache text
479 // painting so we must reset it in case any of the above
480 // parameter is changed.
481 QPixmapCache::clear();
482 guiApp->fontLoader().update();
483 form_->updateScreenFonts();
488 void PrefScreenFonts::update(LyXRC const & rc)
490 setComboxFont(screenRomanCO, rc.roman_font_name,
491 rc.roman_font_foundry);
492 setComboxFont(screenSansCO, rc.sans_font_name,
493 rc.sans_font_foundry);
494 setComboxFont(screenTypewriterCO, rc.typewriter_font_name,
495 rc.typewriter_font_foundry);
497 select_roman(screenRomanCO->currentText());
498 select_sans(screenSansCO->currentText());
499 select_typewriter(screenTypewriterCO->currentText());
501 screenZoomSB->setValue(rc.zoom);
502 screenDpiSB->setValue(rc.dpi);
503 screenTinyED->setText(toqstr(rc.font_sizes[Font::SIZE_TINY]));
504 screenSmallestED->setText(toqstr(rc.font_sizes[Font::SIZE_SCRIPT]));
505 screenSmallerED->setText(toqstr(rc.font_sizes[Font::SIZE_FOOTNOTE]));
506 screenSmallED->setText(toqstr(rc.font_sizes[Font::SIZE_SMALL]));
507 screenNormalED->setText(toqstr(rc.font_sizes[Font::SIZE_NORMAL]));
508 screenLargeED->setText(toqstr(rc.font_sizes[Font::SIZE_LARGE]));
509 screenLargerED->setText(toqstr(rc.font_sizes[Font::SIZE_LARGER]));
510 screenLargestED->setText(toqstr(rc.font_sizes[Font::SIZE_LARGEST]));
511 screenHugeED->setText(toqstr(rc.font_sizes[Font::SIZE_HUGE]));
512 screenHugerED->setText(toqstr(rc.font_sizes[Font::SIZE_HUGER]));
515 void PrefScreenFonts::select_roman(const QString& name)
517 screenRomanFE->set(QFont(name), name);
521 void PrefScreenFonts::select_sans(const QString& name)
523 screenSansFE->set(QFont(name), name);
527 void PrefScreenFonts::select_typewriter(const QString& name)
529 screenTypewriterFE->set(QFont(name), name);
533 /////////////////////////////////////////////////////////////////////
537 /////////////////////////////////////////////////////////////////////
543 bool operator()(Color::color const & lhs, Color::color const & rhs) const {
544 return lcolor.getGUIName(lhs) < lcolor.getGUIName(rhs);
550 PrefColors::PrefColors(GuiPreferences * form, QWidget * parent)
551 : PrefModule( _("Colors"), form, parent)
555 // FIXME: all of this initialization should be put into the controller.
556 // See http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg113301.html
557 // for some discussion of why that is not trivial.
558 QPixmap icon(32, 32);
559 for (int i = 0; i < Color::ignore; ++i) {
560 Color::color lc = static_cast<Color::color>(i);
561 if (lc == Color::none
562 || lc == Color::black
563 || lc == Color::white
565 || lc == Color::green
568 || lc == Color::magenta
569 || lc == Color::yellow
570 || lc == Color::inherit
571 || lc == Color::ignore) continue;
573 lcolors_.push_back(lc);
575 std::sort(lcolors_.begin(), lcolors_.end(), ColorSorter());
576 vector<Color_color>::const_iterator cit = lcolors_.begin();
577 vector<Color_color>::const_iterator const end = lcolors_.end();
578 for (; cit != end; ++cit) {
579 (void) new QListWidgetItem(QIcon(icon),
580 toqstr(lcolor.getGUIName(*cit)), lyxObjectsLW);
582 curcolors_.resize(lcolors_.size());
583 newcolors_.resize(lcolors_.size());
584 // End initialization
586 connect(colorChangePB, SIGNAL(clicked()),
587 this, SLOT(change_color()));
588 connect(lyxObjectsLW, SIGNAL(itemSelectionChanged()),
589 this, SLOT(change_lyxObjects_selection()));
590 connect(lyxObjectsLW, SIGNAL(itemActivated(QListWidgetItem*)),
591 this, SLOT(change_color()));
595 void PrefColors::apply(LyXRC & /*rc*/) const
597 for (unsigned int i = 0; i < lcolors_.size(); ++i)
598 if (curcolors_[i] != newcolors_[i])
599 form_->setColor(lcolors_[i], fromqstr(newcolors_[i]));
603 void PrefColors::update(LyXRC const & /*rc*/)
605 for (unsigned int i = 0; i < lcolors_.size(); ++i) {
606 QColor color = QColor(guiApp->colorCache().get(lcolors_[i]));
607 QPixmap coloritem(32, 32);
608 coloritem.fill(color);
609 lyxObjectsLW->item(i)->setIcon(QIcon(coloritem));
610 newcolors_[i] = curcolors_[i] = color.name();
612 change_lyxObjects_selection();
615 void PrefColors::change_color()
617 int const row = lyxObjectsLW->currentRow();
623 QString const color = newcolors_[row];
624 QColor c = QColorDialog::getColor(QColor(color), qApp->focusWidget());
626 if (c.isValid() && c.name() != color) {
627 newcolors_[row] = c.name();
628 QPixmap coloritem(32, 32);
630 lyxObjectsLW->currentItem()->setIcon(QIcon(coloritem));
636 void PrefColors::change_lyxObjects_selection()
638 colorChangePB->setDisabled(lyxObjectsLW->currentRow() < 0);
642 /////////////////////////////////////////////////////////////////////
646 /////////////////////////////////////////////////////////////////////
648 PrefDisplay::PrefDisplay(QWidget * parent)
649 : PrefModule(_("Graphics"), 0, parent)
652 connect(instantPreviewCO, SIGNAL(activated(int)),
653 this, SIGNAL(changed()));
654 connect(displayGraphicsCO, SIGNAL(activated(int)),
655 this, SIGNAL(changed()));
659 void PrefDisplay::apply(LyXRC & rc) const
661 switch (instantPreviewCO->currentIndex()) {
662 case 0: rc.preview = LyXRC::PREVIEW_OFF; break;
663 case 1: rc.preview = LyXRC::PREVIEW_NO_MATH; break;
664 case 2: rc.preview = LyXRC::PREVIEW_ON; break;
667 lyx::graphics::DisplayType dtype;
668 switch (displayGraphicsCO->currentIndex()) {
669 case 3: dtype = lyx::graphics::NoDisplay; break;
670 case 2: dtype = lyx::graphics::ColorDisplay; break;
671 case 1: dtype = lyx::graphics::GrayscaleDisplay; break;
672 case 0: dtype = lyx::graphics::MonochromeDisplay; break;
673 default: dtype = lyx::graphics::GrayscaleDisplay;
675 rc.display_graphics = dtype;
677 // FIXME!! The graphics cache no longer has a changeDisplay method.
679 if (old_value != rc.display_graphics) {
680 lyx::graphics::GCache & gc = lyx::graphics::GCache::get();
687 void PrefDisplay::update(LyXRC const & rc)
689 switch (rc.preview) {
690 case LyXRC::PREVIEW_OFF:
691 instantPreviewCO->setCurrentIndex(0);
693 case LyXRC::PREVIEW_NO_MATH :
694 instantPreviewCO->setCurrentIndex(1);
696 case LyXRC::PREVIEW_ON :
697 instantPreviewCO->setCurrentIndex(2);
702 switch (rc.display_graphics) {
703 case lyx::graphics::NoDisplay: item = 3; break;
704 case lyx::graphics::ColorDisplay: item = 2; break;
705 case lyx::graphics::GrayscaleDisplay: item = 1; break;
706 case lyx::graphics::MonochromeDisplay: item = 0; break;
709 displayGraphicsCO->setCurrentIndex(item);
713 /////////////////////////////////////////////////////////////////////
717 /////////////////////////////////////////////////////////////////////
719 PrefPaths::PrefPaths(GuiPreferences * form, QWidget * parent)
720 : PrefModule(_("Paths"), form, parent)
723 connect(templateDirPB, SIGNAL(clicked()), this, SLOT(select_templatedir()));
724 connect(tempDirPB, SIGNAL(clicked()), this, SLOT(select_tempdir()));
725 connect(backupDirPB, SIGNAL(clicked()), this, SLOT(select_backupdir()));
726 connect(workingDirPB, SIGNAL(clicked()), this, SLOT(select_workingdir()));
727 connect(lyxserverDirPB, SIGNAL(clicked()), this, SLOT(select_lyxpipe()));
728 connect(workingDirED, SIGNAL(textChanged(const QString&)),
729 this, SIGNAL(changed()));
730 connect(templateDirED, SIGNAL(textChanged(const QString&)),
731 this, SIGNAL(changed()));
732 connect(backupDirED, SIGNAL(textChanged(const QString&)),
733 this, SIGNAL(changed()));
734 connect(tempDirED, SIGNAL(textChanged(const QString&)),
735 this, SIGNAL(changed()));
736 connect(lyxserverDirED, SIGNAL(textChanged(const QString&)),
737 this, SIGNAL(changed()));
738 connect(pathPrefixED, SIGNAL(textChanged(const QString&)),
739 this, SIGNAL(changed()));
743 void PrefPaths::apply(LyXRC & rc) const
745 rc.document_path = internal_path(fromqstr(workingDirED->text()));
746 rc.template_path = internal_path(fromqstr(templateDirED->text()));
747 rc.backupdir_path = internal_path(fromqstr(backupDirED->text()));
748 rc.tempdir_path = internal_path(fromqstr(tempDirED->text()));
749 rc.path_prefix = internal_path_list(fromqstr(pathPrefixED->text()));
750 // FIXME: should be a checkbox only
751 rc.lyxpipes = internal_path(fromqstr(lyxserverDirED->text()));
755 void PrefPaths::update(LyXRC const & rc)
757 workingDirED->setText(toqstr(external_path(rc.document_path)));
758 templateDirED->setText(toqstr(external_path(rc.template_path)));
759 backupDirED->setText(toqstr(external_path(rc.backupdir_path)));
760 tempDirED->setText(toqstr(external_path(rc.tempdir_path)));
761 pathPrefixED->setText(toqstr(external_path_list(rc.path_prefix)));
762 // FIXME: should be a checkbox only
763 lyxserverDirED->setText(toqstr(external_path(rc.lyxpipes)));
767 void PrefPaths::select_templatedir()
769 docstring file(form_->browsedir(
770 from_utf8(internal_path(fromqstr(templateDirED->text()))),
771 _("Select a document templates directory")));
773 templateDirED->setText(toqstr(file));
777 void PrefPaths::select_tempdir()
779 docstring file(form_->browsedir(
780 from_utf8(internal_path(fromqstr(tempDirED->text()))),
781 _("Select a temporary directory")));
783 tempDirED->setText(toqstr(file));
787 void PrefPaths::select_backupdir()
789 docstring file(form_->browsedir(
790 from_utf8(internal_path(fromqstr(backupDirED->text()))),
791 _("Select a backups directory")));
793 backupDirED->setText(toqstr(file));
797 void PrefPaths::select_workingdir()
799 docstring file(form_->browsedir(
800 from_utf8(internal_path(fromqstr(workingDirED->text()))),
801 _("Select a document directory")));
803 workingDirED->setText(toqstr(file));
807 void PrefPaths::select_lyxpipe()
809 docstring file(form_->browse(
810 from_utf8(internal_path(fromqstr(lyxserverDirED->text()))),
811 _("Give a filename for the LyX server pipe")));
813 lyxserverDirED->setText(toqstr(file));
817 /////////////////////////////////////////////////////////////////////
821 /////////////////////////////////////////////////////////////////////
823 PrefSpellchecker::PrefSpellchecker(GuiPreferences * form, QWidget * parent)
824 : PrefModule(_("Spellchecker"), form, parent)
828 connect(persDictionaryPB, SIGNAL(clicked()), this, SLOT(select_dict()));
829 #if defined (USE_ISPELL)
830 connect(spellCommandCO, SIGNAL(activated(int)),
831 this, SIGNAL(changed()));
833 spellCommandCO->setEnabled(false);
835 connect(altLanguageED, SIGNAL(textChanged(const QString&)),
836 this, SIGNAL(changed()));
837 connect(escapeCharactersED, SIGNAL(textChanged(const QString&)),
838 this, SIGNAL(changed()));
839 connect(persDictionaryED, SIGNAL(textChanged(const QString&)),
840 this, SIGNAL(changed()));
841 connect(compoundWordCB, SIGNAL(clicked()),
842 this, SIGNAL(changed()));
843 connect(inputEncodingCB, SIGNAL(clicked()),
844 this, SIGNAL(changed()));
846 spellCommandCO->addItem(qt_("ispell"));
847 spellCommandCO->addItem(qt_("aspell"));
848 spellCommandCO->addItem(qt_("hspell"));
850 spellCommandCO->addItem(qt_("pspell (library)"));
853 spellCommandCO->addItem(qt_("aspell (library)"));
859 void PrefSpellchecker::apply(LyXRC & rc) const
861 switch (spellCommandCO->currentIndex()) {
865 rc.use_spell_lib = false;
866 rc.isp_command = fromqstr(spellCommandCO->currentText());
869 rc.use_spell_lib = true;
873 // FIXME: remove isp_use_alt_lang
874 rc.isp_alt_lang = fromqstr(altLanguageED->text());
875 rc.isp_use_alt_lang = !rc.isp_alt_lang.empty();
876 // FIXME: remove isp_use_esc_chars
877 rc.isp_esc_chars = fromqstr(escapeCharactersED->text());
878 rc.isp_use_esc_chars = !rc.isp_esc_chars.empty();
879 // FIXME: remove isp_use_pers_dict
880 rc.isp_pers_dict = internal_path(fromqstr(persDictionaryED->text()));
881 rc.isp_use_pers_dict = !rc.isp_pers_dict.empty();
882 rc.isp_accept_compound = compoundWordCB->isChecked();
883 rc.isp_use_input_encoding = inputEncodingCB->isChecked();
887 void PrefSpellchecker::update(LyXRC const & rc)
889 spellCommandCO->setCurrentIndex(0);
891 if (rc.isp_command == "ispell") {
892 spellCommandCO->setCurrentIndex(0);
893 } else if (rc.isp_command == "aspell") {
894 spellCommandCO->setCurrentIndex(1);
895 } else if (rc.isp_command == "hspell") {
896 spellCommandCO->setCurrentIndex(2);
899 if (rc.use_spell_lib) {
900 #if defined(USE_ASPELL) || defined(USE_PSPELL)
901 spellCommandCO->setCurrentIndex(3);
905 // FIXME: remove isp_use_alt_lang
906 altLanguageED->setText(toqstr(rc.isp_alt_lang));
907 // FIXME: remove isp_use_esc_chars
908 escapeCharactersED->setText(toqstr(rc.isp_esc_chars));
909 // FIXME: remove isp_use_pers_dict
910 persDictionaryED->setText(toqstr(external_path(rc.isp_pers_dict)));
911 compoundWordCB->setChecked(rc.isp_accept_compound);
912 inputEncodingCB->setChecked(rc.isp_use_input_encoding);
916 void PrefSpellchecker::select_dict()
918 docstring file(form_->browsedict(
919 from_utf8(internal_path(fromqstr(persDictionaryED->text())))));
921 persDictionaryED->setText(toqstr(file));
926 /////////////////////////////////////////////////////////////////////
930 /////////////////////////////////////////////////////////////////////
933 PrefConverters::PrefConverters(GuiPreferences * form, QWidget * parent)
934 : PrefModule(_("Converters"), form, parent)
938 connect(converterNewPB, SIGNAL(clicked()),
939 this, SLOT(update_converter()));
940 connect(converterRemovePB, SIGNAL(clicked()),
941 this, SLOT(remove_converter()));
942 connect(converterModifyPB, SIGNAL(clicked()),
943 this, SLOT(update_converter()));
944 connect(convertersLW, SIGNAL(currentRowChanged(int)),
945 this, SLOT(switch_converter()));
946 connect(converterFromCO, SIGNAL(activated(const QString&)),
947 this, SLOT(converter_changed()));
948 connect(converterToCO, SIGNAL(activated(const QString&)),
949 this, SLOT(converter_changed()));
950 connect(converterED, SIGNAL(textEdited(const QString&)),
951 this, SLOT(converter_changed()));
952 connect(converterFlagED, SIGNAL(textEdited(const QString&)),
953 this, SLOT(converter_changed()));
954 connect(converterNewPB, SIGNAL(clicked()),
955 this, SIGNAL(changed()));
956 connect(converterRemovePB, SIGNAL(clicked()),
957 this, SIGNAL(changed()));
958 connect(converterModifyPB, SIGNAL(clicked()),
959 this, SIGNAL(changed()));
960 connect(maxAgeLE, SIGNAL(textEdited(const QString&)),
961 this, SIGNAL(changed()));
963 maxAgeLE->setValidator(new QDoubleValidator(maxAgeLE));
964 //converterDefGB->setFocusProxy(convertersLW);
968 void PrefConverters::apply(LyXRC & rc) const
970 rc.use_converter_cache = cacheCB->isChecked();
971 rc.converter_cache_maxage = int(maxAgeLE->text().toDouble() * 86400.0);
975 void PrefConverters::update(LyXRC const & rc)
977 cacheCB->setChecked(rc.use_converter_cache);
979 max_age.setNum(double(rc.converter_cache_maxage) / 86400.0, 'g', 6);
980 maxAgeLE->setText(max_age);
985 void PrefConverters::updateGui()
987 form_->formats().sort();
988 form_->converters().update(form_->formats());
989 // save current selection
990 QString current = converterFromCO->currentText()
991 + " -> " + converterToCO->currentText();
993 converterFromCO->clear();
994 converterToCO->clear();
996 Formats::const_iterator cit = form_->formats().begin();
997 Formats::const_iterator end = form_->formats().end();
998 for (; cit != end; ++cit) {
999 converterFromCO->addItem(toqstr(cit->prettyname()));
1000 converterToCO->addItem(toqstr(cit->prettyname()));
1003 // currentRowChanged(int) is also triggered when updating the listwidget
1004 // block signals to avoid unnecessary calls to switch_converter()
1005 convertersLW->blockSignals(true);
1006 convertersLW->clear();
1008 Converters::const_iterator ccit = form_->converters().begin();
1009 Converters::const_iterator cend = form_->converters().end();
1010 for (; ccit != cend; ++ccit) {
1011 std::string const name =
1012 ccit->From->prettyname() + " -> " + ccit->To->prettyname();
1013 int type = form_->converters().getNumber(ccit->From->name(), ccit->To->name());
1014 new QListWidgetItem(toqstr(name), convertersLW, type);
1016 convertersLW->sortItems(Qt::AscendingOrder);
1017 convertersLW->blockSignals(false);
1019 // restore selection
1020 if (!current.isEmpty()) {
1021 QList<QListWidgetItem *> const item =
1022 convertersLW->findItems(current, Qt::MatchExactly);
1023 if (!item.isEmpty())
1024 convertersLW->setCurrentItem(item.at(0));
1027 // select first element if restoring failed
1028 if (convertersLW->currentRow() == -1)
1029 convertersLW->setCurrentRow(0);
1035 void PrefConverters::switch_converter()
1037 int const cnr = convertersLW->currentItem()->type();
1038 Converter const & c(form_->converters().get(cnr));
1039 converterFromCO->setCurrentIndex(form_->formats().getNumber(c.from));
1040 converterToCO->setCurrentIndex(form_->formats().getNumber(c.to));
1041 converterED->setText(toqstr(c.command));
1042 converterFlagED->setText(toqstr(c.flags));
1048 void PrefConverters::converter_changed()
1054 void PrefConverters::updateButtons()
1056 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1057 Format const & to = form_->formats().get(converterToCO->currentIndex());
1058 int const sel = form_->converters().getNumber(from.name(), to.name());
1059 bool const known = !(sel < 0);
1060 bool const valid = !(converterED->text().isEmpty()
1061 || from.name() == to.name());
1063 int const cnr = convertersLW->currentItem()->type();
1064 Converter const & c(form_->converters().get(cnr));
1065 string const old_command = c.command;
1066 string const old_flag = c.flags;
1067 string const new_command(fromqstr(converterED->text()));
1068 string const new_flag(fromqstr(converterFlagED->text()));
1070 bool modified = ((old_command != new_command) || (old_flag != new_flag));
1072 converterModifyPB->setEnabled(valid && known && modified);
1073 converterNewPB->setEnabled(valid && !known);
1074 converterRemovePB->setEnabled(known);
1076 maxAgeLE->setEnabled(cacheCB->isChecked());
1077 maxAgeLA->setEnabled(cacheCB->isChecked());
1082 // specify unique from/to or it doesn't appear. This is really bad UI
1083 // this is why we can use the same function for both new and modify
1084 void PrefConverters::update_converter()
1086 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1087 Format const & to = form_->formats().get(converterToCO->currentIndex());
1088 string const flags = fromqstr(converterFlagED->text());
1089 string const command = fromqstr(converterED->text());
1091 Converter const * old =
1092 form_->converters().getConverter(from.name(), to.name());
1093 form_->converters().add(from.name(), to.name(), command, flags);
1096 form_->converters().updateLast(form_->formats());
1100 // Remove all files created by this converter from the cache, since
1101 // the modified converter might create different files.
1102 ConverterCache::get().remove_all(from.name(), to.name());
1106 void PrefConverters::remove_converter()
1108 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1109 Format const & to = form_->formats().get(converterToCO->currentIndex());
1110 form_->converters().erase(from.name(), to.name());
1114 // Remove all files created by this converter from the cache, since
1115 // a possible new converter might create different files.
1116 ConverterCache::get().remove_all(from.name(), to.name());
1120 void PrefConverters::on_cacheCB_stateChanged(int state)
1122 maxAgeLE->setEnabled(state == Qt::Checked);
1123 maxAgeLA->setEnabled(state == Qt::Checked);
1128 /////////////////////////////////////////////////////////////////////
1132 /////////////////////////////////////////////////////////////////////
1133 FormatValidator::FormatValidator(QWidget * parent, Formats const & f)
1134 : QValidator(parent), formats_(f)
1139 void FormatValidator::fixup(QString & input) const
1141 Formats::const_iterator cit = formats_.begin();
1142 Formats::const_iterator end = formats_.end();
1143 for (; cit != end; ++cit) {
1144 string const name = str(cit);
1145 if (distance(formats_.begin(), cit) == nr()) {
1146 input = toqstr(name);
1154 QValidator::State FormatValidator::validate(QString & input, int & /*pos*/) const
1156 Formats::const_iterator cit = formats_.begin();
1157 Formats::const_iterator end = formats_.end();
1158 bool unknown = true;
1159 for (; unknown && cit != end; ++cit) {
1160 string const name = str(cit);
1161 if (distance(formats_.begin(), cit) != nr())
1162 unknown = toqstr(name) != input;
1165 if (unknown && !input.isEmpty())
1166 return QValidator::Acceptable;
1168 return QValidator::Intermediate;
1172 int FormatValidator::nr() const
1174 QComboBox * p = qobject_cast<QComboBox *>(parent());
1175 return p->itemData(p->currentIndex()).toInt();
1179 FormatNameValidator::FormatNameValidator(QWidget * parent, Formats const & f)
1180 : FormatValidator(parent, f)
1184 std::string FormatNameValidator::str(Formats::const_iterator it) const
1190 FormatPrettynameValidator::FormatPrettynameValidator(QWidget * parent, Formats const & f)
1191 : FormatValidator(parent, f)
1196 std::string FormatPrettynameValidator::str(Formats::const_iterator it) const
1198 return it->prettyname();
1202 PrefFileformats::PrefFileformats(GuiPreferences * form, QWidget * parent)
1203 : PrefModule(_("File formats"), form, parent)
1206 formatED->setValidator(new FormatNameValidator(formatsCB, form_->formats()));
1207 formatsCB->setValidator(new FormatPrettynameValidator(formatsCB, form_->formats()));
1209 connect(documentCB, SIGNAL(clicked()),
1210 this, SLOT(setFlags()));
1211 connect(vectorCB, SIGNAL(clicked()),
1212 this, SLOT(setFlags()));
1213 connect(formatsCB->lineEdit(), SIGNAL(editingFinished()),
1214 this, SLOT(updatePrettyname()));
1215 connect(formatsCB->lineEdit(), SIGNAL(textEdited(const QString &)),
1216 this, SIGNAL(changed()));
1220 void PrefFileformats::apply(LyXRC & /*rc*/) const
1225 void PrefFileformats::update(LyXRC const & /*rc*/)
1231 void PrefFileformats::updateView()
1233 QString const current = formatsCB->currentText();
1235 // update combobox with formats
1236 formatsCB->blockSignals(true);
1238 form_->formats().sort();
1239 Formats::const_iterator cit = form_->formats().begin();
1240 Formats::const_iterator end = form_->formats().end();
1241 for (; cit != end; ++cit)
1242 formatsCB->addItem(toqstr(cit->prettyname()),
1243 QVariant(form_->formats().getNumber(cit->name())) );
1245 // restore selection
1246 int const item = formatsCB->findText(current, Qt::MatchExactly);
1247 formatsCB->setCurrentIndex(item < 0 ? 0 : item);
1248 on_formatsCB_currentIndexChanged(item < 0 ? 0 : item);
1249 formatsCB->blockSignals(false);
1253 void PrefFileformats::on_formatsCB_currentIndexChanged(int i)
1255 int const nr = formatsCB->itemData(i).toInt();
1256 Format const f = form_->formats().get(nr);
1258 formatED->setText(toqstr(f.name()));
1259 copierED->setText(toqstr(form_->movers().command(f.name())));
1260 extensionED->setText(toqstr(f.extension()));
1261 shortcutED->setText(toqstr(f.shortcut()));
1262 viewerED->setText(toqstr(f.viewer()));
1263 editorED->setText(toqstr(f.editor()));
1264 documentCB->setChecked((f.documentFormat()));
1265 vectorCB->setChecked((f.vectorFormat()));
1269 void PrefFileformats::setFlags()
1271 int flags = Format::none;
1272 if (documentCB->isChecked())
1273 flags |= Format::document;
1274 if (vectorCB->isChecked())
1275 flags |= Format::vector;
1276 currentFormat().setFlags(flags);
1281 void PrefFileformats::on_copierED_textEdited(const QString & s)
1283 string const fmt = fromqstr(formatED->text());
1284 form_->movers().set(fmt, fromqstr(s));
1289 void PrefFileformats::on_extensionED_textEdited(const QString & s)
1291 currentFormat().setExtension(fromqstr(s));
1295 void PrefFileformats::on_viewerED_textEdited(const QString & s)
1297 currentFormat().setViewer(fromqstr(s));
1302 void PrefFileformats::on_editorED_textEdited(const QString & s)
1304 currentFormat().setEditor(fromqstr(s));
1309 void PrefFileformats::on_shortcutED_textEdited(const QString & s)
1311 currentFormat().setShortcut(fromqstr(s));
1316 void PrefFileformats::on_formatED_editingFinished()
1318 string const newname = fromqstr(formatED->displayText());
1319 if (newname == currentFormat().name())
1322 currentFormat().setName(newname);
1327 void PrefFileformats::on_formatED_textChanged(const QString &)
1329 QString t = formatED->text();
1331 bool valid = formatED->validator()->validate(t, p) == QValidator::Acceptable;
1332 setValid(formatLA, valid);
1336 void PrefFileformats::on_formatsCB_editTextChanged(const QString &)
1338 QString t = formatsCB->currentText();
1340 bool valid = formatsCB->validator()->validate(t, p) == QValidator::Acceptable;
1341 setValid(formatsLA, valid);
1345 void PrefFileformats::updatePrettyname()
1347 string const newname = fromqstr(formatsCB->currentText());
1348 if (newname == currentFormat().prettyname())
1351 currentFormat().setPrettyname(newname);
1358 Format & PrefFileformats::currentFormat()
1360 int const i = formatsCB->currentIndex();
1361 int const nr = formatsCB->itemData(i).toInt();
1362 return form_->formats().get(nr);
1366 void PrefFileformats::on_formatNewPB_clicked()
1368 form_->formats().add("", "", "", "", "", "", Format::none);
1370 formatsCB->setCurrentIndex(0);
1371 formatsCB->setFocus(Qt::OtherFocusReason);
1375 void PrefFileformats::on_formatRemovePB_clicked()
1377 int const i = formatsCB->currentIndex();
1378 int const nr = formatsCB->itemData(i).toInt();
1379 string const current_text = form_->formats().get(nr).name();
1380 if (form_->converters().formatIsUsed(current_text)) {
1381 Alert::error(_("Format in use"),
1382 _("Cannot remove a Format used by a Converter. "
1383 "Remove the converter first."));
1387 form_->formats().erase(current_text);
1390 on_formatsCB_editTextChanged(formatsCB->currentText());
1395 /////////////////////////////////////////////////////////////////////
1399 /////////////////////////////////////////////////////////////////////
1401 PrefLanguage::PrefLanguage(QWidget * parent)
1402 : PrefModule(_("Language"), 0, parent)
1406 connect(rtlCB, SIGNAL(clicked()),
1407 this, SIGNAL(changed()));
1408 connect(markForeignCB, SIGNAL(clicked()),
1409 this, SIGNAL(changed()));
1410 connect(autoBeginCB, SIGNAL(clicked()),
1411 this, SIGNAL(changed()));
1412 connect(autoEndCB, SIGNAL(clicked()),
1413 this, SIGNAL(changed()));
1414 connect(useBabelCB, SIGNAL(clicked()),
1415 this, SIGNAL(changed()));
1416 connect(globalCB, SIGNAL(clicked()),
1417 this, SIGNAL(changed()));
1418 connect(languagePackageED, SIGNAL(textChanged(const QString&)),
1419 this, SIGNAL(changed()));
1420 connect(startCommandED, SIGNAL(textChanged(const QString&)),
1421 this, SIGNAL(changed()));
1422 connect(endCommandED, SIGNAL(textChanged(const QString&)),
1423 this, SIGNAL(changed()));
1424 connect(defaultLanguageCO, SIGNAL(activated(int)),
1425 this, SIGNAL(changed()));
1427 defaultLanguageCO->clear();
1429 // store the lang identifiers for later
1430 std::vector<LanguagePair> const langs = frontend::getLanguageData(false);
1431 std::vector<LanguagePair>::const_iterator lit = langs.begin();
1432 std::vector<LanguagePair>::const_iterator lend = langs.end();
1434 for (; lit != lend; ++lit) {
1435 defaultLanguageCO->addItem(toqstr(lit->first));
1436 lang_.push_back(lit->second);
1441 void PrefLanguage::apply(LyXRC & rc) const
1443 // FIXME: remove rtl_support bool
1444 rc.rtl_support = rtlCB->isChecked();
1445 rc.mark_foreign_language = markForeignCB->isChecked();
1446 rc.language_auto_begin = autoBeginCB->isChecked();
1447 rc.language_auto_end = autoEndCB->isChecked();
1448 rc.language_use_babel = useBabelCB->isChecked();
1449 rc.language_global_options = globalCB->isChecked();
1450 rc.language_package = fromqstr(languagePackageED->text());
1451 rc.language_command_begin = fromqstr(startCommandED->text());
1452 rc.language_command_end = fromqstr(endCommandED->text());
1453 rc.default_language = lang_[defaultLanguageCO->currentIndex()];
1457 void PrefLanguage::update(LyXRC const & rc)
1459 // FIXME: remove rtl_support bool
1460 rtlCB->setChecked(rc.rtl_support);
1461 markForeignCB->setChecked(rc.mark_foreign_language);
1462 autoBeginCB->setChecked(rc.language_auto_begin);
1463 autoEndCB->setChecked(rc.language_auto_end);
1464 useBabelCB->setChecked(rc.language_use_babel);
1465 globalCB->setChecked(rc.language_global_options);
1466 languagePackageED->setText(toqstr(rc.language_package));
1467 startCommandED->setText(toqstr(rc.language_command_begin));
1468 endCommandED->setText(toqstr(rc.language_command_end));
1470 int const pos = int(findPos_helper(lang_, rc.default_language));
1471 defaultLanguageCO->setCurrentIndex(pos);
1475 /////////////////////////////////////////////////////////////////////
1479 /////////////////////////////////////////////////////////////////////
1481 PrefPrinter::PrefPrinter(QWidget * parent)
1482 : PrefModule(_("Printer"), 0, parent)
1486 connect(printerAdaptCB, SIGNAL(clicked()),
1487 this, SIGNAL(changed()));
1488 connect(printerCommandED, SIGNAL(textChanged(const QString&)),
1489 this, SIGNAL(changed()));
1490 connect(printerNameED, SIGNAL(textChanged(const QString&)),
1491 this, SIGNAL(changed()));
1492 connect(printerPageRangeED, SIGNAL(textChanged(const QString&)),
1493 this, SIGNAL(changed()));
1494 connect(printerCopiesED, SIGNAL(textChanged(const QString&)),
1495 this, SIGNAL(changed()));
1496 connect(printerReverseED, SIGNAL(textChanged(const QString&)),
1497 this, SIGNAL(changed()));
1498 connect(printerToPrinterED, SIGNAL(textChanged(const QString&)),
1499 this, SIGNAL(changed()));
1500 connect(printerExtensionED, SIGNAL(textChanged(const QString&)),
1501 this, SIGNAL(changed()));
1502 connect(printerSpoolCommandED, SIGNAL(textChanged(const QString&)),
1503 this, SIGNAL(changed()));
1504 connect(printerPaperTypeED, SIGNAL(textChanged(const QString&)),
1505 this, SIGNAL(changed()));
1506 connect(printerEvenED, SIGNAL(textChanged(const QString&)),
1507 this, SIGNAL(changed()));
1508 connect(printerOddED, SIGNAL(textChanged(const QString&)),
1509 this, SIGNAL(changed()));
1510 connect(printerCollatedED, SIGNAL(textChanged(const QString&)),
1511 this, SIGNAL(changed()));
1512 connect(printerLandscapeED, SIGNAL(textChanged(const QString&)),
1513 this, SIGNAL(changed()));
1514 connect(printerToFileED, SIGNAL(textChanged(const QString&)),
1515 this, SIGNAL(changed()));
1516 connect(printerExtraED, SIGNAL(textChanged(const QString&)),
1517 this, SIGNAL(changed()));
1518 connect(printerSpoolPrefixED, SIGNAL(textChanged(const QString&)),
1519 this, SIGNAL(changed()));
1520 connect(printerPaperSizeED, SIGNAL(textChanged(const QString&)),
1521 this, SIGNAL(changed()));
1525 void PrefPrinter::apply(LyXRC & rc) const
1527 rc.print_adapt_output = printerAdaptCB->isChecked();
1528 rc.print_command = fromqstr(printerCommandED->text());
1529 rc.printer = fromqstr(printerNameED->text());
1531 rc.print_pagerange_flag = fromqstr(printerPageRangeED->text());
1532 rc.print_copies_flag = fromqstr(printerCopiesED->text());
1533 rc.print_reverse_flag = fromqstr(printerReverseED->text());
1534 rc.print_to_printer = fromqstr(printerToPrinterED->text());
1535 rc.print_file_extension = fromqstr(printerExtensionED->text());
1536 rc.print_spool_command = fromqstr(printerSpoolCommandED->text());
1537 rc.print_paper_flag = fromqstr(printerPaperTypeED->text());
1538 rc.print_evenpage_flag = fromqstr(printerEvenED->text());
1539 rc.print_oddpage_flag = fromqstr(printerOddED->text());
1540 rc.print_collcopies_flag = fromqstr(printerCollatedED->text());
1541 rc.print_landscape_flag = fromqstr(printerLandscapeED->text());
1542 rc.print_to_file = internal_path(fromqstr(printerToFileED->text()));
1543 rc.print_extra_options = fromqstr(printerExtraED->text());
1544 rc.print_spool_printerprefix = fromqstr(printerSpoolPrefixED->text());
1545 rc.print_paper_dimension_flag = fromqstr(printerPaperSizeED->text());
1549 void PrefPrinter::update(LyXRC const & rc)
1551 printerAdaptCB->setChecked(rc.print_adapt_output);
1552 printerCommandED->setText(toqstr(rc.print_command));
1553 printerNameED->setText(toqstr(rc.printer));
1555 printerPageRangeED->setText(toqstr(rc.print_pagerange_flag));
1556 printerCopiesED->setText(toqstr(rc.print_copies_flag));
1557 printerReverseED->setText(toqstr(rc.print_reverse_flag));
1558 printerToPrinterED->setText(toqstr(rc.print_to_printer));
1559 printerExtensionED->setText(toqstr(rc.print_file_extension));
1560 printerSpoolCommandED->setText(toqstr(rc.print_spool_command));
1561 printerPaperTypeED->setText(toqstr(rc.print_paper_flag));
1562 printerEvenED->setText(toqstr(rc.print_evenpage_flag));
1563 printerOddED->setText(toqstr(rc.print_oddpage_flag));
1564 printerCollatedED->setText(toqstr(rc.print_collcopies_flag));
1565 printerLandscapeED->setText(toqstr(rc.print_landscape_flag));
1566 printerToFileED->setText(toqstr(external_path(rc.print_to_file)));
1567 printerExtraED->setText(toqstr(rc.print_extra_options));
1568 printerSpoolPrefixED->setText(toqstr(rc.print_spool_printerprefix));
1569 printerPaperSizeED->setText(toqstr(rc.print_paper_dimension_flag));
1573 /////////////////////////////////////////////////////////////////////
1575 // PrefUserInterface
1577 /////////////////////////////////////////////////////////////////////
1579 PrefUserInterface::PrefUserInterface(GuiPreferences * form, QWidget * parent)
1580 : PrefModule(_("User interface"), form, parent)
1584 connect(autoSaveCB, SIGNAL(toggled(bool)),
1585 autoSaveSB, SLOT(setEnabled(bool)));
1586 connect(autoSaveCB, SIGNAL(toggled(bool)),
1587 TextLabel1, SLOT(setEnabled(bool)));
1588 connect(uiFilePB, SIGNAL(clicked()),
1589 this, SLOT(select_ui()));
1590 connect(uiFileED, SIGNAL(textChanged(const QString &)),
1591 this, SIGNAL(changed()));
1592 connect(restoreCursorCB, SIGNAL(clicked()),
1593 this, SIGNAL(changed()));
1594 connect(loadSessionCB, SIGNAL(clicked()),
1595 this, SIGNAL(changed()));
1596 connect(loadWindowSizeCB, SIGNAL(clicked()),
1597 this, SIGNAL(changed()));
1598 connect(loadWindowLocationCB, SIGNAL(clicked()),
1599 this, SIGNAL(changed()));
1600 connect(windowWidthSB, SIGNAL(valueChanged(int)),
1601 this, SIGNAL(changed()));
1602 connect(windowHeightSB, SIGNAL(valueChanged(int)),
1603 this, SIGNAL(changed()));
1604 connect(cursorFollowsCB, SIGNAL(clicked()),
1605 this, SIGNAL(changed()));
1606 connect(autoSaveSB, SIGNAL(valueChanged(int)),
1607 this, SIGNAL(changed()));
1608 connect(autoSaveCB, SIGNAL(clicked()),
1609 this, SIGNAL(changed()));
1610 connect(lastfilesSB, SIGNAL(valueChanged(int)),
1611 this, SIGNAL(changed()));
1612 lastfilesSB->setMaximum(maxlastfiles);
1616 void PrefUserInterface::apply(LyXRC & rc) const
1618 rc.ui_file = internal_path(fromqstr(uiFileED->text()));
1619 rc.use_lastfilepos = restoreCursorCB->isChecked();
1620 rc.load_session = loadSessionCB->isChecked();
1621 if (loadWindowSizeCB->isChecked()) {
1622 rc.geometry_width = 0;
1623 rc.geometry_height = 0;
1625 rc.geometry_width = windowWidthSB->value();
1626 rc.geometry_height = windowHeightSB->value();
1628 rc.geometry_xysaved = loadWindowLocationCB->isChecked();
1629 rc.cursor_follows_scrollbar = cursorFollowsCB->isChecked();
1630 rc.autosave = autoSaveSB->value() * 60;
1631 rc.make_backup = autoSaveCB->isChecked();
1632 rc.num_lastfiles = lastfilesSB->value();
1636 void PrefUserInterface::update(LyXRC const & rc)
1638 uiFileED->setText(toqstr(external_path(rc.ui_file)));
1639 restoreCursorCB->setChecked(rc.use_lastfilepos);
1640 loadSessionCB->setChecked(rc.load_session);
1641 bool loadWindowSize = rc.geometry_width == 0 && rc.geometry_height == 0;
1642 loadWindowSizeCB->setChecked(loadWindowSize);
1643 if (!loadWindowSize) {
1644 windowWidthSB->setValue(rc.geometry_width);
1645 windowHeightSB->setValue(rc.geometry_height);
1647 loadWindowLocationCB->setChecked(rc.geometry_xysaved);
1648 cursorFollowsCB->setChecked(rc.cursor_follows_scrollbar);
1649 // convert to minutes
1650 int mins(rc.autosave / 60);
1651 if (rc.autosave && !mins)
1653 autoSaveSB->setValue(mins);
1654 autoSaveCB->setChecked(rc.make_backup);
1655 lastfilesSB->setValue(rc.num_lastfiles);
1659 void PrefUserInterface::select_ui()
1661 docstring const name =
1662 from_utf8(internal_path(fromqstr(uiFileED->text())));
1663 docstring file = form_->browseUI(name);
1665 uiFileED->setText(toqstr(file));
1669 void PrefUserInterface::on_loadWindowSizeCB_toggled(bool loadwindowsize)
1671 windowWidthLA->setDisabled(loadwindowsize);
1672 windowHeightLA->setDisabled(loadwindowsize);
1673 windowWidthSB->setDisabled(loadwindowsize);
1674 windowHeightSB->setDisabled(loadwindowsize);
1678 /////////////////////////////////////////////////////////////////////
1682 /////////////////////////////////////////////////////////////////////
1684 PrefShortcuts::PrefShortcuts(GuiPreferences * form, QWidget * parent)
1685 : PrefModule(_("Shortcuts"), form, parent)
1689 shortcutsTW->setColumnCount(3);
1690 shortcutsTW->headerItem()->setText(0, qt_(""));
1691 shortcutsTW->headerItem()->setText(1, qt_("Function"));
1692 shortcutsTW->headerItem()->setText(2, qt_("Shortcut"));
1693 shortcutsTW->setSortingEnabled(false);
1695 connect(bindFilePB, SIGNAL(clicked()),
1696 this, SLOT(select_bind()));
1697 connect(bindFileED, SIGNAL(textChanged(const QString &)),
1698 this, SIGNAL(changed()));
1702 void PrefShortcuts::apply(LyXRC & rc) const
1704 rc.bind_file = internal_path(fromqstr(bindFileED->text()));
1708 void PrefShortcuts::update(LyXRC const & rc)
1710 bindFileED->setText(toqstr(external_path(rc.bind_file)));
1712 KeyMap & km = theTopLevelKeymap();
1713 KeyMap::Table::const_iterator it = km.begin();
1714 KeyMap::Table::const_iterator it_end = km.end();
1715 for (; it != it_end; ++it) {
1716 QTreeWidgetItem * newItem = new QTreeWidgetItem(shortcutsTW);
1717 string const action = lyxaction.getActionName(it->func.action);
1718 if (action == "self-insert")
1720 QString const lfun = toqstr(from_utf8(action) + " " + it->func.argument());
1721 QString const shortcut = toqstr(it->code.print(it->mod.first, true));
1722 newItem->setText(1, lfun);
1723 newItem->setText(2, shortcut);
1724 // FIXME: TreeItem can not be user-checkable?
1725 newItem->setFlags(newItem->flags() | Qt::ItemIsEditable
1726 | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable);
1731 void PrefShortcuts::select_bind()
1733 docstring const name =
1734 from_utf8(internal_path(fromqstr(bindFileED->text())));
1735 docstring file = form_->browsebind(name);
1737 bindFileED->setText(toqstr(file));
1741 PrefIdentity::PrefIdentity(QWidget * parent)
1742 : PrefModule(_("Identity"), 0, parent)
1746 connect(nameED, SIGNAL(textChanged(const QString&)),
1747 this, SIGNAL(changed()));
1748 connect(emailED, SIGNAL(textChanged(const QString&)),
1749 this, SIGNAL(changed()));
1753 void PrefIdentity::apply(LyXRC & rc) const
1755 rc.user_name = fromqstr(nameED->text());
1756 rc.user_email = fromqstr(emailED->text());
1760 void PrefIdentity::update(LyXRC const & rc)
1762 nameED->setText(toqstr(rc.user_name));
1763 emailED->setText(toqstr(rc.user_email));
1768 /////////////////////////////////////////////////////////////////////
1772 /////////////////////////////////////////////////////////////////////
1774 GuiPreferences::GuiPreferences(LyXView & lv)
1775 : GuiDialog(lv, "prefs"), update_screen_font_(false)
1778 setViewTitle(_("Preferences"));
1780 QDialog::setModal(false);
1782 connect(savePB, SIGNAL(clicked()), this, SLOT(slotOK()));
1783 connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
1784 connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
1785 connect(restorePB, SIGNAL(clicked()), this, SLOT(slotRestore()));
1787 add(new PrefUserInterface(this));
1788 add(new PrefShortcuts(this));
1789 add(new PrefScreenFonts(this));
1790 add(new PrefColors(this));
1791 add(new PrefDisplay);
1792 add(new PrefKeyboard(this));
1794 add(new PrefPaths(this));
1796 add(new PrefIdentity);
1798 add(new PrefLanguage);
1799 add(new PrefSpellchecker(this));
1801 add(new PrefPrinter);
1803 add(new PrefPlaintext);
1804 add(new PrefLatex(this));
1806 PrefConverters * converters = new PrefConverters(this);
1807 PrefFileformats * formats = new PrefFileformats(this);
1808 connect(formats, SIGNAL(formatsChanged()),
1809 converters, SLOT(updateGui()));
1813 prefsPS->setCurrentPanel(_("User interface"));
1814 // FIXME: hack to work around resizing bug in Qt >= 4.2
1815 // bug verified with Qt 4.2.{0-3} (JSpitzm)
1816 #if QT_VERSION >= 0x040200
1817 prefsPS->updateGeometry();
1820 bc().setPolicy(ButtonPolicy::PreferencesPolicy);
1822 bc().setApply(applyPB);
1823 bc().setCancel(closePB);
1824 bc().setRestore(restorePB);
1828 void GuiPreferences::add(PrefModule * module)
1830 BOOST_ASSERT(module);
1831 prefsPS->addPanel(module, module->title());
1832 connect(module, SIGNAL(changed()), this, SLOT(change_adaptor()));
1833 modules_.push_back(module);
1837 void GuiPreferences::closeEvent(QCloseEvent * e)
1844 void GuiPreferences::change_adaptor()
1850 void GuiPreferences::apply(LyXRC & rc) const
1852 size_t end = modules_.size();
1853 for (size_t i = 0; i != end; ++i)
1854 modules_[i]->apply(rc);
1858 void GuiPreferences::updateRc(LyXRC const & rc)
1860 size_t const end = modules_.size();
1861 for (size_t i = 0; i != end; ++i)
1862 modules_[i]->update(rc);
1866 void GuiPreferences::applyView()
1872 void GuiPreferences::updateContents()
1878 bool GuiPreferences::initialiseParams(std::string const &)
1881 formats_ = lyx::formats;
1882 converters_ = theConverters();
1883 converters_.update(formats_);
1884 movers_ = theMovers();
1886 update_screen_font_ = false;
1892 void GuiPreferences::dispatchParams()
1895 rc_.write(ss, true);
1896 dispatch(FuncRequest(LFUN_LYXRC_APPLY, ss.str()));
1897 // FIXME: these need lfuns
1899 theBufferList().setCurrentAuthor(from_utf8(rc_.user_name), from_utf8(rc_.user_email));
1901 lyx::formats = formats_;
1903 theConverters() = converters_;
1904 theConverters().update(lyx::formats);
1905 theConverters().buildGraph();
1907 theMovers() = movers_;
1909 vector<string>::const_iterator it = colors_.begin();
1910 vector<string>::const_iterator const end = colors_.end();
1911 for (; it != end; ++it)
1912 dispatch(FuncRequest(LFUN_SET_COLOR, *it));
1915 if (update_screen_font_) {
1916 dispatch(FuncRequest(LFUN_SCREEN_FONT_UPDATE));
1917 update_screen_font_ = false;
1920 // The Save button has been pressed
1922 dispatch(FuncRequest(LFUN_PREFERENCES_SAVE));
1926 void GuiPreferences::setColor(Color_color col, string const & hex)
1928 colors_.push_back(lcolor.getLyXName(col) + ' ' + hex);
1932 void GuiPreferences::updateScreenFonts()
1934 update_screen_font_ = true;
1938 docstring const GuiPreferences::browsebind(docstring const & file) const
1940 return browseLibFile(from_ascii("bind"), file, from_ascii("bind"),
1941 _("Choose bind file"),
1942 FileFilterList(_("LyX bind files (*.bind)")));
1946 docstring const GuiPreferences::browseUI(docstring const & file) const
1948 return browseLibFile(from_ascii("ui"), file, from_ascii("ui"),
1949 _("Choose UI file"),
1950 FileFilterList(_("LyX UI files (*.ui)")));
1954 docstring const GuiPreferences::browsekbmap(docstring const & file) const
1956 return browseLibFile(from_ascii("kbd"), file, from_ascii("kmap"),
1957 _("Choose keyboard map"),
1958 FileFilterList(_("LyX keyboard maps (*.kmap)")));
1962 docstring const GuiPreferences::browsedict(docstring const & file) const
1964 if (lyxrc.use_spell_lib)
1965 return browseFile(file,
1966 _("Choose personal dictionary"),
1967 FileFilterList(_("*.pws")));
1969 return browseFile(file,
1970 _("Choose personal dictionary"),
1971 FileFilterList(_("*.ispell")));
1975 docstring const GuiPreferences::browse(docstring const & file,
1976 docstring const & title) const
1978 return browseFile(file, title, FileFilterList(), true);
1982 docstring const GuiPreferences::browsedir(docstring const & path,
1983 docstring const & title) const
1985 return browseDir(path, title);
1989 // We support less paper sizes than the document dialog
1990 // Therefore this adjustment is needed.
1991 PAPER_SIZE GuiPreferences::toPaperSize(int i) const
1995 return PAPER_DEFAULT;
1997 return PAPER_USLETTER;
1999 return PAPER_USLEGAL;
2001 return PAPER_USEXECUTIVE;
2011 // should not happen
2012 return PAPER_DEFAULT;
2017 int GuiPreferences::fromPaperSize(PAPER_SIZE papersize) const
2019 switch (papersize) {
2022 case PAPER_USLETTER:
2026 case PAPER_USEXECUTIVE:
2037 // should not happen
2043 Dialog * createGuiPreferences(LyXView & lv) { return new GuiPreferences(lv); }
2046 } // namespace frontend
2049 #include "GuiPrefs_moc.cpp"