3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
9 * Full author contact details are available in file CREDITS.
16 #include "ColorCache.h"
17 #include "FileDialog.h"
18 #include "GuiApplication.h"
19 #include "GuiFontExample.h"
20 #include "GuiFontLoader.h"
21 #include "GuiKeySymbol.h"
22 #include "qt_helpers.h"
23 #include "Validator.h"
26 #include "BufferList.h"
29 #include "ConverterCache.h"
30 #include "FontEnums.h"
31 #include "FuncRequest.h"
33 #include "KeySequence.h"
35 #include "LyXAction.h"
37 #include "PanelStack.h"
39 #include "SpellChecker.h"
41 #include "support/debug.h"
42 #include "support/FileName.h"
43 #include "support/filetools.h"
44 #include "support/gettext.h"
45 #include "support/lassert.h"
46 #include "support/lstrings.h"
47 #include "support/Messages.h"
48 #include "support/os.h"
49 #include "support/Package.h"
51 #include "graphics/GraphicsTypes.h"
53 #include "frontends/alert.h"
54 #include "frontends/Application.h"
55 #include "frontends/FontLoader.h"
57 #include <QAbstractItemModel>
59 #include <QColorDialog>
60 #include <QFontDatabase>
61 #include <QHeaderView>
63 #include <QMessageBox>
64 #include <QPixmapCache>
65 #include <QPushButton>
68 #include <QTreeWidget>
69 #include <QTreeWidgetItem>
80 using namespace lyx::support;
81 using namespace lyx::support::os;
86 /////////////////////////////////////////////////////////////////////
90 /////////////////////////////////////////////////////////////////////
92 /** Launch a file dialog and return the chosen file.
93 filename: a suggested filename.
94 title: the title of the dialog.
96 dir1 = (name, dir), dir2 = (name, dir): extra buttons on the dialog.
98 QString browseFile(QString const & filename,
99 QString const & title,
100 QStringList const & filters,
102 QString const & label1 = QString(),
103 QString const & dir1 = QString(),
104 QString const & label2 = QString(),
105 QString const & dir2 = QString(),
106 QString const & fallback_dir = QString())
108 QString lastPath = ".";
109 if (!filename.isEmpty())
110 lastPath = onlyPath(filename);
111 else if(!fallback_dir.isEmpty())
112 lastPath = fallback_dir;
114 FileDialog dlg(title);
115 dlg.setButton1(label1, dir1);
116 dlg.setButton2(label2, dir2);
118 FileDialog::Result result;
121 result = dlg.save(lastPath, filters, onlyFileName(filename));
123 result = dlg.open(lastPath, filters, onlyFileName(filename));
125 return result.second;
129 /** Wrapper around browseFile which tries to provide a filename
130 * relative to the user or system directory. The dir, name and ext
131 * parameters have the same meaning as in the
132 * support::LibFileSearch function.
134 QString browseLibFile(QString const & dir,
135 QString const & name,
137 QString const & title,
138 QStringList const & filters)
141 QString const label1 = qt_("&System files");
143 toqstr(addName(package().system_support().absFileName(), fromqstr(dir)));
145 QString const label2 = qt_("&User files");
147 toqstr(addName(package().user_support().absFileName(), fromqstr(dir)));
149 QString const result = browseFile(toqstr(
150 libFileSearch(dir, name, ext).absFileName()),
151 title, filters, false, dir1, dir2, QString(), QString(), dir1);
153 // remove the extension if it is the default one
155 if (getExtension(result) == ext)
156 noextresult = removeExtension(result);
158 noextresult = result;
160 // remove the directory, if it is the default one
161 QString const file = onlyFileName(noextresult);
162 if (toqstr(libFileSearch(dir, file, ext).absFileName()) == result)
169 /** Launch a file dialog and return the chosen directory.
170 pathname: a suggested pathname.
171 title: the title of the dialog.
172 dir1 = (name, dir), dir2 = (name, dir): extra buttons on the dialog.
174 QString browseDir(QString const & pathname,
175 QString const & title,
176 QString const & label1 = QString(),
177 QString const & dir1 = QString(),
178 QString const & label2 = QString(),
179 QString const & dir2 = QString())
181 QString lastPath = ".";
182 if (!pathname.isEmpty())
183 lastPath = onlyPath(pathname);
185 FileDialog dlg(title);
186 dlg.setButton1(label1, dir1);
187 dlg.setButton2(label2, dir2);
189 FileDialog::Result const result =
190 dlg.opendir(lastPath, onlyFileName(pathname));
192 return result.second;
196 } // namespace frontend
199 QString browseRelToParent(QString const & filename, QString const & relpath,
200 QString const & title, QStringList const & filters, bool save,
201 QString const & label1, QString const & dir1,
202 QString const & label2, QString const & dir2)
204 QString const fname = makeAbsPath(filename, relpath);
206 QString const outname =
207 frontend::browseFile(fname, title, filters, save, label1, dir1, label2, dir2);
209 QString const reloutname =
210 toqstr(makeRelPath(qstring_to_ucs4(outname), qstring_to_ucs4(relpath)));
212 if (reloutname.startsWith("../"))
219 QString browseRelToSub(QString const & filename, QString const & relpath,
220 QString const & title, QStringList const & filters, bool save,
221 QString const & label1, QString const & dir1,
222 QString const & label2, QString const & dir2)
224 QString const fname = makeAbsPath(filename, relpath);
226 QString const outname =
227 frontend::browseFile(fname, title, filters, save, label1, dir1, label2, dir2);
229 QString const reloutname =
230 toqstr(makeRelPath(qstring_to_ucs4(outname), qstring_to_ucs4(relpath)));
232 QString testname = reloutname;
233 testname.remove(QRegExp("^(\\.\\./)+"));
235 if (testname.contains("/"))
243 /////////////////////////////////////////////////////////////////////
247 /////////////////////////////////////////////////////////////////////
251 QString const catLookAndFeel = N_("Look & Feel");
252 QString const catEditing = N_("Editing");
253 QString const catLanguage = N_("Language Settings");
254 QString const catOutput = N_("Output");
255 QString const catFiles = N_("File Handling");
257 static void parseFontName(QString const & mangled0,
258 string & name, string & foundry)
260 string mangled = fromqstr(mangled0);
261 size_t const idx = mangled.find('[');
262 if (idx == string::npos || idx == 0) {
266 name = mangled.substr(0, idx - 1),
267 foundry = mangled.substr(idx + 1, mangled.size() - idx - 2);
272 static void setComboxFont(QComboBox * cb, string const & family,
273 string const & foundry)
275 QString fontname = toqstr(family);
276 if (!foundry.empty())
277 fontname += " [" + toqstr(foundry) + ']';
279 for (int i = 0; i != cb->count(); ++i) {
280 if (cb->itemText(i) == fontname) {
281 cb->setCurrentIndex(i);
286 // Try matching without foundry name
288 // We count in reverse in order to prefer the Xft foundry
289 for (int i = cb->count(); --i >= 0;) {
290 string name, fnt_foundry;
291 parseFontName(cb->itemText(i), name, fnt_foundry);
292 if (compare_ascii_no_case(name, family) == 0) {
293 cb->setCurrentIndex(i);
298 // family alone can contain e.g. "Helvetica [Adobe]"
299 string tmpname, tmpfoundry;
300 parseFontName(toqstr(family), tmpname, tmpfoundry);
302 // We count in reverse in order to prefer the Xft foundry
303 for (int i = cb->count(); --i >= 0; ) {
304 string name, fnt_foundry;
305 parseFontName(cb->itemText(i), name, fnt_foundry);
306 if (compare_ascii_no_case(name, fnt_foundry) == 0) {
307 cb->setCurrentIndex(i);
312 // Bleh, default fonts, and the names couldn't be found. Hack
317 QString const font_family = toqstr(family);
318 if (font_family == guiApp->romanFontName()) {
319 font.setStyleHint(QFont::Serif);
320 font.setFamily(font_family);
321 } else if (font_family == guiApp->sansFontName()) {
322 font.setStyleHint(QFont::SansSerif);
323 font.setFamily(font_family);
324 } else if (font_family == guiApp->typewriterFontName()) {
325 font.setStyleHint(QFont::TypeWriter);
326 font.setFamily(font_family);
328 LYXERR0("FAILED to find the default font: '"
329 << foundry << "', '" << family << '\'');
333 QFontInfo info(font);
334 string default_font_name, dummyfoundry;
335 parseFontName(info.family(), default_font_name, dummyfoundry);
336 LYXERR0("Apparent font is " << default_font_name);
338 for (int i = 0; i < cb->count(); ++i) {
339 LYXERR0("Looking at " << cb->itemText(i));
340 if (compare_ascii_no_case(fromqstr(cb->itemText(i)),
341 default_font_name) == 0) {
342 cb->setCurrentIndex(i);
347 LYXERR0("FAILED to find the font: '"
348 << foundry << "', '" << family << '\'');
352 /////////////////////////////////////////////////////////////////////
356 /////////////////////////////////////////////////////////////////////
358 class StrftimeValidator : public QValidator
361 StrftimeValidator(QWidget *);
362 QValidator::State validate(QString & input, int & pos) const;
366 StrftimeValidator::StrftimeValidator(QWidget * parent)
372 QValidator::State StrftimeValidator::validate(QString & input, int & /*pos*/) const
374 if (is_valid_strftime(fromqstr(input)))
375 return QValidator::Acceptable;
377 return QValidator::Intermediate;
381 /////////////////////////////////////////////////////////////////////
385 /////////////////////////////////////////////////////////////////////
387 PrefOutput::PrefOutput(GuiPreferences * form)
388 : PrefModule(catOutput, N_("General"), form)
392 DateED->setValidator(new StrftimeValidator(DateED));
393 dviCB->setValidator(new NoNewLineValidator(dviCB));
394 pdfCB->setValidator(new NoNewLineValidator(pdfCB));
396 connect(DateED, SIGNAL(textChanged(QString)),
397 this, SIGNAL(changed()));
398 connect(plaintextLinelengthSB, SIGNAL(valueChanged(int)),
399 this, SIGNAL(changed()));
400 connect(overwriteCO, SIGNAL(activated(int)),
401 this, SIGNAL(changed()));
402 connect(dviCB, SIGNAL(editTextChanged(QString)),
403 this, SIGNAL(changed()));
404 connect(pdfCB, SIGNAL(editTextChanged(QString)),
405 this, SIGNAL(changed()));
406 connect(printerPaperTypeED, SIGNAL(textChanged(QString)),
407 this, SIGNAL(changed()));
408 connect(printerLandscapeED, SIGNAL(textChanged(QString)),
409 this, SIGNAL(changed()));
410 connect(printerPaperSizeED, SIGNAL(textChanged(QString)),
411 this, SIGNAL(changed()));
413 printerPaperTypeED->setValidator(new NoNewLineValidator(printerPaperTypeED));
414 printerLandscapeED->setValidator(new NoNewLineValidator(printerLandscapeED));
415 printerPaperSizeED->setValidator(new NoNewLineValidator(printerPaperSizeED));
418 dviCB->addItem("xdvi -sourceposition '$$n:\\ $$t' $$o");
419 dviCB->addItem("yap -1 -s \"$$n $$t\" $$o");
420 dviCB->addItem("okular --unique \"$$o#src:$$n $$f\"");
421 dviCB->addItem("synctex view -i $$n:0:$$t -o $$o -x \"evince -i %{page+1} $$o\"");
423 pdfCB->addItem("CMCDDE SUMATRA control [ForwardSearch(\\\"$$o\\\",\\\"$$t\\\",$$n,0,0,1)]");
424 pdfCB->addItem("SumatraPDF -reuse-instance \"$$o\" -forward-search \"$$t\" $$n");
425 pdfCB->addItem("synctex view -i $$n:0:$$t -o $$o -x \"xpdf -raise -remote $$t.tmp $$o %{page+1}\"");
426 pdfCB->addItem("okular --unique \"$$o#src:$$n $$f\"");
427 pdfCB->addItem("qpdfview --unique \"$$o#src:$$f:$$n:0\"");
428 pdfCB->addItem("synctex view -i $$n:0:$$t -o $$o -x \"evince -i %{page+1} $$o\"");
429 pdfCB->addItem("/Applications/Skim.app/Contents/SharedSupport/displayline $$n $$o $$t");
433 void PrefOutput::on_DateED_textChanged(const QString &)
435 QString t = DateED->text();
437 bool valid = DateED->validator()->validate(t, p)
438 == QValidator::Acceptable;
439 setValid(DateLA, valid);
443 void PrefOutput::applyRC(LyXRC & rc) const
445 rc.date_insert_format = fromqstr(DateED->text());
446 rc.plaintext_linelen = plaintextLinelengthSB->value();
447 rc.forward_search_dvi = fromqstr(dviCB->currentText());
448 rc.forward_search_pdf = fromqstr(pdfCB->currentText());
450 switch (overwriteCO->currentIndex()) {
452 rc.export_overwrite = NO_FILES;
455 rc.export_overwrite = MAIN_FILE;
458 rc.export_overwrite = ALL_FILES;
462 rc.print_paper_flag = fromqstr(printerPaperTypeED->text());
463 rc.print_landscape_flag = fromqstr(printerLandscapeED->text());
464 rc.print_paper_dimension_flag = fromqstr(printerPaperSizeED->text());
468 void PrefOutput::updateRC(LyXRC const & rc)
470 DateED->setText(toqstr(rc.date_insert_format));
471 plaintextLinelengthSB->setValue(rc.plaintext_linelen);
472 dviCB->setEditText(toqstr(rc.forward_search_dvi));
473 pdfCB->setEditText(toqstr(rc.forward_search_pdf));
475 switch (rc.export_overwrite) {
477 overwriteCO->setCurrentIndex(0);
480 overwriteCO->setCurrentIndex(1);
483 overwriteCO->setCurrentIndex(2);
487 printerPaperTypeED->setText(toqstr(rc.print_paper_flag));
488 printerLandscapeED->setText(toqstr(rc.print_landscape_flag));
489 printerPaperSizeED->setText(toqstr(rc.print_paper_dimension_flag));
493 /////////////////////////////////////////////////////////////////////
497 /////////////////////////////////////////////////////////////////////
499 PrefInput::PrefInput(GuiPreferences * form)
500 : PrefModule(catEditing, N_("Keyboard/Mouse"), form)
504 connect(keymapCB, SIGNAL(clicked()),
505 this, SIGNAL(changed()));
506 connect(firstKeymapED, SIGNAL(textChanged(QString)),
507 this, SIGNAL(changed()));
508 connect(secondKeymapED, SIGNAL(textChanged(QString)),
509 this, SIGNAL(changed()));
510 connect(mouseWheelSpeedSB, SIGNAL(valueChanged(double)),
511 this, SIGNAL(changed()));
512 connect(scrollzoomEnableCB, SIGNAL(clicked()),
513 this, SIGNAL(changed()));
514 connect(scrollzoomValueCO, SIGNAL(activated(int)),
515 this, SIGNAL(changed()));
516 connect(dontswapCB, SIGNAL(toggled(bool)),
517 this, SIGNAL(changed()));
518 connect(mmPasteCB, SIGNAL(toggled(bool)),
519 this, SIGNAL(changed()));
521 // reveal checkbox for switching Ctrl and Meta on Mac:
524 #if QT_VERSION > 0x040600
528 dontswapCB->setVisible(swapcb);
532 void PrefInput::applyRC(LyXRC & rc) const
534 // FIXME: can derive CB from the two EDs
535 rc.use_kbmap = keymapCB->isChecked();
536 rc.primary_kbmap = internal_path(fromqstr(firstKeymapED->text()));
537 rc.secondary_kbmap = internal_path(fromqstr(secondKeymapED->text()));
538 rc.mouse_wheel_speed = mouseWheelSpeedSB->value();
539 if (scrollzoomEnableCB->isChecked()) {
540 switch (scrollzoomValueCO->currentIndex()) {
542 rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_CTRL;
545 rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_SHIFT;
548 rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_ALT;
552 rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_OFF;
554 rc.mac_dontswap_ctrl_meta = dontswapCB->isChecked();
555 rc.mouse_middlebutton_paste = mmPasteCB->isChecked();
559 void PrefInput::updateRC(LyXRC const & rc)
561 // FIXME: can derive CB from the two EDs
562 keymapCB->setChecked(rc.use_kbmap);
563 firstKeymapED->setText(toqstr(external_path(rc.primary_kbmap)));
564 secondKeymapED->setText(toqstr(external_path(rc.secondary_kbmap)));
565 mouseWheelSpeedSB->setValue(rc.mouse_wheel_speed);
566 switch (rc.scroll_wheel_zoom) {
567 case LyXRC::SCROLL_WHEEL_ZOOM_OFF:
568 scrollzoomEnableCB->setChecked(false);
570 case LyXRC::SCROLL_WHEEL_ZOOM_CTRL:
571 scrollzoomEnableCB->setChecked(true);
572 scrollzoomValueCO->setCurrentIndex(0);
574 case LyXRC::SCROLL_WHEEL_ZOOM_SHIFT:
575 scrollzoomEnableCB->setChecked(true);
576 scrollzoomValueCO->setCurrentIndex(1);
578 case LyXRC::SCROLL_WHEEL_ZOOM_ALT:
579 scrollzoomEnableCB->setChecked(true);
580 scrollzoomValueCO->setCurrentIndex(2);
583 dontswapCB->setChecked(rc.mac_dontswap_ctrl_meta);
584 mmPasteCB->setChecked(rc.mouse_middlebutton_paste);
588 QString PrefInput::testKeymap(QString const & keymap)
590 return form_->browsekbmap(internalPath(keymap));
594 void PrefInput::on_firstKeymapPB_clicked(bool)
596 QString const file = testKeymap(firstKeymapED->text());
598 firstKeymapED->setText(file);
602 void PrefInput::on_secondKeymapPB_clicked(bool)
604 QString const file = testKeymap(secondKeymapED->text());
606 secondKeymapED->setText(file);
610 void PrefInput::on_keymapCB_toggled(bool keymap)
612 firstKeymapLA->setEnabled(keymap);
613 secondKeymapLA->setEnabled(keymap);
614 firstKeymapED->setEnabled(keymap);
615 secondKeymapED->setEnabled(keymap);
616 firstKeymapPB->setEnabled(keymap);
617 secondKeymapPB->setEnabled(keymap);
621 void PrefInput::on_scrollzoomEnableCB_toggled(bool enabled)
623 scrollzoomValueCO->setEnabled(enabled);
627 /////////////////////////////////////////////////////////////////////
631 /////////////////////////////////////////////////////////////////////
633 PrefCompletion::PrefCompletion(GuiPreferences * form)
634 : PrefModule(catEditing, N_("Input Completion"), form)
638 connect(inlineDelaySB, SIGNAL(valueChanged(double)),
639 this, SIGNAL(changed()));
640 connect(inlineMathCB, SIGNAL(clicked()),
641 this, SIGNAL(changed()));
642 connect(inlineTextCB, SIGNAL(clicked()),
643 this, SIGNAL(changed()));
644 connect(inlineDotsCB, SIGNAL(clicked()),
645 this, SIGNAL(changed()));
646 connect(popupDelaySB, SIGNAL(valueChanged(double)),
647 this, SIGNAL(changed()));
648 connect(popupMathCB, SIGNAL(clicked()),
649 this, SIGNAL(changed()));
650 connect(autocorrectionCB, SIGNAL(clicked()),
651 this, SIGNAL(changed()));
652 connect(popupTextCB, SIGNAL(clicked()),
653 this, SIGNAL(changed()));
654 connect(popupAfterCompleteCB, SIGNAL(clicked()),
655 this, SIGNAL(changed()));
656 connect(cursorTextCB, SIGNAL(clicked()),
657 this, SIGNAL(changed()));
658 connect(minlengthSB, SIGNAL(valueChanged(int)),
659 this, SIGNAL(changed()));
663 void PrefCompletion::on_inlineTextCB_clicked()
669 void PrefCompletion::on_popupTextCB_clicked()
675 void PrefCompletion::enableCB()
677 cursorTextCB->setEnabled(
678 popupTextCB->isChecked() || inlineTextCB->isChecked());
682 void PrefCompletion::applyRC(LyXRC & rc) const
684 rc.completion_inline_delay = inlineDelaySB->value();
685 rc.completion_inline_math = inlineMathCB->isChecked();
686 rc.completion_inline_text = inlineTextCB->isChecked();
687 rc.completion_inline_dots = inlineDotsCB->isChecked() ? 13 : -1;
688 rc.completion_popup_delay = popupDelaySB->value();
689 rc.completion_popup_math = popupMathCB->isChecked();
690 rc.autocorrection_math = autocorrectionCB->isChecked();
691 rc.completion_popup_text = popupTextCB->isChecked();
692 rc.completion_cursor_text = cursorTextCB->isChecked();
693 rc.completion_popup_after_complete =
694 popupAfterCompleteCB->isChecked();
695 rc.completion_minlength = minlengthSB->value();
699 void PrefCompletion::updateRC(LyXRC const & rc)
701 inlineDelaySB->setValue(rc.completion_inline_delay);
702 inlineMathCB->setChecked(rc.completion_inline_math);
703 inlineTextCB->setChecked(rc.completion_inline_text);
704 inlineDotsCB->setChecked(rc.completion_inline_dots != -1);
705 popupDelaySB->setValue(rc.completion_popup_delay);
706 popupMathCB->setChecked(rc.completion_popup_math);
707 autocorrectionCB->setChecked(rc.autocorrection_math);
708 popupTextCB->setChecked(rc.completion_popup_text);
709 cursorTextCB->setChecked(rc.completion_cursor_text);
710 popupAfterCompleteCB->setChecked(rc.completion_popup_after_complete);
712 minlengthSB->setValue(rc.completion_minlength);
717 /////////////////////////////////////////////////////////////////////
721 /////////////////////////////////////////////////////////////////////
723 PrefLatex::PrefLatex(GuiPreferences * form)
724 : PrefModule(catOutput, N_("LaTeX"), form)
728 latexDviPaperED->setValidator(new NoNewLineValidator(latexDviPaperED));
729 latexBibtexED->setValidator(new NoNewLineValidator(latexBibtexED));
730 latexJBibtexED->setValidator(new NoNewLineValidator(latexJBibtexED));
731 latexIndexED->setValidator(new NoNewLineValidator(latexIndexED));
732 latexJIndexED->setValidator(new NoNewLineValidator(latexJIndexED));
733 latexNomenclED->setValidator(new NoNewLineValidator(latexNomenclED));
734 latexChecktexED->setValidator(new NoNewLineValidator(latexChecktexED));
736 connect(latexChecktexED, SIGNAL(textChanged(QString)),
737 this, SIGNAL(changed()));
738 connect(latexBibtexCO, SIGNAL(activated(int)),
739 this, SIGNAL(changed()));
740 connect(latexBibtexED, SIGNAL(textChanged(QString)),
741 this, SIGNAL(changed()));
742 connect(latexJBibtexCO, SIGNAL(activated(int)),
743 this, SIGNAL(changed()));
744 connect(latexJBibtexED, SIGNAL(textChanged(QString)),
745 this, SIGNAL(changed()));
746 connect(latexIndexCO, SIGNAL(activated(int)),
747 this, SIGNAL(changed()));
748 connect(latexIndexED, SIGNAL(textChanged(QString)),
749 this, SIGNAL(changed()));
750 connect(latexJIndexED, SIGNAL(textChanged(QString)),
751 this, SIGNAL(changed()));
752 connect(latexAutoresetCB, SIGNAL(clicked()),
753 this, SIGNAL(changed()));
754 connect(latexDviPaperED, SIGNAL(textChanged(QString)),
755 this, SIGNAL(changed()));
756 connect(latexNomenclED, SIGNAL(textChanged(QString)),
757 this, SIGNAL(changed()));
759 #if defined(__CYGWIN__) || defined(_WIN32)
760 pathCB->setVisible(true);
761 connect(pathCB, SIGNAL(clicked()),
762 this, SIGNAL(changed()));
764 pathCB->setVisible(false);
769 void PrefLatex::on_latexBibtexCO_activated(int n)
771 QString const bibtex = latexBibtexCO->itemData(n).toString();
772 if (bibtex.isEmpty()) {
773 latexBibtexED->clear();
774 latexBibtexOptionsLA->setText(qt_("C&ommand:"));
777 for (LyXRC::CommandSet::const_iterator it = bibtex_alternatives.begin();
778 it != bibtex_alternatives.end(); ++it) {
779 QString const bib = toqstr(*it);
780 int ind = bib.indexOf(" ");
781 QString sel_command = bib.left(ind);
782 QString sel_options = ind < 0 ? QString() : bib.mid(ind + 1);
783 if (bibtex == sel_command) {
785 latexBibtexED->clear();
787 latexBibtexED->setText(sel_options.trimmed());
790 latexBibtexOptionsLA->setText(qt_("&Options:"));
794 void PrefLatex::on_latexJBibtexCO_activated(int n)
796 QString const jbibtex = latexJBibtexCO->itemData(n).toString();
797 if (jbibtex.isEmpty()) {
798 latexJBibtexED->clear();
799 latexJBibtexOptionsLA->setText(qt_("Co&mmand:"));
802 for (LyXRC::CommandSet::const_iterator it = jbibtex_alternatives.begin();
803 it != jbibtex_alternatives.end(); ++it) {
804 QString const bib = toqstr(*it);
805 int ind = bib.indexOf(" ");
806 QString sel_command = bib.left(ind);
807 QString sel_options = ind < 0 ? QString() : bib.mid(ind + 1);
808 if (jbibtex == sel_command) {
810 latexJBibtexED->clear();
812 latexJBibtexED->setText(sel_options.trimmed());
815 latexJBibtexOptionsLA->setText(qt_("Opt&ions:"));
819 void PrefLatex::on_latexIndexCO_activated(int n)
821 QString const index = latexIndexCO->itemData(n).toString();
822 if (index.isEmpty()) {
823 latexIndexED->clear();
824 latexIndexOptionsLA->setText(qt_("Co&mmand:"));
827 for (LyXRC::CommandSet::const_iterator it = index_alternatives.begin();
828 it != index_alternatives.end(); ++it) {
829 QString const idx = toqstr(*it);
830 int ind = idx.indexOf(" ");
831 QString sel_command = idx.left(ind);
832 QString sel_options = ind < 0 ? QString() : idx.mid(ind + 1);
833 if (index == sel_command) {
835 latexIndexED->clear();
837 latexIndexED->setText(sel_options.trimmed());
840 latexIndexOptionsLA->setText(qt_("Op&tions:"));
844 void PrefLatex::applyRC(LyXRC & rc) const
846 // If bibtex is not empty, bibopt contains the options, otherwise
847 // it is a customized bibtex command with options.
848 QString const bibtex = latexBibtexCO->itemData(
849 latexBibtexCO->currentIndex()).toString();
850 QString const bibopt = latexBibtexED->text();
851 if (bibtex.isEmpty())
852 rc.bibtex_command = fromqstr(bibopt);
853 else if (bibopt.isEmpty())
854 rc.bibtex_command = fromqstr(bibtex);
856 rc.bibtex_command = fromqstr(bibtex) + " " + fromqstr(bibopt);
858 // If jbibtex is not empty, jbibopt contains the options, otherwise
859 // it is a customized bibtex command with options.
860 QString const jbibtex = latexJBibtexCO->itemData(
861 latexJBibtexCO->currentIndex()).toString();
862 QString const jbibopt = latexJBibtexED->text();
863 if (jbibtex.isEmpty())
864 rc.jbibtex_command = fromqstr(jbibopt);
865 else if (jbibopt.isEmpty())
866 rc.jbibtex_command = fromqstr(jbibtex);
868 rc.jbibtex_command = fromqstr(jbibtex) + " " + fromqstr(jbibopt);
870 // If index is not empty, idxopt contains the options, otherwise
871 // it is a customized index command with options.
872 QString const index = latexIndexCO->itemData(
873 latexIndexCO->currentIndex()).toString();
874 QString const idxopt = latexIndexED->text();
876 rc.index_command = fromqstr(idxopt);
877 else if (idxopt.isEmpty())
878 rc.index_command = fromqstr(index);
880 rc.index_command = fromqstr(index) + " " + fromqstr(idxopt);
882 rc.chktex_command = fromqstr(latexChecktexED->text());
883 rc.jindex_command = fromqstr(latexJIndexED->text());
884 rc.nomencl_command = fromqstr(latexNomenclED->text());
885 rc.auto_reset_options = latexAutoresetCB->isChecked();
886 rc.view_dvi_paper_option = fromqstr(latexDviPaperED->text());
887 #if defined(__CYGWIN__) || defined(_WIN32)
888 rc.windows_style_tex_paths = pathCB->isChecked();
893 void PrefLatex::updateRC(LyXRC const & rc)
895 latexBibtexCO->clear();
897 latexBibtexCO->addItem(qt_("Automatic"), "automatic");
898 latexBibtexCO->addItem(qt_("Custom"), QString());
899 for (LyXRC::CommandSet::const_iterator it = rc.bibtex_alternatives.begin();
900 it != rc.bibtex_alternatives.end(); ++it) {
901 QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
902 latexBibtexCO->addItem(command, command);
905 bibtex_alternatives = rc.bibtex_alternatives;
907 QString const bib = toqstr(rc.bibtex_command);
908 int ind = bib.indexOf(" ");
909 QString sel_command = bib.left(ind);
910 QString sel_options = ind < 0 ? QString() : bib.mid(ind + 1);
912 int pos = latexBibtexCO->findData(sel_command);
914 latexBibtexCO->setCurrentIndex(pos);
915 latexBibtexED->setText(sel_options.trimmed());
916 latexBibtexOptionsLA->setText(qt_("&Options:"));
918 latexBibtexED->setText(toqstr(rc.bibtex_command));
919 latexBibtexCO->setCurrentIndex(0);
920 latexBibtexOptionsLA->setText(qt_("C&ommand:"));
923 latexJBibtexCO->clear();
925 latexJBibtexCO->addItem(qt_("Automatic"), "automatic");
926 latexJBibtexCO->addItem(qt_("Custom"), QString());
927 for (LyXRC::CommandSet::const_iterator it = rc.jbibtex_alternatives.begin();
928 it != rc.jbibtex_alternatives.end(); ++it) {
929 QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
930 latexJBibtexCO->addItem(command, command);
933 jbibtex_alternatives = rc.jbibtex_alternatives;
935 QString const jbib = toqstr(rc.jbibtex_command);
936 ind = jbib.indexOf(" ");
937 sel_command = jbib.left(ind);
938 sel_options = ind < 0 ? QString() : jbib.mid(ind + 1);
940 pos = latexJBibtexCO->findData(sel_command);
942 latexJBibtexCO->setCurrentIndex(pos);
943 latexJBibtexED->setText(sel_options.trimmed());
944 latexJBibtexOptionsLA->setText(qt_("Opt&ions:"));
946 latexJBibtexED->setText(toqstr(rc.bibtex_command));
947 latexJBibtexCO->setCurrentIndex(0);
948 latexJBibtexOptionsLA->setText(qt_("Co&mmand:"));
951 latexIndexCO->clear();
953 latexIndexCO->addItem(qt_("Custom"), QString());
954 for (LyXRC::CommandSet::const_iterator it = rc.index_alternatives.begin();
955 it != rc.index_alternatives.end(); ++it) {
956 QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
957 latexIndexCO->addItem(command, command);
960 index_alternatives = rc.index_alternatives;
962 QString const idx = toqstr(rc.index_command);
963 ind = idx.indexOf(" ");
964 sel_command = idx.left(ind);
965 sel_options = ind < 0 ? QString() : idx.mid(ind + 1);
967 pos = latexIndexCO->findData(sel_command);
969 latexIndexCO->setCurrentIndex(pos);
970 latexIndexED->setText(sel_options.trimmed());
971 latexIndexOptionsLA->setText(qt_("Op&tions:"));
973 latexIndexED->setText(toqstr(rc.index_command));
974 latexIndexCO->setCurrentIndex(0);
975 latexIndexOptionsLA->setText(qt_("Co&mmand:"));
978 latexChecktexED->setText(toqstr(rc.chktex_command));
979 latexJIndexED->setText(toqstr(rc.jindex_command));
980 latexNomenclED->setText(toqstr(rc.nomencl_command));
981 latexAutoresetCB->setChecked(rc.auto_reset_options);
982 latexDviPaperED->setText(toqstr(rc.view_dvi_paper_option));
983 #if defined(__CYGWIN__) || defined(_WIN32)
984 pathCB->setChecked(rc.windows_style_tex_paths);
989 /////////////////////////////////////////////////////////////////////
993 /////////////////////////////////////////////////////////////////////
995 PrefScreenFonts::PrefScreenFonts(GuiPreferences * form)
996 : PrefModule(catLookAndFeel, N_("Screen Fonts"), form)
1000 connect(screenRomanCO, SIGNAL(activated(QString)),
1001 this, SLOT(selectRoman(QString)));
1002 connect(screenSansCO, SIGNAL(activated(QString)),
1003 this, SLOT(selectSans(QString)));
1004 connect(screenTypewriterCO, SIGNAL(activated(QString)),
1005 this, SLOT(selectTypewriter(QString)));
1007 QFontDatabase fontdb;
1008 QStringList families(fontdb.families());
1009 for (QStringList::Iterator it = families.begin(); it != families.end(); ++it) {
1010 screenRomanCO->addItem(*it);
1011 screenSansCO->addItem(*it);
1012 screenTypewriterCO->addItem(*it);
1014 connect(screenRomanCO, SIGNAL(activated(QString)),
1015 this, SIGNAL(changed()));
1016 connect(screenSansCO, SIGNAL(activated(QString)),
1017 this, SIGNAL(changed()));
1018 connect(screenTypewriterCO, SIGNAL(activated(QString)),
1019 this, SIGNAL(changed()));
1020 connect(screenZoomSB, SIGNAL(valueChanged(int)),
1021 this, SIGNAL(changed()));
1022 connect(screenTinyED, SIGNAL(textChanged(QString)),
1023 this, SIGNAL(changed()));
1024 connect(screenSmallestED, SIGNAL(textChanged(QString)),
1025 this, SIGNAL(changed()));
1026 connect(screenSmallerED, SIGNAL(textChanged(QString)),
1027 this, SIGNAL(changed()));
1028 connect(screenSmallED, SIGNAL(textChanged(QString)),
1029 this, SIGNAL(changed()));
1030 connect(screenNormalED, SIGNAL(textChanged(QString)),
1031 this, SIGNAL(changed()));
1032 connect(screenLargeED, SIGNAL(textChanged(QString)),
1033 this, SIGNAL(changed()));
1034 connect(screenLargerED, SIGNAL(textChanged(QString)),
1035 this, SIGNAL(changed()));
1036 connect(screenLargestED, SIGNAL(textChanged(QString)),
1037 this, SIGNAL(changed()));
1038 connect(screenHugeED, SIGNAL(textChanged(QString)),
1039 this, SIGNAL(changed()));
1040 connect(screenHugerED, SIGNAL(textChanged(QString)),
1041 this, SIGNAL(changed()));
1042 connect(pixmapCacheCB, SIGNAL(toggled(bool)),
1043 this, SIGNAL(changed()));
1045 screenTinyED->setValidator(new QDoubleValidator(screenTinyED));
1046 screenSmallestED->setValidator(new QDoubleValidator(screenSmallestED));
1047 screenSmallerED->setValidator(new QDoubleValidator(screenSmallerED));
1048 screenSmallED->setValidator(new QDoubleValidator(screenSmallED));
1049 screenNormalED->setValidator(new QDoubleValidator(screenNormalED));
1050 screenLargeED->setValidator(new QDoubleValidator(screenLargeED));
1051 screenLargerED->setValidator(new QDoubleValidator(screenLargerED));
1052 screenLargestED->setValidator(new QDoubleValidator(screenLargestED));
1053 screenHugeED->setValidator(new QDoubleValidator(screenHugeED));
1054 screenHugerED->setValidator(new QDoubleValidator(screenHugerED));
1058 void PrefScreenFonts::applyRC(LyXRC & rc) const
1060 LyXRC const oldrc = rc;
1062 parseFontName(screenRomanCO->currentText(),
1063 rc.roman_font_name, rc.roman_font_foundry);
1064 parseFontName(screenSansCO->currentText(),
1065 rc.sans_font_name, rc.sans_font_foundry);
1066 parseFontName(screenTypewriterCO->currentText(),
1067 rc.typewriter_font_name, rc.typewriter_font_foundry);
1069 rc.defaultZoom = screenZoomSB->value();
1070 rc.font_sizes[FONT_SIZE_TINY] = widgetToDoubleStr(screenTinyED);
1071 rc.font_sizes[FONT_SIZE_SCRIPT] = widgetToDoubleStr(screenSmallestED);
1072 rc.font_sizes[FONT_SIZE_FOOTNOTE] = widgetToDoubleStr(screenSmallerED);
1073 rc.font_sizes[FONT_SIZE_SMALL] = widgetToDoubleStr(screenSmallED);
1074 rc.font_sizes[FONT_SIZE_NORMAL] = widgetToDoubleStr(screenNormalED);
1075 rc.font_sizes[FONT_SIZE_LARGE] = widgetToDoubleStr(screenLargeED);
1076 rc.font_sizes[FONT_SIZE_LARGER] = widgetToDoubleStr(screenLargerED);
1077 rc.font_sizes[FONT_SIZE_LARGEST] = widgetToDoubleStr(screenLargestED);
1078 rc.font_sizes[FONT_SIZE_HUGE] = widgetToDoubleStr(screenHugeED);
1079 rc.font_sizes[FONT_SIZE_HUGER] = widgetToDoubleStr(screenHugerED);
1080 rc.use_pixmap_cache = pixmapCacheCB->isChecked();
1082 if (rc.font_sizes != oldrc.font_sizes
1083 || rc.roman_font_name != oldrc.roman_font_name
1084 || rc.sans_font_name != oldrc.sans_font_name
1085 || rc.typewriter_font_name != oldrc.typewriter_font_name
1086 || rc.defaultZoom != oldrc.defaultZoom) {
1087 // The global QPixmapCache is used in GuiPainter to cache text
1088 // painting so we must reset it in case any of the above
1089 // parameter is changed.
1090 QPixmapCache::clear();
1091 guiApp->fontLoader().update();
1092 form_->updateScreenFonts();
1097 void PrefScreenFonts::updateRC(LyXRC const & rc)
1099 setComboxFont(screenRomanCO, rc.roman_font_name,
1100 rc.roman_font_foundry);
1101 setComboxFont(screenSansCO, rc.sans_font_name,
1102 rc.sans_font_foundry);
1103 setComboxFont(screenTypewriterCO, rc.typewriter_font_name,
1104 rc.typewriter_font_foundry);
1106 selectRoman(screenRomanCO->currentText());
1107 selectSans(screenSansCO->currentText());
1108 selectTypewriter(screenTypewriterCO->currentText());
1110 screenZoomSB->setValue(rc.defaultZoom);
1111 updateScreenFontSizes(rc);
1113 pixmapCacheCB->setChecked(rc.use_pixmap_cache);
1114 #if defined(Q_WS_X11) || defined(QPA_XCB)
1115 pixmapCacheCB->setEnabled(false);
1121 void PrefScreenFonts::updateScreenFontSizes(LyXRC const & rc)
1123 doubleToWidget(screenTinyED, rc.font_sizes[FONT_SIZE_TINY]);
1124 doubleToWidget(screenSmallestED, rc.font_sizes[FONT_SIZE_SCRIPT]);
1125 doubleToWidget(screenSmallerED, rc.font_sizes[FONT_SIZE_FOOTNOTE]);
1126 doubleToWidget(screenSmallED, rc.font_sizes[FONT_SIZE_SMALL]);
1127 doubleToWidget(screenNormalED, rc.font_sizes[FONT_SIZE_NORMAL]);
1128 doubleToWidget(screenLargeED, rc.font_sizes[FONT_SIZE_LARGE]);
1129 doubleToWidget(screenLargerED, rc.font_sizes[FONT_SIZE_LARGER]);
1130 doubleToWidget(screenLargestED, rc.font_sizes[FONT_SIZE_LARGEST]);
1131 doubleToWidget(screenHugeED, rc.font_sizes[FONT_SIZE_HUGE]);
1132 doubleToWidget(screenHugerED, rc.font_sizes[FONT_SIZE_HUGER]);
1136 void PrefScreenFonts::selectRoman(const QString & name)
1138 screenRomanFE->set(QFont(name), name);
1142 void PrefScreenFonts::selectSans(const QString & name)
1144 screenSansFE->set(QFont(name), name);
1148 void PrefScreenFonts::selectTypewriter(const QString & name)
1150 screenTypewriterFE->set(QFont(name), name);
1154 /////////////////////////////////////////////////////////////////////
1158 /////////////////////////////////////////////////////////////////////
1161 PrefColors::PrefColors(GuiPreferences * form)
1162 : PrefModule(catLookAndFeel, N_("Colors"), form)
1166 // FIXME: all of this initialization should be put into the controller.
1167 // See http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg113301.html
1168 // for some discussion of why that is not trivial.
1169 QPixmap icon(32, 32);
1170 for (int i = 0; i < Color_ignore; ++i) {
1171 ColorCode lc = static_cast<ColorCode>(i);
1172 if (lc == Color_none
1173 || lc == Color_black
1174 || lc == Color_white
1176 || lc == Color_brown
1178 || lc == Color_darkgray
1180 || lc == Color_green
1181 || lc == Color_lightgray
1183 || lc == Color_magenta
1184 || lc == Color_olive
1185 || lc == Color_orange
1187 || lc == Color_purple
1190 || lc == Color_violet
1191 || lc == Color_yellow
1192 || lc == Color_inherit
1193 || lc == Color_ignore)
1195 lcolors_.push_back(lc);
1197 qSort(lcolors_.begin(), lcolors_.end(), ColorSorter);
1198 vector<ColorCode>::const_iterator cit = lcolors_.begin();
1199 vector<ColorCode>::const_iterator const end = lcolors_.end();
1200 for (; cit != end; ++cit) {
1201 (void) new QListWidgetItem(QIcon(icon),
1202 toqstr(lcolor.getGUIName(*cit)), lyxObjectsLW);
1204 curcolors_.resize(lcolors_.size());
1205 newcolors_.resize(lcolors_.size());
1206 // End initialization
1208 connect(colorChangePB, SIGNAL(clicked()),
1209 this, SLOT(changeColor()));
1210 connect(lyxObjectsLW, SIGNAL(itemSelectionChanged()),
1211 this, SLOT(changeLyxObjectsSelection()));
1212 connect(lyxObjectsLW, SIGNAL(itemActivated(QListWidgetItem*)),
1213 this, SLOT(changeColor()));
1214 connect(syscolorsCB, SIGNAL(toggled(bool)),
1215 this, SIGNAL(changed()));
1216 connect(syscolorsCB, SIGNAL(toggled(bool)),
1217 this, SLOT(changeSysColor()));
1221 void PrefColors::applyRC(LyXRC & rc) const
1225 for (unsigned int i = 0; i < lcolors_.size(); ++i)
1226 if (curcolors_[i] != newcolors_[i])
1227 form_->setColor(lcolors_[i], newcolors_[i]);
1228 rc.use_system_colors = syscolorsCB->isChecked();
1230 if (oldrc.use_system_colors != rc.use_system_colors)
1231 guiApp->colorCache().clear();
1235 void PrefColors::updateRC(LyXRC const & rc)
1237 for (unsigned int i = 0; i < lcolors_.size(); ++i) {
1238 QColor color = QColor(guiApp->colorCache().get(lcolors_[i], false));
1239 QPixmap coloritem(32, 32);
1240 coloritem.fill(color);
1241 lyxObjectsLW->item(i)->setIcon(QIcon(coloritem));
1242 newcolors_[i] = curcolors_[i] = color.name();
1244 syscolorsCB->setChecked(rc.use_system_colors);
1245 changeLyxObjectsSelection();
1249 void PrefColors::changeColor()
1251 int const row = lyxObjectsLW->currentRow();
1257 QString const color = newcolors_[row];
1258 QColor c = QColorDialog::getColor(QColor(color), qApp->focusWidget());
1260 if (c.isValid() && c.name() != color) {
1261 newcolors_[row] = c.name();
1262 QPixmap coloritem(32, 32);
1264 lyxObjectsLW->currentItem()->setIcon(QIcon(coloritem));
1270 void PrefColors::changeSysColor()
1272 for (int row = 0 ; row < lyxObjectsLW->count() ; ++row) {
1273 // skip colors that are taken from system palette
1274 bool const disable = syscolorsCB->isChecked()
1275 && guiApp->colorCache().isSystem(lcolors_[row]);
1277 QListWidgetItem * const item = lyxObjectsLW->item(row);
1278 Qt::ItemFlags const flags = item->flags();
1281 item->setFlags(flags & ~Qt::ItemIsEnabled);
1283 item->setFlags(flags | Qt::ItemIsEnabled);
1287 void PrefColors::changeLyxObjectsSelection()
1289 colorChangePB->setDisabled(lyxObjectsLW->currentRow() < 0);
1293 /////////////////////////////////////////////////////////////////////
1297 /////////////////////////////////////////////////////////////////////
1299 PrefDisplay::PrefDisplay(GuiPreferences * form)
1300 : PrefModule(catLookAndFeel, N_("Display"), form)
1303 connect(displayGraphicsCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1304 connect(instantPreviewCO, SIGNAL(activated(int)), this, SIGNAL(changed()));
1305 connect(previewSizeSB, SIGNAL(valueChanged(double)), this, SIGNAL(changed()));
1306 connect(paragraphMarkerCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1310 void PrefDisplay::on_instantPreviewCO_currentIndexChanged(int index)
1312 previewSizeSB->setEnabled(index != 0);
1316 void PrefDisplay::applyRC(LyXRC & rc) const
1318 switch (instantPreviewCO->currentIndex()) {
1320 rc.preview = LyXRC::PREVIEW_OFF;
1323 if (rc.preview != LyXRC::PREVIEW_NO_MATH) {
1324 rc.preview = LyXRC::PREVIEW_NO_MATH;
1325 form_->updatePreviews();
1329 if (rc.preview != LyXRC::PREVIEW_ON) {
1330 rc.preview = LyXRC::PREVIEW_ON;
1331 form_->updatePreviews();
1336 rc.display_graphics = displayGraphicsCB->isChecked();
1337 rc.preview_scale_factor = previewSizeSB->value();
1338 rc.paragraph_markers = paragraphMarkerCB->isChecked();
1340 // FIXME!! The graphics cache no longer has a changeDisplay method.
1342 if (old_value != rc.display_graphics) {
1343 graphics::GCache & gc = graphics::GCache::get();
1350 void PrefDisplay::updateRC(LyXRC const & rc)
1352 switch (rc.preview) {
1353 case LyXRC::PREVIEW_OFF:
1354 instantPreviewCO->setCurrentIndex(0);
1356 case LyXRC::PREVIEW_NO_MATH :
1357 instantPreviewCO->setCurrentIndex(1);
1359 case LyXRC::PREVIEW_ON :
1360 instantPreviewCO->setCurrentIndex(2);
1364 displayGraphicsCB->setChecked(rc.display_graphics);
1365 previewSizeSB->setValue(rc.preview_scale_factor);
1366 paragraphMarkerCB->setChecked(rc.paragraph_markers);
1367 previewSizeSB->setEnabled(
1369 && rc.preview != LyXRC::PREVIEW_OFF);
1373 /////////////////////////////////////////////////////////////////////
1377 /////////////////////////////////////////////////////////////////////
1379 PrefPaths::PrefPaths(GuiPreferences * form)
1380 : PrefModule(QString(), N_("Paths"), form)
1384 connect(workingDirPB, SIGNAL(clicked()), this, SLOT(selectWorkingdir()));
1385 connect(workingDirED, SIGNAL(textChanged(QString)),
1386 this, SIGNAL(changed()));
1388 connect(templateDirPB, SIGNAL(clicked()), this, SLOT(selectTemplatedir()));
1389 connect(templateDirED, SIGNAL(textChanged(QString)),
1390 this, SIGNAL(changed()));
1392 connect(exampleDirPB, SIGNAL(clicked()), this, SLOT(selectExampledir()));
1393 connect(exampleDirED, SIGNAL(textChanged(QString)),
1394 this, SIGNAL(changed()));
1396 connect(backupDirPB, SIGNAL(clicked()), this, SLOT(selectBackupdir()));
1397 connect(backupDirED, SIGNAL(textChanged(QString)),
1398 this, SIGNAL(changed()));
1400 connect(lyxserverDirPB, SIGNAL(clicked()), this, SLOT(selectLyxPipe()));
1401 connect(lyxserverDirED, SIGNAL(textChanged(QString)),
1402 this, SIGNAL(changed()));
1404 connect(thesaurusDirPB, SIGNAL(clicked()), this, SLOT(selectThesaurusdir()));
1405 connect(thesaurusDirED, SIGNAL(textChanged(QString)),
1406 this, SIGNAL(changed()));
1408 connect(tempDirPB, SIGNAL(clicked()), this, SLOT(selectTempdir()));
1409 connect(tempDirED, SIGNAL(textChanged(QString)),
1410 this, SIGNAL(changed()));
1412 #if defined(USE_HUNSPELL)
1413 connect(hunspellDirPB, SIGNAL(clicked()), this, SLOT(selectHunspelldir()));
1414 connect(hunspellDirED, SIGNAL(textChanged(QString)),
1415 this, SIGNAL(changed()));
1417 hunspellDirPB->setEnabled(false);
1418 hunspellDirED->setEnabled(false);
1421 connect(pathPrefixED, SIGNAL(textChanged(QString)),
1422 this, SIGNAL(changed()));
1424 connect(texinputsPrefixED, SIGNAL(textChanged(QString)),
1425 this, SIGNAL(changed()));
1427 pathPrefixED->setValidator(new NoNewLineValidator(pathPrefixED));
1428 texinputsPrefixED->setValidator(new NoNewLineValidator(texinputsPrefixED));
1432 void PrefPaths::applyRC(LyXRC & rc) const
1434 rc.document_path = internal_path(fromqstr(workingDirED->text()));
1435 rc.example_path = internal_path(fromqstr(exampleDirED->text()));
1436 rc.template_path = internal_path(fromqstr(templateDirED->text()));
1437 rc.backupdir_path = internal_path(fromqstr(backupDirED->text()));
1438 rc.tempdir_path = internal_path(fromqstr(tempDirED->text()));
1439 rc.thesaurusdir_path = internal_path(fromqstr(thesaurusDirED->text()));
1440 rc.hunspelldir_path = internal_path(fromqstr(hunspellDirED->text()));
1441 rc.path_prefix = internal_path_list(fromqstr(pathPrefixED->text()));
1442 rc.texinputs_prefix = internal_path_list(fromqstr(texinputsPrefixED->text()));
1443 // FIXME: should be a checkbox only
1444 rc.lyxpipes = internal_path(fromqstr(lyxserverDirED->text()));
1448 void PrefPaths::updateRC(LyXRC const & rc)
1450 workingDirED->setText(toqstr(external_path(rc.document_path)));
1451 exampleDirED->setText(toqstr(external_path(rc.example_path)));
1452 templateDirED->setText(toqstr(external_path(rc.template_path)));
1453 backupDirED->setText(toqstr(external_path(rc.backupdir_path)));
1454 tempDirED->setText(toqstr(external_path(rc.tempdir_path)));
1455 thesaurusDirED->setText(toqstr(external_path(rc.thesaurusdir_path)));
1456 hunspellDirED->setText(toqstr(external_path(rc.hunspelldir_path)));
1457 pathPrefixED->setText(toqstr(external_path_list(rc.path_prefix)));
1458 texinputsPrefixED->setText(toqstr(external_path_list(rc.texinputs_prefix)));
1459 // FIXME: should be a checkbox only
1460 lyxserverDirED->setText(toqstr(external_path(rc.lyxpipes)));
1464 void PrefPaths::selectExampledir()
1466 QString file = browseDir(internalPath(exampleDirED->text()),
1467 qt_("Select directory for example files"));
1468 if (!file.isEmpty())
1469 exampleDirED->setText(file);
1473 void PrefPaths::selectTemplatedir()
1475 QString file = browseDir(internalPath(templateDirED->text()),
1476 qt_("Select a document templates directory"));
1477 if (!file.isEmpty())
1478 templateDirED->setText(file);
1482 void PrefPaths::selectTempdir()
1484 QString file = browseDir(internalPath(tempDirED->text()),
1485 qt_("Select a temporary directory"));
1486 if (!file.isEmpty())
1487 tempDirED->setText(file);
1491 void PrefPaths::selectBackupdir()
1493 QString file = browseDir(internalPath(backupDirED->text()),
1494 qt_("Select a backups directory"));
1495 if (!file.isEmpty())
1496 backupDirED->setText(file);
1500 void PrefPaths::selectWorkingdir()
1502 QString file = browseDir(internalPath(workingDirED->text()),
1503 qt_("Select a document directory"));
1504 if (!file.isEmpty())
1505 workingDirED->setText(file);
1509 void PrefPaths::selectThesaurusdir()
1511 QString file = browseDir(internalPath(thesaurusDirED->text()),
1512 qt_("Set the path to the thesaurus dictionaries"));
1513 if (!file.isEmpty())
1514 thesaurusDirED->setText(file);
1518 void PrefPaths::selectHunspelldir()
1520 QString file = browseDir(internalPath(hunspellDirED->text()),
1521 qt_("Set the path to the Hunspell dictionaries"));
1522 if (!file.isEmpty())
1523 hunspellDirED->setText(file);
1527 void PrefPaths::selectLyxPipe()
1529 QString file = form_->browse(internalPath(lyxserverDirED->text()),
1530 qt_("Give a filename for the LyX server pipe"));
1531 if (!file.isEmpty())
1532 lyxserverDirED->setText(file);
1536 /////////////////////////////////////////////////////////////////////
1540 /////////////////////////////////////////////////////////////////////
1542 PrefSpellchecker::PrefSpellchecker(GuiPreferences * form)
1543 : PrefModule(catLanguage, N_("Spellchecker"), form)
1547 // FIXME: this check should test the target platform (darwin)
1548 #if defined(USE_MACOSX_PACKAGING)
1549 spellcheckerCB->addItem(qt_("Native"), QString("native"));
1550 #define CONNECT_APPLESPELL
1552 #undef CONNECT_APPLESPELL
1554 #if defined(USE_ASPELL)
1555 spellcheckerCB->addItem(qt_("Aspell"), QString("aspell"));
1557 #if defined(USE_ENCHANT)
1558 spellcheckerCB->addItem(qt_("Enchant"), QString("enchant"));
1560 #if defined(USE_HUNSPELL)
1561 spellcheckerCB->addItem(qt_("Hunspell"), QString("hunspell"));
1564 #if defined(CONNECT_APPLESPELL) || defined(USE_ASPELL) || defined(USE_ENCHANT) || defined(USE_HUNSPELL)
1565 connect(spellcheckerCB, SIGNAL(currentIndexChanged(int)),
1566 this, SIGNAL(changed()));
1567 connect(altLanguageED, SIGNAL(textChanged(QString)),
1568 this, SIGNAL(changed()));
1569 connect(escapeCharactersED, SIGNAL(textChanged(QString)),
1570 this, SIGNAL(changed()));
1571 connect(compoundWordCB, SIGNAL(clicked()),
1572 this, SIGNAL(changed()));
1573 connect(spellcheckContinuouslyCB, SIGNAL(clicked()),
1574 this, SIGNAL(changed()));
1575 connect(spellcheckNotesCB, SIGNAL(clicked()),
1576 this, SIGNAL(changed()));
1578 altLanguageED->setValidator(new NoNewLineValidator(altLanguageED));
1579 escapeCharactersED->setValidator(new NoNewLineValidator(escapeCharactersED));
1581 spellcheckerCB->setEnabled(false);
1582 altLanguageED->setEnabled(false);
1583 escapeCharactersED->setEnabled(false);
1584 compoundWordCB->setEnabled(false);
1585 spellcheckContinuouslyCB->setEnabled(false);
1586 spellcheckNotesCB->setEnabled(false);
1591 void PrefSpellchecker::applyRC(LyXRC & rc) const
1593 string const speller = fromqstr(spellcheckerCB->
1594 itemData(spellcheckerCB->currentIndex()).toString());
1595 if (!speller.empty())
1596 rc.spellchecker = speller;
1597 rc.spellchecker_alt_lang = fromqstr(altLanguageED->text());
1598 rc.spellchecker_esc_chars = fromqstr(escapeCharactersED->text());
1599 rc.spellchecker_accept_compound = compoundWordCB->isChecked();
1600 rc.spellcheck_continuously = spellcheckContinuouslyCB->isChecked();
1601 rc.spellcheck_notes = spellcheckNotesCB->isChecked();
1605 void PrefSpellchecker::updateRC(LyXRC const & rc)
1607 spellcheckerCB->setCurrentIndex(
1608 spellcheckerCB->findData(toqstr(rc.spellchecker)));
1609 altLanguageED->setText(toqstr(rc.spellchecker_alt_lang));
1610 escapeCharactersED->setText(toqstr(rc.spellchecker_esc_chars));
1611 compoundWordCB->setChecked(rc.spellchecker_accept_compound);
1612 spellcheckContinuouslyCB->setChecked(rc.spellcheck_continuously);
1613 spellcheckNotesCB->setChecked(rc.spellcheck_notes);
1617 void PrefSpellchecker::on_spellcheckerCB_currentIndexChanged(int index)
1619 QString spellchecker = spellcheckerCB->itemData(index).toString();
1621 compoundWordCB->setEnabled(spellchecker == QString("aspell"));
1626 /////////////////////////////////////////////////////////////////////
1630 /////////////////////////////////////////////////////////////////////
1633 PrefConverters::PrefConverters(GuiPreferences * form)
1634 : PrefModule(catFiles, N_("Converters"), form)
1638 connect(converterNewPB, SIGNAL(clicked()),
1639 this, SLOT(updateConverter()));
1640 connect(converterRemovePB, SIGNAL(clicked()),
1641 this, SLOT(removeConverter()));
1642 connect(converterModifyPB, SIGNAL(clicked()),
1643 this, SLOT(updateConverter()));
1644 connect(convertersLW, SIGNAL(currentRowChanged(int)),
1645 this, SLOT(switchConverter()));
1646 connect(converterFromCO, SIGNAL(activated(QString)),
1647 this, SLOT(changeConverter()));
1648 connect(converterToCO, SIGNAL(activated(QString)),
1649 this, SLOT(changeConverter()));
1650 connect(converterED, SIGNAL(textEdited(QString)),
1651 this, SLOT(changeConverter()));
1652 connect(converterFlagED, SIGNAL(textEdited(QString)),
1653 this, SLOT(changeConverter()));
1654 connect(converterNewPB, SIGNAL(clicked()),
1655 this, SIGNAL(changed()));
1656 connect(converterRemovePB, SIGNAL(clicked()),
1657 this, SIGNAL(changed()));
1658 connect(converterModifyPB, SIGNAL(clicked()),
1659 this, SIGNAL(changed()));
1660 connect(maxAgeLE, SIGNAL(textEdited(QString)),
1661 this, SIGNAL(changed()));
1662 connect(needauthForbiddenCB, SIGNAL(toggled(bool)),
1663 this, SIGNAL(changed()));
1665 converterED->setValidator(new NoNewLineValidator(converterED));
1666 converterFlagED->setValidator(new NoNewLineValidator(converterFlagED));
1667 maxAgeLE->setValidator(new QDoubleValidator(0, HUGE_VAL, 6, maxAgeLE));
1668 //converterDefGB->setFocusProxy(convertersLW);
1672 void PrefConverters::applyRC(LyXRC & rc) const
1674 rc.use_converter_cache = cacheCB->isChecked();
1675 rc.use_converter_needauth_forbidden = needauthForbiddenCB->isChecked();
1676 rc.use_converter_needauth = needauthCB->isChecked();
1677 rc.converter_cache_maxage = int(widgetToDouble(maxAgeLE) * 86400.0);
1681 static void setCheckboxBlockSignals(QCheckBox *cb, bool checked) {
1682 cb->blockSignals(true);
1683 cb->setChecked(checked);
1684 cb->blockSignals(false);
1688 void PrefConverters::updateRC(LyXRC const & rc)
1690 cacheCB->setChecked(rc.use_converter_cache);
1691 needauthForbiddenCB->setChecked(rc.use_converter_needauth_forbidden);
1692 setCheckboxBlockSignals(needauthCB, rc.use_converter_needauth);
1694 doubleToWidget(maxAgeLE, (double(rc.converter_cache_maxage) / 86400.0), 'g', 6);
1699 void PrefConverters::updateGui()
1701 QString const pattern("%1 -> %2");
1702 form_->formats().sort();
1703 form_->converters().update(form_->formats());
1704 // save current selection
1707 .arg(converterFromCO->currentText())
1708 .arg(converterToCO->currentText());
1710 converterFromCO->clear();
1711 converterToCO->clear();
1713 for (Format const & f : form_->formats()) {
1714 QString const name = toqstr(translateIfPossible(f.prettyname()));
1715 converterFromCO->addItem(name);
1716 converterToCO->addItem(name);
1719 // currentRowChanged(int) is also triggered when updating the listwidget
1720 // block signals to avoid unnecessary calls to switchConverter()
1721 convertersLW->blockSignals(true);
1722 convertersLW->clear();
1724 for (Converter const & c : form_->converters()) {
1725 QString const name =
1727 .arg(toqstr(translateIfPossible(c.From()->prettyname())))
1728 .arg(toqstr(translateIfPossible(c.To()->prettyname())));
1729 int type = form_->converters().getNumber(c.From()->name(),
1731 new QListWidgetItem(name, convertersLW, type);
1733 convertersLW->sortItems(Qt::AscendingOrder);
1734 convertersLW->blockSignals(false);
1736 // restore selection
1737 if (current != pattern.arg(QString()).arg(QString())) {
1738 QList<QListWidgetItem *> const item =
1739 convertersLW->findItems(current, Qt::MatchExactly);
1740 if (!item.isEmpty())
1741 convertersLW->setCurrentItem(item.at(0));
1744 // select first element if restoring failed
1745 if (convertersLW->currentRow() == -1)
1746 convertersLW->setCurrentRow(0);
1752 void PrefConverters::switchConverter()
1754 int const cnr = convertersLW->currentItem()->type();
1755 Converter const & c(form_->converters().get(cnr));
1756 converterFromCO->setCurrentIndex(form_->formats().getNumber(c.from()));
1757 converterToCO->setCurrentIndex(form_->formats().getNumber(c.to()));
1758 converterED->setText(toqstr(c.command()));
1759 converterFlagED->setText(toqstr(c.flags()));
1765 void PrefConverters::changeConverter()
1771 void PrefConverters::updateButtons()
1773 if (form_->formats().empty())
1775 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1776 Format const & to = form_->formats().get(converterToCO->currentIndex());
1777 int const sel = form_->converters().getNumber(from.name(), to.name());
1778 bool const known = sel >= 0;
1779 bool const valid = !(converterED->text().isEmpty()
1780 || from.name() == to.name());
1785 if (convertersLW->count() > 0) {
1786 int const cnr = convertersLW->currentItem()->type();
1787 Converter const & c = form_->converters().get(cnr);
1788 old_command = c.command();
1789 old_flag = c.flags();
1792 string const new_command = fromqstr(converterED->text());
1793 string const new_flag = fromqstr(converterFlagED->text());
1795 bool modified = (old_command != new_command || old_flag != new_flag);
1797 converterModifyPB->setEnabled(valid && known && modified);
1798 converterNewPB->setEnabled(valid && !known);
1799 converterRemovePB->setEnabled(known);
1801 maxAgeLE->setEnabled(cacheCB->isChecked());
1802 maxAgeLA->setEnabled(cacheCB->isChecked());
1807 // specify unique from/to or it doesn't appear. This is really bad UI
1808 // this is why we can use the same function for both new and modify
1809 void PrefConverters::updateConverter()
1811 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1812 Format const & to = form_->formats().get(converterToCO->currentIndex());
1813 string const flags = fromqstr(converterFlagED->text());
1814 string const command = fromqstr(converterED->text());
1816 Converter const * old =
1817 form_->converters().getConverter(from.name(), to.name());
1818 form_->converters().add(from.name(), to.name(), command, flags);
1821 form_->converters().updateLast(form_->formats());
1825 // Remove all files created by this converter from the cache, since
1826 // the modified converter might create different files.
1827 ConverterCache::get().remove_all(from.name(), to.name());
1831 void PrefConverters::removeConverter()
1833 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1834 Format const & to = form_->formats().get(converterToCO->currentIndex());
1835 form_->converters().erase(from.name(), to.name());
1839 // Remove all files created by this converter from the cache, since
1840 // a possible new converter might create different files.
1841 ConverterCache::get().remove_all(from.name(), to.name());
1845 void PrefConverters::on_cacheCB_stateChanged(int state)
1847 maxAgeLE->setEnabled(state == Qt::Checked);
1848 maxAgeLA->setEnabled(state == Qt::Checked);
1853 void PrefConverters::on_needauthForbiddenCB_toggled(bool checked)
1855 needauthCB->setEnabled(!checked);
1859 void PrefConverters::on_needauthCB_toggled(bool checked)
1866 int ret = frontend::Alert::prompt(
1867 _("SECURITY WARNING!"), _("Unchecking this option has the effect that potentially harmful converters would be run without asking your permission first. This is UNSAFE and NOT recommended, unless you know what you are doing. Are you sure you would like to proceed ? The recommended and safe answer is NO!"),
1868 0, 0, _("&No"), _("&Yes"));
1872 setCheckboxBlockSignals(needauthCB, true);
1876 /////////////////////////////////////////////////////////////////////
1880 /////////////////////////////////////////////////////////////////////
1882 class FormatValidator : public QValidator
1885 FormatValidator(QWidget *, Formats const & f);
1886 void fixup(QString & input) const;
1887 QValidator::State validate(QString & input, int & pos) const;
1889 virtual QString toString(Format const & format) const = 0;
1891 Formats const & formats_;
1895 FormatValidator::FormatValidator(QWidget * parent, Formats const & f)
1896 : QValidator(parent), formats_(f)
1901 void FormatValidator::fixup(QString & input) const
1903 Formats::const_iterator cit = formats_.begin();
1904 Formats::const_iterator end = formats_.end();
1905 for (; cit != end; ++cit) {
1906 QString const name = toString(*cit);
1907 if (distance(formats_.begin(), cit) == nr()) {
1915 QValidator::State FormatValidator::validate(QString & input, int & /*pos*/) const
1917 Formats::const_iterator cit = formats_.begin();
1918 Formats::const_iterator end = formats_.end();
1919 bool unknown = true;
1920 for (; unknown && cit != end; ++cit) {
1921 QString const name = toString(*cit);
1922 if (distance(formats_.begin(), cit) != nr())
1923 unknown = name != input;
1926 if (unknown && !input.isEmpty())
1927 return QValidator::Acceptable;
1929 return QValidator::Intermediate;
1933 int FormatValidator::nr() const
1935 QComboBox * p = qobject_cast<QComboBox *>(parent());
1936 return p->itemData(p->currentIndex()).toInt();
1940 /////////////////////////////////////////////////////////////////////
1942 // FormatNameValidator
1944 /////////////////////////////////////////////////////////////////////
1946 class FormatNameValidator : public FormatValidator
1949 FormatNameValidator(QWidget * parent, Formats const & f)
1950 : FormatValidator(parent, f)
1953 QString toString(Format const & format) const
1955 return toqstr(format.name());
1960 /////////////////////////////////////////////////////////////////////
1962 // FormatPrettynameValidator
1964 /////////////////////////////////////////////////////////////////////
1966 class FormatPrettynameValidator : public FormatValidator
1969 FormatPrettynameValidator(QWidget * parent, Formats const & f)
1970 : FormatValidator(parent, f)
1973 QString toString(Format const & format) const
1975 return toqstr(translateIfPossible(format.prettyname()));
1980 /////////////////////////////////////////////////////////////////////
1984 /////////////////////////////////////////////////////////////////////
1986 PrefFileformats::PrefFileformats(GuiPreferences * form)
1987 : PrefModule(catFiles, N_("File Formats"), form)
1991 formatED->setValidator(new FormatNameValidator(formatsCB, form_->formats()));
1992 formatsCB->setValidator(new FormatPrettynameValidator(formatsCB, form_->formats()));
1993 extensionsED->setValidator(new NoNewLineValidator(extensionsED));
1994 shortcutED->setValidator(new NoNewLineValidator(shortcutED));
1995 editorED->setValidator(new NoNewLineValidator(editorED));
1996 viewerED->setValidator(new NoNewLineValidator(viewerED));
1997 copierED->setValidator(new NoNewLineValidator(copierED));
1999 connect(documentCB, SIGNAL(clicked()),
2000 this, SLOT(setFlags()));
2001 connect(vectorCB, SIGNAL(clicked()),
2002 this, SLOT(setFlags()));
2003 connect(exportMenuCB, SIGNAL(clicked()),
2004 this, SLOT(setFlags()));
2005 connect(formatsCB->lineEdit(), SIGNAL(editingFinished()),
2006 this, SLOT(updatePrettyname()));
2007 connect(formatsCB->lineEdit(), SIGNAL(textEdited(QString)),
2008 this, SIGNAL(changed()));
2009 connect(defaultFormatCB, SIGNAL(activated(QString)),
2010 this, SIGNAL(changed()));
2011 connect(defaultOTFFormatCB, SIGNAL(activated(QString)),
2012 this, SIGNAL(changed()));
2013 connect(defaultPlatexFormatCB, SIGNAL(activated(QString)),
2014 this, SIGNAL(changed()));
2015 connect(viewerCO, SIGNAL(activated(int)),
2016 this, SIGNAL(changed()));
2017 connect(editorCO, SIGNAL(activated(int)),
2018 this, SIGNAL(changed()));
2024 string const l10n_shortcut(docstring const & prettyname, string const & shortcut)
2026 if (shortcut.empty())
2029 string l10n_format =
2030 to_utf8(_(to_utf8(prettyname) + '|' + shortcut));
2031 return split(l10n_format, '|');
2037 void PrefFileformats::applyRC(LyXRC & rc) const
2039 QString const default_format = defaultFormatCB->itemData(
2040 defaultFormatCB->currentIndex()).toString();
2041 rc.default_view_format = fromqstr(default_format);
2042 QString const default_otf_format = defaultOTFFormatCB->itemData(
2043 defaultOTFFormatCB->currentIndex()).toString();
2044 rc.default_otf_view_format = fromqstr(default_otf_format);
2045 QString const default_platex_format = defaultPlatexFormatCB->itemData(
2046 defaultPlatexFormatCB->currentIndex()).toString();
2047 rc.default_platex_view_format = fromqstr(default_platex_format);
2051 void PrefFileformats::updateRC(LyXRC const & rc)
2053 viewer_alternatives = rc.viewer_alternatives;
2054 editor_alternatives = rc.editor_alternatives;
2055 bool const init = defaultFormatCB->currentText().isEmpty();
2059 defaultFormatCB->findData(toqstr(rc.default_view_format));
2060 defaultFormatCB->setCurrentIndex(pos);
2061 pos = defaultOTFFormatCB->findData(toqstr(rc.default_otf_view_format));
2062 defaultOTFFormatCB->setCurrentIndex(pos);
2063 defaultOTFFormatCB->setCurrentIndex(pos);
2064 pos = defaultPlatexFormatCB->findData(toqstr(rc.default_platex_view_format));
2065 defaultPlatexFormatCB->setCurrentIndex(pos);
2066 defaultPlatexFormatCB->setCurrentIndex(pos);
2071 void PrefFileformats::updateView()
2073 QString const current = formatsCB->currentText();
2074 QString const current_def = defaultFormatCB->currentText();
2075 QString const current_def_otf = defaultOTFFormatCB->currentText();
2076 QString const current_def_platex = defaultPlatexFormatCB->currentText();
2078 // update comboboxes with formats
2079 formatsCB->blockSignals(true);
2080 defaultFormatCB->blockSignals(true);
2081 defaultOTFFormatCB->blockSignals(true);
2082 defaultPlatexFormatCB->blockSignals(true);
2084 defaultFormatCB->clear();
2085 defaultOTFFormatCB->clear();
2086 defaultPlatexFormatCB->clear();
2087 form_->formats().sort();
2088 for (Format const & f : form_->formats()) {
2089 QString const prettyname = toqstr(translateIfPossible(f.prettyname()));
2090 formatsCB->addItem(prettyname,
2091 QVariant(form_->formats().getNumber(f.name())));
2092 if (f.viewer().empty())
2094 if (form_->converters().isReachable("xhtml", f.name())
2095 || form_->converters().isReachable("dviluatex", f.name())
2096 || form_->converters().isReachable("luatex", f.name())
2097 || form_->converters().isReachable("xetex", f.name())) {
2098 defaultFormatCB->addItem(prettyname,
2099 QVariant(toqstr(f.name())));
2100 defaultOTFFormatCB->addItem(prettyname,
2101 QVariant(toqstr(f.name())));
2103 if (form_->converters().isReachable("latex", f.name())
2104 || form_->converters().isReachable("pdflatex", f.name()))
2105 defaultFormatCB->addItem(prettyname,
2106 QVariant(toqstr(f.name())));
2107 if (form_->converters().isReachable("platex", f.name()))
2108 defaultPlatexFormatCB->addItem(prettyname,
2109 QVariant(toqstr(f.name())));
2113 // restore selections
2114 int item = formatsCB->findText(current, Qt::MatchExactly);
2115 formatsCB->setCurrentIndex(item < 0 ? 0 : item);
2116 on_formatsCB_currentIndexChanged(item < 0 ? 0 : item);
2117 item = defaultFormatCB->findText(current_def, Qt::MatchExactly);
2118 defaultFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2119 item = defaultOTFFormatCB->findText(current_def_otf, Qt::MatchExactly);
2120 defaultOTFFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2121 item = defaultPlatexFormatCB->findText(current_def_platex, Qt::MatchExactly);
2122 defaultPlatexFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2123 formatsCB->blockSignals(false);
2124 defaultFormatCB->blockSignals(false);
2125 defaultOTFFormatCB->blockSignals(false);
2126 defaultPlatexFormatCB->blockSignals(false);
2130 void PrefFileformats::on_formatsCB_currentIndexChanged(int i)
2132 if (form_->formats().empty())
2134 int const nr = formatsCB->itemData(i).toInt();
2135 Format const f = form_->formats().get(nr);
2137 formatED->setText(toqstr(f.name()));
2138 copierED->setText(toqstr(form_->movers().command(f.name())));
2139 extensionsED->setText(toqstr(f.extensions()));
2140 mimeED->setText(toqstr(f.mime()));
2141 shortcutED->setText(
2142 toqstr(l10n_shortcut(f.prettyname(), f.shortcut())));
2143 documentCB->setChecked((f.documentFormat()));
2144 vectorCB->setChecked((f.vectorFormat()));
2145 exportMenuCB->setChecked((f.inExportMenu()));
2146 exportMenuCB->setEnabled((f.documentFormat()));
2152 void PrefFileformats::setFlags()
2154 int flags = Format::none;
2155 if (documentCB->isChecked())
2156 flags |= Format::document;
2157 if (vectorCB->isChecked())
2158 flags |= Format::vector;
2159 if (exportMenuCB->isChecked())
2160 flags |= Format::export_menu;
2161 currentFormat().setFlags(flags);
2162 exportMenuCB->setEnabled(documentCB->isChecked());
2167 void PrefFileformats::on_copierED_textEdited(const QString & s)
2169 string const fmt = fromqstr(formatED->text());
2170 form_->movers().set(fmt, fromqstr(s));
2175 void PrefFileformats::on_extensionsED_textEdited(const QString & s)
2177 currentFormat().setExtensions(fromqstr(s));
2182 void PrefFileformats::on_viewerED_textEdited(const QString & s)
2184 currentFormat().setViewer(fromqstr(s));
2189 void PrefFileformats::on_editorED_textEdited(const QString & s)
2191 currentFormat().setEditor(fromqstr(s));
2196 void PrefFileformats::on_mimeED_textEdited(const QString & s)
2198 currentFormat().setMime(fromqstr(s));
2203 void PrefFileformats::on_shortcutED_textEdited(const QString & s)
2205 string const new_shortcut = fromqstr(s);
2206 if (new_shortcut == l10n_shortcut(currentFormat().prettyname(),
2207 currentFormat().shortcut()))
2209 currentFormat().setShortcut(new_shortcut);
2214 void PrefFileformats::on_formatED_editingFinished()
2216 string const newname = fromqstr(formatED->displayText());
2217 string const oldname = currentFormat().name();
2218 if (newname == oldname)
2220 if (form_->converters().formatIsUsed(oldname)) {
2221 Alert::error(_("Format in use"),
2222 _("You cannot change a format's short name "
2223 "if the format is used by a converter. "
2224 "Please remove the converter first."));
2229 currentFormat().setName(newname);
2234 void PrefFileformats::on_formatED_textChanged(const QString &)
2236 QString t = formatED->text();
2238 bool valid = formatED->validator()->validate(t, p) == QValidator::Acceptable;
2239 setValid(formatLA, valid);
2243 void PrefFileformats::on_formatsCB_editTextChanged(const QString &)
2245 QString t = formatsCB->currentText();
2247 bool valid = formatsCB->validator()->validate(t, p) == QValidator::Acceptable;
2248 setValid(formatsLA, valid);
2252 void PrefFileformats::updatePrettyname()
2254 QString const newname = formatsCB->currentText();
2255 if (newname == toqstr(translateIfPossible(currentFormat().prettyname())))
2258 currentFormat().setPrettyname(qstring_to_ucs4(newname));
2266 void updateComboBox(LyXRC::Alternatives const & alts,
2267 string const & fmt, QComboBox * combo)
2269 LyXRC::Alternatives::const_iterator it =
2271 if (it != alts.end()) {
2272 LyXRC::CommandSet const & cmds = it->second;
2273 LyXRC::CommandSet::const_iterator sit =
2275 LyXRC::CommandSet::const_iterator const sen =
2277 for (; sit != sen; ++sit) {
2278 QString const qcmd = toqstr(*sit);
2279 combo->addItem(qcmd, qcmd);
2286 void PrefFileformats::updateViewers()
2288 Format const f = currentFormat();
2289 viewerCO->blockSignals(true);
2291 viewerCO->addItem(qt_("None"), QString());
2292 updateComboBox(viewer_alternatives, f.name(), viewerCO);
2293 viewerCO->addItem(qt_("Custom"), QString("custom viewer"));
2294 viewerCO->blockSignals(false);
2296 int pos = viewerCO->findData(toqstr(f.viewer()));
2299 viewerED->setEnabled(false);
2300 viewerCO->setCurrentIndex(pos);
2302 viewerED->setEnabled(true);
2303 viewerED->setText(toqstr(f.viewer()));
2304 viewerCO->setCurrentIndex(viewerCO->findData(toqstr("custom viewer")));
2309 void PrefFileformats::updateEditors()
2311 Format const f = currentFormat();
2312 editorCO->blockSignals(true);
2314 editorCO->addItem(qt_("None"), QString());
2315 updateComboBox(editor_alternatives, f.name(), editorCO);
2316 editorCO->addItem(qt_("Custom"), QString("custom editor"));
2317 editorCO->blockSignals(false);
2319 int pos = editorCO->findData(toqstr(f.editor()));
2322 editorED->setEnabled(false);
2323 editorCO->setCurrentIndex(pos);
2325 editorED->setEnabled(true);
2326 editorED->setText(toqstr(f.editor()));
2327 editorCO->setCurrentIndex(editorCO->findData(toqstr("custom editor")));
2332 void PrefFileformats::on_viewerCO_currentIndexChanged(int i)
2334 bool const custom = viewerCO->itemData(i).toString() == "custom viewer";
2335 viewerED->setEnabled(custom);
2337 currentFormat().setViewer(fromqstr(viewerCO->itemData(i).toString()));
2341 void PrefFileformats::on_editorCO_currentIndexChanged(int i)
2343 bool const custom = editorCO->itemData(i).toString() == "custom editor";
2344 editorED->setEnabled(custom);
2346 currentFormat().setEditor(fromqstr(editorCO->itemData(i).toString()));
2350 Format & PrefFileformats::currentFormat()
2352 int const i = formatsCB->currentIndex();
2353 int const nr = formatsCB->itemData(i).toInt();
2354 return form_->formats().get(nr);
2358 void PrefFileformats::on_formatNewPB_clicked()
2360 form_->formats().add("", "", docstring(), "", "", "", "", Format::none);
2362 formatsCB->setCurrentIndex(0);
2363 formatsCB->setFocus(Qt::OtherFocusReason);
2367 void PrefFileformats::on_formatRemovePB_clicked()
2369 int const i = formatsCB->currentIndex();
2370 int const nr = formatsCB->itemData(i).toInt();
2371 string const current_text = form_->formats().get(nr).name();
2372 if (form_->converters().formatIsUsed(current_text)) {
2373 Alert::error(_("Format in use"),
2374 _("Cannot remove a Format used by a Converter. "
2375 "Remove the converter first."));
2379 form_->formats().erase(current_text);
2382 on_formatsCB_editTextChanged(formatsCB->currentText());
2387 /////////////////////////////////////////////////////////////////////
2391 /////////////////////////////////////////////////////////////////////
2393 PrefLanguage::PrefLanguage(GuiPreferences * form)
2394 : PrefModule(catLanguage, N_("Language"), form)
2398 connect(visualCursorRB, SIGNAL(clicked()),
2399 this, SIGNAL(changed()));
2400 connect(logicalCursorRB, SIGNAL(clicked()),
2401 this, SIGNAL(changed()));
2402 connect(markForeignCB, SIGNAL(clicked()),
2403 this, SIGNAL(changed()));
2404 connect(autoBeginCB, SIGNAL(clicked()),
2405 this, SIGNAL(changed()));
2406 connect(autoEndCB, SIGNAL(clicked()),
2407 this, SIGNAL(changed()));
2408 connect(languagePackageCO, SIGNAL(activated(int)),
2409 this, SIGNAL(changed()));
2410 connect(languagePackageED, SIGNAL(textChanged(QString)),
2411 this, SIGNAL(changed()));
2412 connect(globalCB, SIGNAL(clicked()),
2413 this, SIGNAL(changed()));
2414 connect(startCommandED, SIGNAL(textChanged(QString)),
2415 this, SIGNAL(changed()));
2416 connect(endCommandED, SIGNAL(textChanged(QString)),
2417 this, SIGNAL(changed()));
2418 connect(uiLanguageCO, SIGNAL(activated(int)),
2419 this, SIGNAL(changed()));
2420 connect(defaultDecimalPointLE, SIGNAL(textChanged(QString)),
2421 this, SIGNAL(changed()));
2422 connect(defaultLengthUnitCO, SIGNAL(activated(int)),
2423 this, SIGNAL(changed()));
2425 languagePackageED->setValidator(new NoNewLineValidator(languagePackageED));
2426 startCommandED->setValidator(new NoNewLineValidator(startCommandED));
2427 endCommandED->setValidator(new NoNewLineValidator(endCommandED));
2429 defaultDecimalPointLE->setInputMask("X; ");
2430 defaultDecimalPointLE->setMaxLength(1);
2432 defaultLengthUnitCO->addItem(lyx::qt_(unit_name_gui[Length::CM]), Length::CM);
2433 defaultLengthUnitCO->addItem(lyx::qt_(unit_name_gui[Length::IN]), Length::IN);
2435 QAbstractItemModel * language_model = guiApp->languageModel();
2436 language_model->sort(0);
2437 uiLanguageCO->blockSignals(true);
2438 uiLanguageCO->clear();
2439 uiLanguageCO->addItem(qt_("Default"), toqstr("auto"));
2440 for (int i = 0; i != language_model->rowCount(); ++i) {
2441 QModelIndex index = language_model->index(i, 0);
2442 // Filter the list based on the available translation and add
2443 // each language code only once
2444 string const name = fromqstr(index.data(Qt::UserRole).toString());
2445 Language const * lang = languages.getLanguage(name);
2448 // never remove the currently selected language
2449 if (name != form->rc().gui_language
2450 && name != lyxrc.gui_language
2451 && (!Messages::available(lang->code())
2452 || !lang->hasGuiSupport()))
2454 uiLanguageCO->addItem(index.data(Qt::DisplayRole).toString(),
2455 index.data(Qt::UserRole).toString());
2457 uiLanguageCO->blockSignals(false);
2461 void PrefLanguage::on_uiLanguageCO_currentIndexChanged(int)
2463 QMessageBox::information(this, qt_("LyX needs to be restarted!"),
2464 qt_("The change of user interface language will be fully "
2465 "effective only after a restart."));
2469 void PrefLanguage::on_languagePackageCO_currentIndexChanged(int i)
2471 languagePackageED->setEnabled(i == 2);
2475 void PrefLanguage::applyRC(LyXRC & rc) const
2477 rc.visual_cursor = visualCursorRB->isChecked();
2478 rc.mark_foreign_language = markForeignCB->isChecked();
2479 rc.language_auto_begin = autoBeginCB->isChecked();
2480 rc.language_auto_end = autoEndCB->isChecked();
2481 int const p = languagePackageCO->currentIndex();
2483 rc.language_package_selection = LyXRC::LP_AUTO;
2485 rc.language_package_selection = LyXRC::LP_BABEL;
2487 rc.language_package_selection = LyXRC::LP_CUSTOM;
2489 rc.language_package_selection = LyXRC::LP_NONE;
2490 rc.language_custom_package = fromqstr(languagePackageED->text());
2491 rc.language_global_options = globalCB->isChecked();
2492 rc.language_command_begin = fromqstr(startCommandED->text());
2493 rc.language_command_end = fromqstr(endCommandED->text());
2494 rc.gui_language = fromqstr(
2495 uiLanguageCO->itemData(uiLanguageCO->currentIndex()).toString());
2496 rc.default_decimal_point = fromqstr(defaultDecimalPointLE->text());
2497 rc.default_length_unit = (Length::UNIT) defaultLengthUnitCO->itemData(defaultLengthUnitCO->currentIndex()).toInt();
2501 void PrefLanguage::updateRC(LyXRC const & rc)
2503 if (rc.visual_cursor)
2504 visualCursorRB->setChecked(true);
2506 logicalCursorRB->setChecked(true);
2507 markForeignCB->setChecked(rc.mark_foreign_language);
2508 autoBeginCB->setChecked(rc.language_auto_begin);
2509 autoEndCB->setChecked(rc.language_auto_end);
2510 languagePackageCO->setCurrentIndex(rc.language_package_selection);
2511 languagePackageED->setText(toqstr(rc.language_custom_package));
2512 languagePackageED->setEnabled(languagePackageCO->currentIndex() == 2);
2513 globalCB->setChecked(rc.language_global_options);
2514 startCommandED->setText(toqstr(rc.language_command_begin));
2515 endCommandED->setText(toqstr(rc.language_command_end));
2516 defaultDecimalPointLE->setText(toqstr(rc.default_decimal_point));
2517 int pos = defaultLengthUnitCO->findData(int(rc.default_length_unit));
2518 defaultLengthUnitCO->setCurrentIndex(pos);
2520 pos = uiLanguageCO->findData(toqstr(rc.gui_language));
2521 uiLanguageCO->blockSignals(true);
2522 uiLanguageCO->setCurrentIndex(pos);
2523 uiLanguageCO->blockSignals(false);
2527 /////////////////////////////////////////////////////////////////////
2529 // PrefUserInterface
2531 /////////////////////////////////////////////////////////////////////
2533 PrefUserInterface::PrefUserInterface(GuiPreferences * form)
2534 : PrefModule(catLookAndFeel, N_("User Interface"), form)
2538 connect(uiFilePB, SIGNAL(clicked()),
2539 this, SLOT(selectUi()));
2540 connect(uiFileED, SIGNAL(textChanged(QString)),
2541 this, SIGNAL(changed()));
2542 connect(iconSetCO, SIGNAL(activated(int)),
2543 this, SIGNAL(changed()));
2544 connect(useSystemThemeIconsCB, SIGNAL(clicked()),
2545 this, SIGNAL(changed()));
2546 connect(lastfilesSB, SIGNAL(valueChanged(int)),
2547 this, SIGNAL(changed()));
2548 connect(tooltipCB, SIGNAL(toggled(bool)),
2549 this, SIGNAL(changed()));
2550 lastfilesSB->setMaximum(maxlastfiles);
2552 iconSetCO->addItem(qt_("Default"), QString());
2553 iconSetCO->addItem(qt_("Classic"), "classic");
2554 iconSetCO->addItem(qt_("Oxygen"), "oxygen");
2556 #if (!(defined Q_WS_X11 || defined(QPA_XCB)) || QT_VERSION < 0x040600)
2557 useSystemThemeIconsCB->hide();
2562 void PrefUserInterface::applyRC(LyXRC & rc) const
2564 rc.icon_set = fromqstr(iconSetCO->itemData(
2565 iconSetCO->currentIndex()).toString());
2567 rc.ui_file = internal_path(fromqstr(uiFileED->text()));
2568 rc.use_system_theme_icons = useSystemThemeIconsCB->isChecked();
2569 rc.num_lastfiles = lastfilesSB->value();
2570 rc.use_tooltip = tooltipCB->isChecked();
2574 void PrefUserInterface::updateRC(LyXRC const & rc)
2576 int iconset = iconSetCO->findData(toqstr(rc.icon_set));
2579 iconSetCO->setCurrentIndex(iconset);
2580 useSystemThemeIconsCB->setChecked(rc.use_system_theme_icons);
2581 uiFileED->setText(toqstr(external_path(rc.ui_file)));
2582 lastfilesSB->setValue(rc.num_lastfiles);
2583 tooltipCB->setChecked(rc.use_tooltip);
2587 void PrefUserInterface::selectUi()
2589 QString file = form_->browseUI(internalPath(uiFileED->text()));
2590 if (!file.isEmpty())
2591 uiFileED->setText(file);
2595 /////////////////////////////////////////////////////////////////////
2597 // PrefDocumentHandling
2599 /////////////////////////////////////////////////////////////////////
2601 PrefDocHandling::PrefDocHandling(GuiPreferences * form)
2602 : PrefModule(catLookAndFeel, N_("Document Handling"), form)
2606 connect(autoSaveCB, SIGNAL(toggled(bool)),
2607 autoSaveSB, SLOT(setEnabled(bool)));
2608 connect(autoSaveCB, SIGNAL(toggled(bool)),
2609 TextLabel1, SLOT(setEnabled(bool)));
2610 connect(openDocumentsInTabsCB, SIGNAL(clicked()),
2611 this, SIGNAL(changed()));
2612 connect(singleInstanceCB, SIGNAL(clicked()),
2613 this, SIGNAL(changed()));
2614 connect(singleCloseTabButtonCB, SIGNAL(clicked()),
2615 this, SIGNAL(changed()));
2616 connect(closeLastViewCO, SIGNAL(activated(int)),
2617 this, SIGNAL(changed()));
2618 connect(restoreCursorCB, SIGNAL(clicked()),
2619 this, SIGNAL(changed()));
2620 connect(loadSessionCB, SIGNAL(clicked()),
2621 this, SIGNAL(changed()));
2622 connect(allowGeometrySessionCB, SIGNAL(clicked()),
2623 this, SIGNAL(changed()));
2624 connect(autoSaveSB, SIGNAL(valueChanged(int)),
2625 this, SIGNAL(changed()));
2626 connect(autoSaveCB, SIGNAL(clicked()),
2627 this, SIGNAL(changed()));
2628 connect(backupCB, SIGNAL(clicked()),
2629 this, SIGNAL(changed()));
2630 connect(saveCompressedCB, SIGNAL(clicked()),
2631 this, SIGNAL(changed()));
2632 connect(saveOriginCB, SIGNAL(clicked()),
2633 this, SIGNAL(changed()));
2637 void PrefDocHandling::applyRC(LyXRC & rc) const
2639 rc.use_lastfilepos = restoreCursorCB->isChecked();
2640 rc.load_session = loadSessionCB->isChecked();
2641 rc.allow_geometry_session = allowGeometrySessionCB->isChecked();
2642 rc.autosave = autoSaveCB->isChecked() ? autoSaveSB->value() * 60 : 0;
2643 rc.make_backup = backupCB->isChecked();
2644 rc.save_compressed = saveCompressedCB->isChecked();
2645 rc.save_origin = saveOriginCB->isChecked();
2646 rc.open_buffers_in_tabs = openDocumentsInTabsCB->isChecked();
2647 rc.single_instance = singleInstanceCB->isChecked();
2648 rc.single_close_tab_button = singleCloseTabButtonCB->isChecked();
2650 switch (closeLastViewCO->currentIndex()) {
2652 rc.close_buffer_with_last_view = "yes";
2655 rc.close_buffer_with_last_view = "no";
2658 rc.close_buffer_with_last_view = "ask";
2666 void PrefDocHandling::updateRC(LyXRC const & rc)
2668 restoreCursorCB->setChecked(rc.use_lastfilepos);
2669 loadSessionCB->setChecked(rc.load_session);
2670 allowGeometrySessionCB->setChecked(rc.allow_geometry_session);
2671 // convert to minutes
2672 bool autosave = rc.autosave > 0;
2673 int mins = rc.autosave / 60;
2676 autoSaveSB->setValue(mins);
2677 autoSaveCB->setChecked(autosave);
2678 autoSaveSB->setEnabled(autosave);
2679 backupCB->setChecked(rc.make_backup);
2680 saveCompressedCB->setChecked(rc.save_compressed);
2681 saveOriginCB->setChecked(rc.save_origin);
2682 openDocumentsInTabsCB->setChecked(rc.open_buffers_in_tabs);
2683 singleInstanceCB->setChecked(rc.single_instance && !rc.lyxpipes.empty());
2684 singleInstanceCB->setEnabled(!rc.lyxpipes.empty());
2685 singleCloseTabButtonCB->setChecked(rc.single_close_tab_button);
2686 if (rc.close_buffer_with_last_view == "yes")
2687 closeLastViewCO->setCurrentIndex(0);
2688 else if (rc.close_buffer_with_last_view == "no")
2689 closeLastViewCO->setCurrentIndex(1);
2690 else if (rc.close_buffer_with_last_view == "ask")
2691 closeLastViewCO->setCurrentIndex(2);
2695 void PrefDocHandling::on_clearSessionPB_clicked()
2697 guiApp->clearSession();
2702 /////////////////////////////////////////////////////////////////////
2706 /////////////////////////////////////////////////////////////////////
2708 PrefEdit::PrefEdit(GuiPreferences * form)
2709 : PrefModule(catEditing, N_("Control"), form)
2713 connect(cursorFollowsCB, SIGNAL(clicked()),
2714 this, SIGNAL(changed()));
2715 connect(scrollBelowCB, SIGNAL(clicked()),
2716 this, SIGNAL(changed()));
2717 connect(macLikeCursorMovementCB, SIGNAL(clicked()),
2718 this, SIGNAL(changed()));
2719 connect(sortEnvironmentsCB, SIGNAL(clicked()),
2720 this, SIGNAL(changed()));
2721 connect(groupEnvironmentsCB, SIGNAL(clicked()),
2722 this, SIGNAL(changed()));
2723 connect(macroEditStyleCO, SIGNAL(activated(int)),
2724 this, SIGNAL(changed()));
2725 connect(cursorWidthSB, SIGNAL(valueChanged(int)),
2726 this, SIGNAL(changed()));
2727 connect(fullscreenLimitGB, SIGNAL(clicked()),
2728 this, SIGNAL(changed()));
2729 connect(fullscreenWidthSB, SIGNAL(valueChanged(int)),
2730 this, SIGNAL(changed()));
2731 connect(toggleTabbarCB, SIGNAL(toggled(bool)),
2732 this, SIGNAL(changed()));
2733 connect(toggleMenubarCB, SIGNAL(toggled(bool)),
2734 this, SIGNAL(changed()));
2735 connect(toggleScrollbarCB, SIGNAL(toggled(bool)),
2736 this, SIGNAL(changed()));
2737 connect(toggleStatusbarCB, SIGNAL(toggled(bool)),
2738 this, SIGNAL(changed()));
2739 connect(toggleToolbarsCB, SIGNAL(toggled(bool)),
2740 this, SIGNAL(changed()));
2744 void PrefEdit::applyRC(LyXRC & rc) const
2746 rc.cursor_follows_scrollbar = cursorFollowsCB->isChecked();
2747 rc.scroll_below_document = scrollBelowCB->isChecked();
2748 rc.mac_like_cursor_movement = macLikeCursorMovementCB->isChecked();
2749 rc.sort_layouts = sortEnvironmentsCB->isChecked();
2750 rc.group_layouts = groupEnvironmentsCB->isChecked();
2751 switch (macroEditStyleCO->currentIndex()) {
2752 case 0: rc.macro_edit_style = LyXRC::MACRO_EDIT_INLINE_BOX; break;
2753 case 1: rc.macro_edit_style = LyXRC::MACRO_EDIT_INLINE; break;
2754 case 2: rc.macro_edit_style = LyXRC::MACRO_EDIT_LIST; break;
2756 rc.cursor_width = cursorWidthSB->value();
2757 rc.full_screen_toolbars = toggleToolbarsCB->isChecked();
2758 rc.full_screen_scrollbar = toggleScrollbarCB->isChecked();
2759 rc.full_screen_statusbar = toggleStatusbarCB->isChecked();
2760 rc.full_screen_tabbar = toggleTabbarCB->isChecked();
2761 rc.full_screen_menubar = toggleMenubarCB->isChecked();
2762 rc.full_screen_width = fullscreenWidthSB->value();
2763 rc.full_screen_limit = fullscreenLimitGB->isChecked();
2767 void PrefEdit::updateRC(LyXRC const & rc)
2769 cursorFollowsCB->setChecked(rc.cursor_follows_scrollbar);
2770 scrollBelowCB->setChecked(rc.scroll_below_document);
2771 macLikeCursorMovementCB->setChecked(rc.mac_like_cursor_movement);
2772 sortEnvironmentsCB->setChecked(rc.sort_layouts);
2773 groupEnvironmentsCB->setChecked(rc.group_layouts);
2774 macroEditStyleCO->setCurrentIndex(rc.macro_edit_style);
2775 cursorWidthSB->setValue(rc.cursor_width);
2776 toggleScrollbarCB->setChecked(rc.full_screen_scrollbar);
2777 toggleStatusbarCB->setChecked(rc.full_screen_statusbar);
2778 toggleToolbarsCB->setChecked(rc.full_screen_toolbars);
2779 toggleTabbarCB->setChecked(rc.full_screen_tabbar);
2780 toggleMenubarCB->setChecked(rc.full_screen_menubar);
2781 fullscreenWidthSB->setValue(rc.full_screen_width);
2782 fullscreenLimitGB->setChecked(rc.full_screen_limit);
2786 /////////////////////////////////////////////////////////////////////
2790 /////////////////////////////////////////////////////////////////////
2793 GuiShortcutDialog::GuiShortcutDialog(QWidget * parent) : QDialog(parent)
2795 Ui::shortcutUi::setupUi(this);
2796 QDialog::setModal(true);
2800 PrefShortcuts::PrefShortcuts(GuiPreferences * form)
2801 : PrefModule(catEditing, N_("Shortcuts"), form),
2802 editItem_(0), mathItem_(0), bufferItem_(0), layoutItem_(0),
2807 shortcutsTW->setColumnCount(2);
2808 shortcutsTW->headerItem()->setText(0, qt_("Function"));
2809 shortcutsTW->headerItem()->setText(1, qt_("Shortcut"));
2810 shortcutsTW->setSortingEnabled(true);
2811 // Multi-selection can be annoying.
2812 // shortcutsTW->setSelectionMode(QAbstractItemView::MultiSelection);
2814 connect(bindFilePB, SIGNAL(clicked()),
2815 this, SLOT(selectBind()));
2816 connect(bindFileED, SIGNAL(textChanged(QString)),
2817 this, SIGNAL(changed()));
2819 shortcut_ = new GuiShortcutDialog(this);
2820 shortcut_bc_.setPolicy(ButtonPolicy::OkCancelPolicy);
2821 shortcut_bc_.setOK(shortcut_->buttonBox->button(QDialogButtonBox::Ok));
2822 shortcut_bc_.setCancel(shortcut_->buttonBox->button(QDialogButtonBox::Cancel));
2824 connect(shortcut_->buttonBox, SIGNAL(accepted()),
2825 this, SIGNAL(changed()));
2826 connect(shortcut_->buttonBox, SIGNAL(rejected()),
2827 shortcut_, SLOT(reject()));
2828 connect(shortcut_->clearPB, SIGNAL(clicked()),
2829 this, SLOT(shortcutClearPressed()));
2830 connect(shortcut_->removePB, SIGNAL(clicked()),
2831 this, SLOT(shortcutRemovePressed()));
2832 connect(shortcut_->buttonBox, SIGNAL(accepted()),
2833 this, SLOT(shortcutOkPressed()));
2834 connect(shortcut_->buttonBox, SIGNAL(rejected()),
2835 this, SLOT(shortcutCancelPressed()));
2839 void PrefShortcuts::applyRC(LyXRC & rc) const
2841 rc.bind_file = internal_path(fromqstr(bindFileED->text()));
2842 // write user_bind and user_unbind to .lyx/bind/user.bind
2843 FileName bind_dir(addPath(package().user_support().absFileName(), "bind"));
2844 if (!bind_dir.exists() && !bind_dir.createDirectory(0777)) {
2845 lyxerr << "LyX could not create the user bind directory '"
2846 << bind_dir << "'. All user-defined key bindings will be lost." << endl;
2849 if (!bind_dir.isDirWritable()) {
2850 lyxerr << "LyX could not write to the user bind directory '"
2851 << bind_dir << "'. All user-defined key bindings will be lost." << endl;
2854 FileName user_bind_file(bind_dir.absFileName() + "/user.bind");
2855 user_unbind_.write(user_bind_file.toFilesystemEncoding(), false, true);
2856 user_bind_.write(user_bind_file.toFilesystemEncoding(), true, false);
2857 // immediately apply the keybindings. Why this is not done before?
2858 // The good thing is that the menus are updated automatically.
2859 theTopLevelKeymap().clear();
2860 theTopLevelKeymap().read("site");
2861 theTopLevelKeymap().read(rc.bind_file, 0, KeyMap::Fallback);
2862 theTopLevelKeymap().read("user", 0, KeyMap::MissingOK);
2866 void PrefShortcuts::updateRC(LyXRC const & rc)
2868 bindFileED->setText(toqstr(external_path(rc.bind_file)));
2870 system_bind_.clear();
2872 user_unbind_.clear();
2873 system_bind_.read("site");
2874 system_bind_.read(rc.bind_file);
2875 // \unbind in user.bind is added to user_unbind_
2876 user_bind_.read("user", &user_unbind_, KeyMap::MissingOK);
2877 updateShortcutsTW();
2881 void PrefShortcuts::updateShortcutsTW()
2883 shortcutsTW->clear();
2885 editItem_ = new QTreeWidgetItem(shortcutsTW);
2886 editItem_->setText(0, qt_("Cursor, Mouse and Editing Functions"));
2887 editItem_->setFlags(editItem_->flags() & ~Qt::ItemIsSelectable);
2889 mathItem_ = new QTreeWidgetItem(shortcutsTW);
2890 mathItem_->setText(0, qt_("Mathematical Symbols"));
2891 mathItem_->setFlags(mathItem_->flags() & ~Qt::ItemIsSelectable);
2893 bufferItem_ = new QTreeWidgetItem(shortcutsTW);
2894 bufferItem_->setText(0, qt_("Document and Window"));
2895 bufferItem_->setFlags(bufferItem_->flags() & ~Qt::ItemIsSelectable);
2897 layoutItem_ = new QTreeWidgetItem(shortcutsTW);
2898 layoutItem_->setText(0, qt_("Font, Layouts and Textclasses"));
2899 layoutItem_->setFlags(layoutItem_->flags() & ~Qt::ItemIsSelectable);
2901 systemItem_ = new QTreeWidgetItem(shortcutsTW);
2902 systemItem_->setText(0, qt_("System and Miscellaneous"));
2903 systemItem_->setFlags(systemItem_->flags() & ~Qt::ItemIsSelectable);
2905 // listBindings(unbound=true) lists all bound and unbound lfuns
2906 // Items in this list is tagged by its source.
2907 KeyMap::BindingList bindinglist = system_bind_.listBindings(true,
2909 KeyMap::BindingList user_bindinglist = user_bind_.listBindings(false,
2911 KeyMap::BindingList user_unbindinglist = user_unbind_.listBindings(false,
2912 KeyMap::UserUnbind);
2913 bindinglist.insert(bindinglist.end(), user_bindinglist.begin(),
2914 user_bindinglist.end());
2915 bindinglist.insert(bindinglist.end(), user_unbindinglist.begin(),
2916 user_unbindinglist.end());
2918 KeyMap::BindingList::const_iterator it = bindinglist.begin();
2919 KeyMap::BindingList::const_iterator it_end = bindinglist.end();
2920 for (; it != it_end; ++it)
2921 insertShortcutItem(it->request, it->sequence, it->tag);
2923 shortcutsTW->sortItems(0, Qt::AscendingOrder);
2924 on_shortcutsTW_itemSelectionChanged();
2925 on_searchLE_textEdited();
2926 shortcutsTW->resizeColumnToContents(0);
2931 KeyMap::ItemType PrefShortcuts::itemType(QTreeWidgetItem & item)
2933 return static_cast<KeyMap::ItemType>(item.data(0, Qt::UserRole).toInt());
2938 bool PrefShortcuts::isAlwaysHidden(QTreeWidgetItem & item)
2940 // Hide rebound system settings that are empty
2941 return itemType(item) == KeyMap::UserUnbind && item.text(1).isEmpty();
2945 void PrefShortcuts::setItemType(QTreeWidgetItem * item, KeyMap::ItemType tag)
2947 item->setData(0, Qt::UserRole, QVariant(tag));
2951 case KeyMap::System:
2953 case KeyMap::UserBind:
2956 case KeyMap::UserUnbind:
2957 font.setStrikeOut(true);
2959 // this item is not displayed now.
2960 case KeyMap::UserExtraUnbind:
2961 font.setStrikeOut(true);
2964 item->setHidden(isAlwaysHidden(*item));
2965 item->setFont(1, font);
2969 QTreeWidgetItem * PrefShortcuts::insertShortcutItem(FuncRequest const & lfun,
2970 KeySequence const & seq, KeyMap::ItemType tag)
2972 FuncCode const action = lfun.action();
2973 string const action_name = lyxaction.getActionName(action);
2974 QString const lfun_name = toqstr(from_utf8(action_name)
2975 + ' ' + lfun.argument());
2976 QString const shortcut = toqstr(seq.print(KeySequence::ForGui));
2978 QTreeWidgetItem * newItem = 0;
2979 // for unbind items, try to find an existing item in the system bind list
2980 if (tag == KeyMap::UserUnbind) {
2981 QList<QTreeWidgetItem*> const items = shortcutsTW->findItems(lfun_name,
2982 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 0);
2983 for (int i = 0; i < items.size(); ++i) {
2984 if (items[i]->text(1) == shortcut) {
2989 // if not found, this unbind item is KeyMap::UserExtraUnbind
2990 // Such an item is not displayed to avoid confusion (what is
2991 // unmatched removed?).
2997 switch(lyxaction.getActionType(action)) {
2998 case LyXAction::Hidden:
3000 case LyXAction::Edit:
3001 newItem = new QTreeWidgetItem(editItem_);
3003 case LyXAction::Math:
3004 newItem = new QTreeWidgetItem(mathItem_);
3006 case LyXAction::Buffer:
3007 newItem = new QTreeWidgetItem(bufferItem_);
3009 case LyXAction::Layout:
3010 newItem = new QTreeWidgetItem(layoutItem_);
3012 case LyXAction::System:
3013 newItem = new QTreeWidgetItem(systemItem_);
3016 // this should not happen
3017 newItem = new QTreeWidgetItem(shortcutsTW);
3021 newItem->setText(0, lfun_name);
3022 newItem->setText(1, shortcut);
3023 // record BindFile representation to recover KeySequence when needed.
3024 newItem->setData(1, Qt::UserRole, toqstr(seq.print(KeySequence::BindFile)));
3025 setItemType(newItem, tag);
3030 void PrefShortcuts::on_shortcutsTW_itemSelectionChanged()
3032 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
3033 removePB->setEnabled(!items.isEmpty() && !items[0]->text(1).isEmpty());
3034 modifyPB->setEnabled(!items.isEmpty());
3035 if (items.isEmpty())
3038 if (itemType(*items[0]) == KeyMap::UserUnbind)
3039 removePB->setText(qt_("Res&tore"));
3041 removePB->setText(qt_("Remo&ve"));
3045 void PrefShortcuts::on_shortcutsTW_itemDoubleClicked()
3051 void PrefShortcuts::modifyShortcut()
3053 QTreeWidgetItem * item = shortcutsTW->currentItem();
3054 if (item->flags() & Qt::ItemIsSelectable) {
3055 shortcut_->lfunLE->setText(item->text(0));
3056 save_lfun_ = item->text(0).trimmed();
3057 shortcut_->shortcutWG->setText(item->text(1));
3059 seq.parse(fromqstr(item->data(1, Qt::UserRole).toString()));
3060 shortcut_->shortcutWG->setKeySequence(seq);
3061 shortcut_->shortcutWG->setFocus();
3067 void PrefShortcuts::unhideEmpty(QString const & lfun, bool select)
3069 // list of items that match lfun
3070 QList<QTreeWidgetItem*> items = shortcutsTW->findItems(lfun,
3071 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 0);
3072 for (int i = 0; i < items.size(); ++i) {
3073 QTreeWidgetItem * item = items[i];
3074 if (isAlwaysHidden(*item)) {
3075 setItemType(item, KeyMap::System);
3077 shortcutsTW->setCurrentItem(item);
3084 void PrefShortcuts::removeShortcut()
3086 // it seems that only one item can be selected, but I am
3087 // removing all selected items anyway.
3088 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
3089 for (int i = 0; i < items.size(); ++i) {
3090 string shortcut = fromqstr(items[i]->data(1, Qt::UserRole).toString());
3091 string lfun = fromqstr(items[i]->text(0));
3092 FuncRequest func = lyxaction.lookupFunc(lfun);
3094 switch (itemType(*items[i])) {
3095 case KeyMap::System: {
3096 // for system bind, we do not touch the item
3097 // but add an user unbind item
3098 user_unbind_.bind(shortcut, func);
3099 setItemType(items[i], KeyMap::UserUnbind);
3100 removePB->setText(qt_("Res&tore"));
3103 case KeyMap::UserBind: {
3104 // for user_bind, we remove this bind
3105 QTreeWidgetItem * parent = items[i]->parent();
3106 int itemIdx = parent->indexOfChild(items[i]);
3107 parent->takeChild(itemIdx);
3109 shortcutsTW->scrollToItem(parent->child(itemIdx - 1));
3111 shortcutsTW->scrollToItem(parent);
3112 user_bind_.unbind(shortcut, func);
3113 // If this user binding hid an empty system binding, unhide the
3114 // latter and select it.
3115 unhideEmpty(items[i]->text(0), true);
3118 case KeyMap::UserUnbind: {
3119 // for user_unbind, we remove the unbind, and the item
3120 // become KeyMap::System again.
3122 seq.parse(shortcut);
3123 // Ask the user to replace current binding
3124 if (!validateNewShortcut(func, seq, QString()))
3126 user_unbind_.unbind(shortcut, func);
3127 setItemType(items[i], KeyMap::System);
3128 removePB->setText(qt_("Remo&ve"));
3131 case KeyMap::UserExtraUnbind: {
3132 // for user unbind that is not in system bind file,
3133 // remove this unbind file
3134 QTreeWidgetItem * parent = items[i]->parent();
3135 parent->takeChild(parent->indexOfChild(items[i]));
3136 user_unbind_.unbind(shortcut, func);
3143 void PrefShortcuts::deactivateShortcuts(QList<QTreeWidgetItem*> const & items)
3145 for (int i = 0; i < items.size(); ++i) {
3146 string shortcut = fromqstr(items[i]->data(1, Qt::UserRole).toString());
3147 string lfun = fromqstr(items[i]->text(0));
3148 FuncRequest func = lyxaction.lookupFunc(lfun);
3150 switch (itemType(*items[i])) {
3151 case KeyMap::System:
3152 // for system bind, we do not touch the item
3153 // but add an user unbind item
3154 user_unbind_.bind(shortcut, func);
3155 setItemType(items[i], KeyMap::UserUnbind);
3158 case KeyMap::UserBind: {
3159 // for user_bind, we remove this bind
3160 QTreeWidgetItem * parent = items[i]->parent();
3161 int itemIdx = parent->indexOfChild(items[i]);
3162 parent->takeChild(itemIdx);
3163 user_bind_.unbind(shortcut, func);
3164 unhideEmpty(items[i]->text(0), false);
3174 void PrefShortcuts::selectBind()
3176 QString file = form_->browsebind(internalPath(bindFileED->text()));
3177 if (!file.isEmpty()) {
3178 bindFileED->setText(file);
3179 system_bind_ = KeyMap();
3180 system_bind_.read(fromqstr(file));
3181 updateShortcutsTW();
3186 void PrefShortcuts::on_modifyPB_pressed()
3192 void PrefShortcuts::on_newPB_pressed()
3194 shortcut_->lfunLE->clear();
3195 shortcut_->shortcutWG->reset();
3196 save_lfun_ = QString();
3201 void PrefShortcuts::on_removePB_pressed()
3208 void PrefShortcuts::on_searchLE_textEdited()
3210 if (searchLE->text().isEmpty()) {
3211 // show all hidden items
3212 QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Hidden);
3214 shortcutsTW->setItemHidden(*it, isAlwaysHidden(**it));
3215 // close all categories
3216 for (int i = 0; i < shortcutsTW->topLevelItemCount(); ++i)
3217 shortcutsTW->collapseItem(shortcutsTW->topLevelItem(i));
3220 // search both columns
3221 QList<QTreeWidgetItem *> matched = shortcutsTW->findItems(searchLE->text(),
3222 Qt::MatchFlags(Qt::MatchContains | Qt::MatchRecursive), 0);
3223 matched += shortcutsTW->findItems(searchLE->text(),
3224 Qt::MatchFlags(Qt::MatchContains | Qt::MatchRecursive), 1);
3226 // hide everyone (to avoid searching in matched QList repeatedly
3227 QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Selectable);
3229 shortcutsTW->setItemHidden(*it++, true);
3230 // show matched items
3231 for (int i = 0; i < matched.size(); ++i)
3232 if (!isAlwaysHidden(*matched[i])) {
3233 shortcutsTW->setItemHidden(matched[i], false);
3234 shortcutsTW->setItemExpanded(matched[i]->parent(), true);
3239 docstring makeCmdString(FuncRequest const & f)
3241 docstring actionStr = from_ascii(lyxaction.getActionName(f.action()));
3242 if (!f.argument().empty())
3243 actionStr += " " + f.argument();
3248 FuncRequest PrefShortcuts::currentBinding(KeySequence const & k)
3250 FuncRequest res = user_bind_.getBinding(k);
3251 if (res.action() != LFUN_UNKNOWN_ACTION)
3253 res = system_bind_.getBinding(k);
3254 // Check if it is unbound. Note: user_unbind_ can only unbind one
3255 // FuncRequest per key sequence.
3256 if (user_unbind_.getBinding(k) == res)
3257 return FuncRequest::unknown;
3262 bool PrefShortcuts::validateNewShortcut(FuncRequest const & func,
3263 KeySequence const & k,
3264 QString const & lfun_to_modify)
3266 if (func.action() == LFUN_UNKNOWN_ACTION) {
3267 Alert::error(_("Failed to create shortcut"),
3268 _("Unknown or invalid LyX function"));
3272 // It is not currently possible to bind Hidden lfuns such as self-insert. In
3273 // the future, to remove this limitation, see GuiPrefs::insertShortcutItem
3274 // and how it is used in GuiPrefs::shortcutOkPressed.
3275 if (lyxaction.getActionType(func.action()) == LyXAction::Hidden) {
3276 Alert::error(_("Failed to create shortcut"),
3277 _("This LyX function is hidden and cannot be bound."));
3281 if (k.length() == 0) {
3282 Alert::error(_("Failed to create shortcut"),
3283 _("Invalid or empty key sequence"));
3287 FuncRequest oldBinding = currentBinding(k);
3288 if (oldBinding == func)
3289 // nothing to change
3292 // make sure this key isn't already bound---and, if so, prompt user
3293 // (exclude the lfun the user already wants to modify)
3294 docstring const action_string = makeCmdString(oldBinding);
3295 if (oldBinding.action() != LFUN_UNKNOWN_ACTION
3296 && lfun_to_modify != toqstr(action_string)) {
3297 docstring const new_action_string = makeCmdString(func);
3298 docstring const text = bformat(_("Shortcut `%1$s' is already bound to "
3300 "Are you sure you want to unbind the "
3301 "current shortcut and bind it to %3$s?"),
3302 k.print(KeySequence::ForGui), action_string,
3304 int ret = Alert::prompt(_("Redefine shortcut?"),
3305 text, 0, 1, _("&Redefine"), _("&Cancel"));
3308 QString const sequence_text = toqstr(k.print(KeySequence::ForGui));
3309 QList<QTreeWidgetItem*> items = shortcutsTW->findItems(sequence_text,
3310 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 1);
3311 deactivateShortcuts(items);
3317 void PrefShortcuts::shortcutOkPressed()
3319 QString const new_lfun = shortcut_->lfunLE->text();
3320 FuncRequest func = lyxaction.lookupFunc(fromqstr(new_lfun));
3321 KeySequence k = shortcut_->shortcutWG->getKeySequence();
3323 // save_lfun_ contains the text of the lfun to modify, if the user clicked
3324 // "modify", or is empty if they clicked "new" (which I do not really like)
3325 if (!validateNewShortcut(func, k, save_lfun_))
3328 if (!save_lfun_.isEmpty()) {
3329 // real modification of the lfun's shortcut,
3330 // so remove the previous one
3331 QList<QTreeWidgetItem*> to_modify = shortcutsTW->selectedItems();
3332 deactivateShortcuts(to_modify);
3335 shortcut_->accept();
3337 QTreeWidgetItem * item = insertShortcutItem(func, k, KeyMap::UserBind);
3339 user_bind_.bind(&k, func);
3340 shortcutsTW->sortItems(0, Qt::AscendingOrder);
3341 shortcutsTW->setItemExpanded(item->parent(), true);
3342 shortcutsTW->setCurrentItem(item);
3343 shortcutsTW->scrollToItem(item);
3345 Alert::error(_("Failed to create shortcut"),
3346 _("Can not insert shortcut to the list"));
3352 void PrefShortcuts::shortcutCancelPressed()
3354 shortcut_->shortcutWG->reset();
3358 void PrefShortcuts::shortcutClearPressed()
3360 shortcut_->shortcutWG->reset();
3364 void PrefShortcuts::shortcutRemovePressed()
3366 shortcut_->shortcutWG->removeFromSequence();
3370 /////////////////////////////////////////////////////////////////////
3374 /////////////////////////////////////////////////////////////////////
3376 PrefIdentity::PrefIdentity(GuiPreferences * form)
3377 : PrefModule(QString(), N_("Identity"), form)
3381 connect(nameED, SIGNAL(textChanged(QString)),
3382 this, SIGNAL(changed()));
3383 connect(emailED, SIGNAL(textChanged(QString)),
3384 this, SIGNAL(changed()));
3386 nameED->setValidator(new NoNewLineValidator(nameED));
3387 emailED->setValidator(new NoNewLineValidator(emailED));
3391 void PrefIdentity::applyRC(LyXRC & rc) const
3393 rc.user_name = fromqstr(nameED->text());
3394 rc.user_email = fromqstr(emailED->text());
3398 void PrefIdentity::updateRC(LyXRC const & rc)
3400 nameED->setText(toqstr(rc.user_name));
3401 emailED->setText(toqstr(rc.user_email));
3406 /////////////////////////////////////////////////////////////////////
3410 /////////////////////////////////////////////////////////////////////
3412 GuiPreferences::GuiPreferences(GuiView & lv)
3413 : GuiDialog(lv, "prefs", qt_("Preferences")), update_screen_font_(false),
3414 update_previews_(false)
3418 QDialog::setModal(false);
3420 connect(buttonBox, SIGNAL(clicked(QAbstractButton *)),
3421 this, SLOT(slotButtonBox(QAbstractButton *)));
3423 addModule(new PrefUserInterface(this));
3424 addModule(new PrefDocHandling(this));
3425 addModule(new PrefEdit(this));
3426 addModule(new PrefShortcuts(this));
3427 PrefScreenFonts * screenfonts = new PrefScreenFonts(this);
3428 connect(this, SIGNAL(prefsApplied(LyXRC const &)),
3429 screenfonts, SLOT(updateScreenFontSizes(LyXRC const &)));
3430 addModule(screenfonts);
3431 addModule(new PrefColors(this));
3432 addModule(new PrefDisplay(this));
3433 addModule(new PrefInput(this));
3434 addModule(new PrefCompletion(this));
3436 addModule(new PrefPaths(this));
3438 addModule(new PrefIdentity(this));
3440 addModule(new PrefLanguage(this));
3441 addModule(new PrefSpellchecker(this));
3443 //for strftime validator
3444 PrefOutput * output = new PrefOutput(this);
3446 addModule(new PrefLatex(this));
3448 PrefConverters * converters = new PrefConverters(this);
3449 PrefFileformats * formats = new PrefFileformats(this);
3450 connect(formats, SIGNAL(formatsChanged()),
3451 converters, SLOT(updateGui()));
3452 addModule(converters);
3455 prefsPS->setCurrentPanel("User Interface");
3456 // FIXME: hack to work around resizing bug in Qt >= 4.2
3457 // bug verified with Qt 4.2.{0-3} (JSpitzm)
3458 #if QT_VERSION >= 0x040200
3459 prefsPS->updateGeometry();
3462 bc().setPolicy(ButtonPolicy::PreferencesPolicy);
3463 bc().setOK(buttonBox->button(QDialogButtonBox::Ok));
3464 bc().setApply(buttonBox->button(QDialogButtonBox::Apply));
3465 bc().setCancel(buttonBox->button(QDialogButtonBox::Cancel));
3466 bc().setRestore(buttonBox->button(QDialogButtonBox::Reset));
3468 // initialize the strftime validator
3469 bc().addCheckedLineEdit(output->DateED);
3473 void GuiPreferences::addModule(PrefModule * module)
3475 LASSERT(module, return);
3476 if (module->category().isEmpty())
3477 prefsPS->addPanel(module, module->title());
3479 prefsPS->addPanel(module, module->title(), module->category());
3480 connect(module, SIGNAL(changed()), this, SLOT(change_adaptor()));
3481 modules_.push_back(module);
3485 void GuiPreferences::change_adaptor()
3491 void GuiPreferences::applyRC(LyXRC & rc) const
3493 size_t end = modules_.size();
3494 for (size_t i = 0; i != end; ++i)
3495 modules_[i]->applyRC(rc);
3499 void GuiPreferences::updateRC(LyXRC const & rc)
3501 size_t const end = modules_.size();
3502 for (size_t i = 0; i != end; ++i)
3503 modules_[i]->updateRC(rc);
3507 void GuiPreferences::applyView()
3513 bool GuiPreferences::initialiseParams(string const &)
3516 formats_ = theFormats();
3517 converters_ = theConverters();
3518 converters_.update(formats_);
3519 movers_ = theMovers();
3521 update_screen_font_ = false;
3522 update_previews_ = false;
3525 // Make sure that the bc is in the INITIAL state
3526 if (bc().policy().buttonStatus(ButtonPolicy::RESTORE))
3533 void GuiPreferences::dispatchParams()
3536 rc_.write(ss, true);
3537 dispatch(FuncRequest(LFUN_LYXRC_APPLY, ss.str()));
3538 // issue prefsApplied signal. This will update the
3539 // localized screen font sizes.
3541 // FIXME: these need lfuns
3543 Author const & author =
3544 Author(from_utf8(rc_.user_name), from_utf8(rc_.user_email));
3545 theBufferList().recordCurrentAuthor(author);
3547 theFormats() = formats_;
3549 theConverters() = converters_;
3550 theConverters().update(formats_);
3551 theConverters().buildGraph();
3552 theBufferList().invalidateConverterCache();
3554 theMovers() = movers_;
3556 vector<string>::const_iterator it = colors_.begin();
3557 vector<string>::const_iterator const end = colors_.end();
3558 for (; it != end; ++it)
3559 dispatch(FuncRequest(LFUN_SET_COLOR, *it));
3562 if (update_screen_font_) {
3563 dispatch(FuncRequest(LFUN_SCREEN_FONT_UPDATE));
3564 // resets flag in case second apply in same dialog
3565 update_screen_font_ = false;
3568 if (update_previews_) {
3569 // resets flag in case second apply in same dialog
3570 theBufferList().updatePreviews();
3571 update_previews_ = false;
3575 if (!tempSaveCB->isChecked())
3576 dispatch(FuncRequest(LFUN_PREFERENCES_SAVE));
3580 void GuiPreferences::setColor(ColorCode col, QString const & hex)
3582 colors_.push_back(lcolor.getLyXName(col) + ' ' + fromqstr(hex));
3586 void GuiPreferences::updateScreenFonts()
3588 update_screen_font_ = true;
3592 void GuiPreferences::updatePreviews()
3594 update_previews_ = true;
3598 QString GuiPreferences::browsebind(QString const & file) const
3600 return browseLibFile("bind", file, "bind", qt_("Choose bind file"),
3601 QStringList(qt_("LyX bind files (*.bind)")));
3605 QString GuiPreferences::browseUI(QString const & file) const
3607 return browseLibFile("ui", file, "ui", qt_("Choose UI file"),
3608 QStringList(qt_("LyX UI files (*.ui)")));
3612 QString GuiPreferences::browsekbmap(QString const & file) const
3614 return browseLibFile("kbd", file, "kmap", qt_("Choose keyboard map"),
3615 QStringList(qt_("LyX keyboard maps (*.kmap)")));
3619 QString GuiPreferences::browse(QString const & file,
3620 QString const & title) const
3622 return browseFile(file, title, QStringList(), true);
3626 Dialog * createGuiPreferences(GuiView & lv) { return new GuiPreferences(lv); }
3629 } // namespace frontend
3632 #include "moc_GuiPrefs.cpp"