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|#S#s");
143 toqstr(addName(package().system_support().absFileName(), fromqstr(dir)));
145 QString const label2 = qt_("User files|#U#u");
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, foundry;
291 parseFontName(cb->itemText(i), name, 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, foundry;
305 parseFontName(cb->itemText(i), name, foundry);
306 if (compare_ascii_no_case(name, 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 latexEncodingED->setValidator(new NoNewLineValidator(latexEncodingED));
729 latexDviPaperED->setValidator(new NoNewLineValidator(latexDviPaperED));
730 latexBibtexED->setValidator(new NoNewLineValidator(latexBibtexED));
731 latexJBibtexED->setValidator(new NoNewLineValidator(latexJBibtexED));
732 latexIndexED->setValidator(new NoNewLineValidator(latexIndexED));
733 latexJIndexED->setValidator(new NoNewLineValidator(latexJIndexED));
734 latexNomenclED->setValidator(new NoNewLineValidator(latexNomenclED));
735 latexChecktexED->setValidator(new NoNewLineValidator(latexChecktexED));
737 connect(latexEncodingCB, SIGNAL(clicked()),
738 this, SIGNAL(changed()));
739 connect(latexEncodingED, SIGNAL(textChanged(QString)),
740 this, SIGNAL(changed()));
741 connect(latexChecktexED, SIGNAL(textChanged(QString)),
742 this, SIGNAL(changed()));
743 connect(latexBibtexCO, SIGNAL(activated(int)),
744 this, SIGNAL(changed()));
745 connect(latexBibtexED, SIGNAL(textChanged(QString)),
746 this, SIGNAL(changed()));
747 connect(latexJBibtexCO, SIGNAL(activated(int)),
748 this, SIGNAL(changed()));
749 connect(latexJBibtexED, SIGNAL(textChanged(QString)),
750 this, SIGNAL(changed()));
751 connect(latexIndexCO, SIGNAL(activated(int)),
752 this, SIGNAL(changed()));
753 connect(latexIndexED, SIGNAL(textChanged(QString)),
754 this, SIGNAL(changed()));
755 connect(latexJIndexED, SIGNAL(textChanged(QString)),
756 this, SIGNAL(changed()));
757 connect(latexAutoresetCB, SIGNAL(clicked()),
758 this, SIGNAL(changed()));
759 connect(latexDviPaperED, SIGNAL(textChanged(QString)),
760 this, SIGNAL(changed()));
761 connect(latexNomenclED, SIGNAL(textChanged(QString)),
762 this, SIGNAL(changed()));
764 #if defined(__CYGWIN__) || defined(_WIN32)
765 pathCB->setVisible(true);
766 connect(pathCB, SIGNAL(clicked()),
767 this, SIGNAL(changed()));
769 pathCB->setVisible(false);
774 void PrefLatex::on_latexEncodingCB_stateChanged(int state)
776 latexEncodingED->setEnabled(state == Qt::Checked);
780 void PrefLatex::on_latexBibtexCO_activated(int n)
782 QString const bibtex = latexBibtexCO->itemData(n).toString();
783 if (bibtex.isEmpty()) {
784 latexBibtexED->clear();
785 latexBibtexOptionsLA->setText(qt_("C&ommand:"));
788 for (LyXRC::CommandSet::const_iterator it = bibtex_alternatives.begin();
789 it != bibtex_alternatives.end(); ++it) {
790 QString const bib = toqstr(*it);
791 int ind = bib.indexOf(" ");
792 QString sel_command = bib.left(ind);
793 QString sel_options = ind < 0 ? QString() : bib.mid(ind + 1);
794 if (bibtex == sel_command) {
796 latexBibtexED->clear();
798 latexBibtexED->setText(sel_options.trimmed());
801 latexBibtexOptionsLA->setText(qt_("&Options:"));
805 void PrefLatex::on_latexJBibtexCO_activated(int n)
807 QString const jbibtex = latexJBibtexCO->itemData(n).toString();
808 if (jbibtex.isEmpty()) {
809 latexJBibtexED->clear();
810 latexJBibtexOptionsLA->setText(qt_("Co&mmand:"));
813 for (LyXRC::CommandSet::const_iterator it = jbibtex_alternatives.begin();
814 it != jbibtex_alternatives.end(); ++it) {
815 QString const bib = toqstr(*it);
816 int ind = bib.indexOf(" ");
817 QString sel_command = bib.left(ind);
818 QString sel_options = ind < 0 ? QString() : bib.mid(ind + 1);
819 if (jbibtex == sel_command) {
821 latexJBibtexED->clear();
823 latexJBibtexED->setText(sel_options.trimmed());
826 latexJBibtexOptionsLA->setText(qt_("Opt&ions:"));
830 void PrefLatex::on_latexIndexCO_activated(int n)
832 QString const index = latexIndexCO->itemData(n).toString();
833 if (index.isEmpty()) {
834 latexIndexED->clear();
835 latexIndexOptionsLA->setText(qt_("Co&mmand:"));
838 for (LyXRC::CommandSet::const_iterator it = index_alternatives.begin();
839 it != index_alternatives.end(); ++it) {
840 QString const idx = toqstr(*it);
841 int ind = idx.indexOf(" ");
842 QString sel_command = idx.left(ind);
843 QString sel_options = ind < 0 ? QString() : idx.mid(ind + 1);
844 if (index == sel_command) {
846 latexIndexED->clear();
848 latexIndexED->setText(sel_options.trimmed());
851 latexIndexOptionsLA->setText(qt_("Op&tions:"));
855 void PrefLatex::applyRC(LyXRC & rc) const
857 // If bibtex is not empty, bibopt contains the options, otherwise
858 // it is a customized bibtex command with options.
859 QString const bibtex = latexBibtexCO->itemData(
860 latexBibtexCO->currentIndex()).toString();
861 QString const bibopt = latexBibtexED->text();
862 if (bibtex.isEmpty())
863 rc.bibtex_command = fromqstr(bibopt);
864 else if (bibopt.isEmpty())
865 rc.bibtex_command = fromqstr(bibtex);
867 rc.bibtex_command = fromqstr(bibtex) + " " + fromqstr(bibopt);
869 // If jbibtex is not empty, jbibopt contains the options, otherwise
870 // it is a customized bibtex command with options.
871 QString const jbibtex = latexJBibtexCO->itemData(
872 latexJBibtexCO->currentIndex()).toString();
873 QString const jbibopt = latexJBibtexED->text();
874 if (jbibtex.isEmpty())
875 rc.jbibtex_command = fromqstr(jbibopt);
876 else if (jbibopt.isEmpty())
877 rc.jbibtex_command = fromqstr(jbibtex);
879 rc.jbibtex_command = fromqstr(jbibtex) + " " + fromqstr(jbibopt);
881 // If index is not empty, idxopt contains the options, otherwise
882 // it is a customized index command with options.
883 QString const index = latexIndexCO->itemData(
884 latexIndexCO->currentIndex()).toString();
885 QString const idxopt = latexIndexED->text();
887 rc.index_command = fromqstr(idxopt);
888 else if (idxopt.isEmpty())
889 rc.index_command = fromqstr(index);
891 rc.index_command = fromqstr(index) + " " + fromqstr(idxopt);
893 if (latexEncodingCB->isChecked())
894 rc.fontenc = fromqstr(latexEncodingED->text());
896 rc.fontenc = "default";
897 rc.chktex_command = fromqstr(latexChecktexED->text());
898 rc.jindex_command = fromqstr(latexJIndexED->text());
899 rc.nomencl_command = fromqstr(latexNomenclED->text());
900 rc.auto_reset_options = latexAutoresetCB->isChecked();
901 rc.view_dvi_paper_option = fromqstr(latexDviPaperED->text());
902 #if defined(__CYGWIN__) || defined(_WIN32)
903 rc.windows_style_tex_paths = pathCB->isChecked();
908 void PrefLatex::updateRC(LyXRC const & rc)
910 latexBibtexCO->clear();
912 latexBibtexCO->addItem(qt_("Automatic"), "automatic");
913 latexBibtexCO->addItem(qt_("Custom"), QString());
914 for (LyXRC::CommandSet::const_iterator it = rc.bibtex_alternatives.begin();
915 it != rc.bibtex_alternatives.end(); ++it) {
916 QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
917 latexBibtexCO->addItem(command, command);
920 bibtex_alternatives = rc.bibtex_alternatives;
922 QString const bib = toqstr(rc.bibtex_command);
923 int ind = bib.indexOf(" ");
924 QString sel_command = bib.left(ind);
925 QString sel_options = ind < 0 ? QString() : bib.mid(ind + 1);
927 int pos = latexBibtexCO->findData(sel_command);
929 latexBibtexCO->setCurrentIndex(pos);
930 latexBibtexED->setText(sel_options.trimmed());
931 latexBibtexOptionsLA->setText(qt_("&Options:"));
933 latexBibtexED->setText(toqstr(rc.bibtex_command));
934 latexBibtexCO->setCurrentIndex(0);
935 latexBibtexOptionsLA->setText(qt_("C&ommand:"));
938 latexJBibtexCO->clear();
940 latexJBibtexCO->addItem(qt_("Automatic"), "automatic");
941 latexJBibtexCO->addItem(qt_("Custom"), QString());
942 for (LyXRC::CommandSet::const_iterator it = rc.jbibtex_alternatives.begin();
943 it != rc.jbibtex_alternatives.end(); ++it) {
944 QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
945 latexJBibtexCO->addItem(command, command);
948 jbibtex_alternatives = rc.jbibtex_alternatives;
950 QString const jbib = toqstr(rc.jbibtex_command);
951 ind = jbib.indexOf(" ");
952 sel_command = jbib.left(ind);
953 sel_options = ind < 0 ? QString() : jbib.mid(ind + 1);
955 pos = latexJBibtexCO->findData(sel_command);
957 latexJBibtexCO->setCurrentIndex(pos);
958 latexJBibtexED->setText(sel_options.trimmed());
959 latexJBibtexOptionsLA->setText(qt_("Opt&ions:"));
961 latexJBibtexED->setText(toqstr(rc.bibtex_command));
962 latexJBibtexCO->setCurrentIndex(0);
963 latexJBibtexOptionsLA->setText(qt_("Co&mmand:"));
966 latexIndexCO->clear();
968 latexIndexCO->addItem(qt_("Custom"), QString());
969 for (LyXRC::CommandSet::const_iterator it = rc.index_alternatives.begin();
970 it != rc.index_alternatives.end(); ++it) {
971 QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
972 latexIndexCO->addItem(command, command);
975 index_alternatives = rc.index_alternatives;
977 QString const idx = toqstr(rc.index_command);
978 ind = idx.indexOf(" ");
979 sel_command = idx.left(ind);
980 sel_options = ind < 0 ? QString() : idx.mid(ind + 1);
982 pos = latexIndexCO->findData(sel_command);
984 latexIndexCO->setCurrentIndex(pos);
985 latexIndexED->setText(sel_options.trimmed());
986 latexIndexOptionsLA->setText(qt_("Op&tions:"));
988 latexIndexED->setText(toqstr(rc.index_command));
989 latexIndexCO->setCurrentIndex(0);
990 latexIndexOptionsLA->setText(qt_("Co&mmand:"));
993 if (rc.fontenc == "default") {
994 latexEncodingCB->setChecked(false);
995 latexEncodingED->setEnabled(false);
997 latexEncodingCB->setChecked(true);
998 latexEncodingED->setEnabled(true);
999 latexEncodingED->setText(toqstr(rc.fontenc));
1001 latexChecktexED->setText(toqstr(rc.chktex_command));
1002 latexJIndexED->setText(toqstr(rc.jindex_command));
1003 latexNomenclED->setText(toqstr(rc.nomencl_command));
1004 latexAutoresetCB->setChecked(rc.auto_reset_options);
1005 latexDviPaperED->setText(toqstr(rc.view_dvi_paper_option));
1006 #if defined(__CYGWIN__) || defined(_WIN32)
1007 pathCB->setChecked(rc.windows_style_tex_paths);
1012 /////////////////////////////////////////////////////////////////////
1016 /////////////////////////////////////////////////////////////////////
1018 PrefScreenFonts::PrefScreenFonts(GuiPreferences * form)
1019 : PrefModule(catLookAndFeel, N_("Screen Fonts"), form)
1023 connect(screenRomanCO, SIGNAL(activated(QString)),
1024 this, SLOT(selectRoman(QString)));
1025 connect(screenSansCO, SIGNAL(activated(QString)),
1026 this, SLOT(selectSans(QString)));
1027 connect(screenTypewriterCO, SIGNAL(activated(QString)),
1028 this, SLOT(selectTypewriter(QString)));
1030 QFontDatabase fontdb;
1031 QStringList families(fontdb.families());
1032 for (QStringList::Iterator it = families.begin(); it != families.end(); ++it) {
1033 screenRomanCO->addItem(*it);
1034 screenSansCO->addItem(*it);
1035 screenTypewriterCO->addItem(*it);
1037 connect(screenRomanCO, SIGNAL(activated(QString)),
1038 this, SIGNAL(changed()));
1039 connect(screenSansCO, SIGNAL(activated(QString)),
1040 this, SIGNAL(changed()));
1041 connect(screenTypewriterCO, SIGNAL(activated(QString)),
1042 this, SIGNAL(changed()));
1043 connect(screenZoomSB, SIGNAL(valueChanged(int)),
1044 this, SIGNAL(changed()));
1045 connect(screenTinyED, SIGNAL(textChanged(QString)),
1046 this, SIGNAL(changed()));
1047 connect(screenSmallestED, SIGNAL(textChanged(QString)),
1048 this, SIGNAL(changed()));
1049 connect(screenSmallerED, SIGNAL(textChanged(QString)),
1050 this, SIGNAL(changed()));
1051 connect(screenSmallED, SIGNAL(textChanged(QString)),
1052 this, SIGNAL(changed()));
1053 connect(screenNormalED, SIGNAL(textChanged(QString)),
1054 this, SIGNAL(changed()));
1055 connect(screenLargeED, SIGNAL(textChanged(QString)),
1056 this, SIGNAL(changed()));
1057 connect(screenLargerED, SIGNAL(textChanged(QString)),
1058 this, SIGNAL(changed()));
1059 connect(screenLargestED, SIGNAL(textChanged(QString)),
1060 this, SIGNAL(changed()));
1061 connect(screenHugeED, SIGNAL(textChanged(QString)),
1062 this, SIGNAL(changed()));
1063 connect(screenHugerED, SIGNAL(textChanged(QString)),
1064 this, SIGNAL(changed()));
1065 connect(pixmapCacheCB, SIGNAL(toggled(bool)),
1066 this, SIGNAL(changed()));
1068 screenTinyED->setValidator(new QDoubleValidator(screenTinyED));
1069 screenSmallestED->setValidator(new QDoubleValidator(screenSmallestED));
1070 screenSmallerED->setValidator(new QDoubleValidator(screenSmallerED));
1071 screenSmallED->setValidator(new QDoubleValidator(screenSmallED));
1072 screenNormalED->setValidator(new QDoubleValidator(screenNormalED));
1073 screenLargeED->setValidator(new QDoubleValidator(screenLargeED));
1074 screenLargerED->setValidator(new QDoubleValidator(screenLargerED));
1075 screenLargestED->setValidator(new QDoubleValidator(screenLargestED));
1076 screenHugeED->setValidator(new QDoubleValidator(screenHugeED));
1077 screenHugerED->setValidator(new QDoubleValidator(screenHugerED));
1081 void PrefScreenFonts::applyRC(LyXRC & rc) const
1083 LyXRC const oldrc = rc;
1085 parseFontName(screenRomanCO->currentText(),
1086 rc.roman_font_name, rc.roman_font_foundry);
1087 parseFontName(screenSansCO->currentText(),
1088 rc.sans_font_name, rc.sans_font_foundry);
1089 parseFontName(screenTypewriterCO->currentText(),
1090 rc.typewriter_font_name, rc.typewriter_font_foundry);
1092 rc.defaultZoom = screenZoomSB->value();
1093 rc.font_sizes[FONT_SIZE_TINY] = widgetToDoubleStr(screenTinyED);
1094 rc.font_sizes[FONT_SIZE_SCRIPT] = widgetToDoubleStr(screenSmallestED);
1095 rc.font_sizes[FONT_SIZE_FOOTNOTE] = widgetToDoubleStr(screenSmallerED);
1096 rc.font_sizes[FONT_SIZE_SMALL] = widgetToDoubleStr(screenSmallED);
1097 rc.font_sizes[FONT_SIZE_NORMAL] = widgetToDoubleStr(screenNormalED);
1098 rc.font_sizes[FONT_SIZE_LARGE] = widgetToDoubleStr(screenLargeED);
1099 rc.font_sizes[FONT_SIZE_LARGER] = widgetToDoubleStr(screenLargerED);
1100 rc.font_sizes[FONT_SIZE_LARGEST] = widgetToDoubleStr(screenLargestED);
1101 rc.font_sizes[FONT_SIZE_HUGE] = widgetToDoubleStr(screenHugeED);
1102 rc.font_sizes[FONT_SIZE_HUGER] = widgetToDoubleStr(screenHugerED);
1103 rc.use_pixmap_cache = pixmapCacheCB->isChecked();
1105 if (rc.font_sizes != oldrc.font_sizes
1106 || rc.roman_font_name != oldrc.roman_font_name
1107 || rc.sans_font_name != oldrc.sans_font_name
1108 || rc.typewriter_font_name != oldrc.typewriter_font_name
1109 || rc.defaultZoom != oldrc.defaultZoom) {
1110 // The global QPixmapCache is used in GuiPainter to cache text
1111 // painting so we must reset it in case any of the above
1112 // parameter is changed.
1113 QPixmapCache::clear();
1114 guiApp->fontLoader().update();
1115 form_->updateScreenFonts();
1120 void PrefScreenFonts::updateRC(LyXRC const & rc)
1122 setComboxFont(screenRomanCO, rc.roman_font_name,
1123 rc.roman_font_foundry);
1124 setComboxFont(screenSansCO, rc.sans_font_name,
1125 rc.sans_font_foundry);
1126 setComboxFont(screenTypewriterCO, rc.typewriter_font_name,
1127 rc.typewriter_font_foundry);
1129 selectRoman(screenRomanCO->currentText());
1130 selectSans(screenSansCO->currentText());
1131 selectTypewriter(screenTypewriterCO->currentText());
1133 screenZoomSB->setValue(rc.defaultZoom);
1134 updateScreenFontSizes(rc);
1136 pixmapCacheCB->setChecked(rc.use_pixmap_cache);
1137 #if defined(Q_WS_X11) || defined(QPA_XCB)
1138 pixmapCacheCB->setEnabled(false);
1140 pixmapCacheCB->hide();
1144 void PrefScreenFonts::updateScreenFontSizes(LyXRC const & rc)
1146 doubleToWidget(screenTinyED, rc.font_sizes[FONT_SIZE_TINY]);
1147 doubleToWidget(screenSmallestED, rc.font_sizes[FONT_SIZE_SCRIPT]);
1148 doubleToWidget(screenSmallerED, rc.font_sizes[FONT_SIZE_FOOTNOTE]);
1149 doubleToWidget(screenSmallED, rc.font_sizes[FONT_SIZE_SMALL]);
1150 doubleToWidget(screenNormalED, rc.font_sizes[FONT_SIZE_NORMAL]);
1151 doubleToWidget(screenLargeED, rc.font_sizes[FONT_SIZE_LARGE]);
1152 doubleToWidget(screenLargerED, rc.font_sizes[FONT_SIZE_LARGER]);
1153 doubleToWidget(screenLargestED, rc.font_sizes[FONT_SIZE_LARGEST]);
1154 doubleToWidget(screenHugeED, rc.font_sizes[FONT_SIZE_HUGE]);
1155 doubleToWidget(screenHugerED, rc.font_sizes[FONT_SIZE_HUGER]);
1159 void PrefScreenFonts::selectRoman(const QString & name)
1161 screenRomanFE->set(QFont(name), name);
1165 void PrefScreenFonts::selectSans(const QString & name)
1167 screenSansFE->set(QFont(name), name);
1171 void PrefScreenFonts::selectTypewriter(const QString & name)
1173 screenTypewriterFE->set(QFont(name), name);
1177 /////////////////////////////////////////////////////////////////////
1181 /////////////////////////////////////////////////////////////////////
1184 PrefColors::PrefColors(GuiPreferences * form)
1185 : PrefModule(catLookAndFeel, N_("Colors"), form)
1189 // FIXME: all of this initialization should be put into the controller.
1190 // See http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg113301.html
1191 // for some discussion of why that is not trivial.
1192 QPixmap icon(32, 32);
1193 for (int i = 0; i < Color_ignore; ++i) {
1194 ColorCode lc = static_cast<ColorCode>(i);
1195 if (lc == Color_none
1196 || lc == Color_black
1197 || lc == Color_white
1199 || lc == Color_brown
1201 || lc == Color_darkgray
1203 || lc == Color_green
1204 || lc == Color_lightgray
1206 || lc == Color_magenta
1207 || lc == Color_olive
1208 || lc == Color_orange
1210 || lc == Color_purple
1213 || lc == Color_violet
1214 || lc == Color_yellow
1215 || lc == Color_inherit
1216 || lc == Color_ignore)
1218 lcolors_.push_back(lc);
1220 qSort(lcolors_.begin(), lcolors_.end(), ColorSorter);
1221 vector<ColorCode>::const_iterator cit = lcolors_.begin();
1222 vector<ColorCode>::const_iterator const end = lcolors_.end();
1223 for (; cit != end; ++cit) {
1224 (void) new QListWidgetItem(QIcon(icon),
1225 toqstr(lcolor.getGUIName(*cit)), lyxObjectsLW);
1227 curcolors_.resize(lcolors_.size());
1228 newcolors_.resize(lcolors_.size());
1229 // End initialization
1231 connect(colorChangePB, SIGNAL(clicked()),
1232 this, SLOT(changeColor()));
1233 connect(lyxObjectsLW, SIGNAL(itemSelectionChanged()),
1234 this, SLOT(changeLyxObjectsSelection()));
1235 connect(lyxObjectsLW, SIGNAL(itemActivated(QListWidgetItem*)),
1236 this, SLOT(changeColor()));
1237 connect(syscolorsCB, SIGNAL(toggled(bool)),
1238 this, SIGNAL(changed()));
1239 connect(syscolorsCB, SIGNAL(toggled(bool)),
1240 this, SLOT(changeSysColor()));
1244 void PrefColors::applyRC(LyXRC & rc) const
1248 for (unsigned int i = 0; i < lcolors_.size(); ++i)
1249 if (curcolors_[i] != newcolors_[i])
1250 form_->setColor(lcolors_[i], newcolors_[i]);
1251 rc.use_system_colors = syscolorsCB->isChecked();
1253 if (oldrc.use_system_colors != rc.use_system_colors)
1254 guiApp->colorCache().clear();
1258 void PrefColors::updateRC(LyXRC const & rc)
1260 for (unsigned int i = 0; i < lcolors_.size(); ++i) {
1261 QColor color = QColor(guiApp->colorCache().get(lcolors_[i], false));
1262 QPixmap coloritem(32, 32);
1263 coloritem.fill(color);
1264 lyxObjectsLW->item(i)->setIcon(QIcon(coloritem));
1265 newcolors_[i] = curcolors_[i] = color.name();
1267 syscolorsCB->setChecked(rc.use_system_colors);
1268 changeLyxObjectsSelection();
1272 void PrefColors::changeColor()
1274 int const row = lyxObjectsLW->currentRow();
1280 QString const color = newcolors_[row];
1281 QColor c = QColorDialog::getColor(QColor(color), qApp->focusWidget());
1283 if (c.isValid() && c.name() != color) {
1284 newcolors_[row] = c.name();
1285 QPixmap coloritem(32, 32);
1287 lyxObjectsLW->currentItem()->setIcon(QIcon(coloritem));
1293 void PrefColors::changeSysColor()
1295 for (int row = 0 ; row < lyxObjectsLW->count() ; ++row) {
1296 // skip colors that are taken from system palette
1297 bool const disable = syscolorsCB->isChecked()
1298 && guiApp->colorCache().isSystem(lcolors_[row]);
1300 QListWidgetItem * const item = lyxObjectsLW->item(row);
1301 Qt::ItemFlags const flags = item->flags();
1304 item->setFlags(flags & ~Qt::ItemIsEnabled);
1306 item->setFlags(flags | Qt::ItemIsEnabled);
1310 void PrefColors::changeLyxObjectsSelection()
1312 colorChangePB->setDisabled(lyxObjectsLW->currentRow() < 0);
1316 /////////////////////////////////////////////////////////////////////
1320 /////////////////////////////////////////////////////////////////////
1322 PrefDisplay::PrefDisplay(GuiPreferences * form)
1323 : PrefModule(catLookAndFeel, N_("Display"), form)
1326 connect(displayGraphicsCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1327 connect(instantPreviewCO, SIGNAL(activated(int)), this, SIGNAL(changed()));
1328 connect(previewSizeSB, SIGNAL(valueChanged(double)), this, SIGNAL(changed()));
1329 connect(paragraphMarkerCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1333 void PrefDisplay::on_instantPreviewCO_currentIndexChanged(int index)
1335 previewSizeSB->setEnabled(index != 0);
1339 void PrefDisplay::applyRC(LyXRC & rc) const
1341 switch (instantPreviewCO->currentIndex()) {
1343 rc.preview = LyXRC::PREVIEW_OFF;
1346 if (rc.preview != LyXRC::PREVIEW_NO_MATH) {
1347 rc.preview = LyXRC::PREVIEW_NO_MATH;
1348 form_->updatePreviews();
1352 if (rc.preview != LyXRC::PREVIEW_ON) {
1353 rc.preview = LyXRC::PREVIEW_ON;
1354 form_->updatePreviews();
1359 rc.display_graphics = displayGraphicsCB->isChecked();
1360 rc.preview_scale_factor = previewSizeSB->value();
1361 rc.paragraph_markers = paragraphMarkerCB->isChecked();
1363 // FIXME!! The graphics cache no longer has a changeDisplay method.
1365 if (old_value != rc.display_graphics) {
1366 graphics::GCache & gc = graphics::GCache::get();
1373 void PrefDisplay::updateRC(LyXRC const & rc)
1375 switch (rc.preview) {
1376 case LyXRC::PREVIEW_OFF:
1377 instantPreviewCO->setCurrentIndex(0);
1379 case LyXRC::PREVIEW_NO_MATH :
1380 instantPreviewCO->setCurrentIndex(1);
1382 case LyXRC::PREVIEW_ON :
1383 instantPreviewCO->setCurrentIndex(2);
1387 displayGraphicsCB->setChecked(rc.display_graphics);
1388 previewSizeSB->setValue(rc.preview_scale_factor);
1389 paragraphMarkerCB->setChecked(rc.paragraph_markers);
1390 previewSizeSB->setEnabled(
1392 && rc.preview != LyXRC::PREVIEW_OFF);
1396 /////////////////////////////////////////////////////////////////////
1400 /////////////////////////////////////////////////////////////////////
1402 PrefPaths::PrefPaths(GuiPreferences * form)
1403 : PrefModule(QString(), N_("Paths"), form)
1407 connect(workingDirPB, SIGNAL(clicked()), this, SLOT(selectWorkingdir()));
1408 connect(workingDirED, SIGNAL(textChanged(QString)),
1409 this, SIGNAL(changed()));
1411 connect(templateDirPB, SIGNAL(clicked()), this, SLOT(selectTemplatedir()));
1412 connect(templateDirED, SIGNAL(textChanged(QString)),
1413 this, SIGNAL(changed()));
1415 connect(exampleDirPB, SIGNAL(clicked()), this, SLOT(selectExampledir()));
1416 connect(exampleDirED, SIGNAL(textChanged(QString)),
1417 this, SIGNAL(changed()));
1419 connect(backupDirPB, SIGNAL(clicked()), this, SLOT(selectBackupdir()));
1420 connect(backupDirED, SIGNAL(textChanged(QString)),
1421 this, SIGNAL(changed()));
1423 connect(lyxserverDirPB, SIGNAL(clicked()), this, SLOT(selectLyxPipe()));
1424 connect(lyxserverDirED, SIGNAL(textChanged(QString)),
1425 this, SIGNAL(changed()));
1427 connect(thesaurusDirPB, SIGNAL(clicked()), this, SLOT(selectThesaurusdir()));
1428 connect(thesaurusDirED, SIGNAL(textChanged(QString)),
1429 this, SIGNAL(changed()));
1431 connect(tempDirPB, SIGNAL(clicked()), this, SLOT(selectTempdir()));
1432 connect(tempDirED, SIGNAL(textChanged(QString)),
1433 this, SIGNAL(changed()));
1435 #if defined(USE_HUNSPELL)
1436 connect(hunspellDirPB, SIGNAL(clicked()), this, SLOT(selectHunspelldir()));
1437 connect(hunspellDirED, SIGNAL(textChanged(QString)),
1438 this, SIGNAL(changed()));
1440 hunspellDirPB->setEnabled(false);
1441 hunspellDirED->setEnabled(false);
1444 connect(pathPrefixED, SIGNAL(textChanged(QString)),
1445 this, SIGNAL(changed()));
1447 connect(texinputsPrefixED, SIGNAL(textChanged(QString)),
1448 this, SIGNAL(changed()));
1450 pathPrefixED->setValidator(new NoNewLineValidator(pathPrefixED));
1451 texinputsPrefixED->setValidator(new NoNewLineValidator(texinputsPrefixED));
1455 void PrefPaths::applyRC(LyXRC & rc) const
1457 rc.document_path = internal_path(fromqstr(workingDirED->text()));
1458 rc.example_path = internal_path(fromqstr(exampleDirED->text()));
1459 rc.template_path = internal_path(fromqstr(templateDirED->text()));
1460 rc.backupdir_path = internal_path(fromqstr(backupDirED->text()));
1461 rc.tempdir_path = internal_path(fromqstr(tempDirED->text()));
1462 rc.thesaurusdir_path = internal_path(fromqstr(thesaurusDirED->text()));
1463 rc.hunspelldir_path = internal_path(fromqstr(hunspellDirED->text()));
1464 rc.path_prefix = internal_path_list(fromqstr(pathPrefixED->text()));
1465 rc.texinputs_prefix = internal_path_list(fromqstr(texinputsPrefixED->text()));
1466 // FIXME: should be a checkbox only
1467 rc.lyxpipes = internal_path(fromqstr(lyxserverDirED->text()));
1471 void PrefPaths::updateRC(LyXRC const & rc)
1473 workingDirED->setText(toqstr(external_path(rc.document_path)));
1474 exampleDirED->setText(toqstr(external_path(rc.example_path)));
1475 templateDirED->setText(toqstr(external_path(rc.template_path)));
1476 backupDirED->setText(toqstr(external_path(rc.backupdir_path)));
1477 tempDirED->setText(toqstr(external_path(rc.tempdir_path)));
1478 thesaurusDirED->setText(toqstr(external_path(rc.thesaurusdir_path)));
1479 hunspellDirED->setText(toqstr(external_path(rc.hunspelldir_path)));
1480 pathPrefixED->setText(toqstr(external_path_list(rc.path_prefix)));
1481 texinputsPrefixED->setText(toqstr(external_path_list(rc.texinputs_prefix)));
1482 // FIXME: should be a checkbox only
1483 lyxserverDirED->setText(toqstr(external_path(rc.lyxpipes)));
1487 void PrefPaths::selectExampledir()
1489 QString file = browseDir(internalPath(exampleDirED->text()),
1490 qt_("Select directory for example files"));
1491 if (!file.isEmpty())
1492 exampleDirED->setText(file);
1496 void PrefPaths::selectTemplatedir()
1498 QString file = browseDir(internalPath(templateDirED->text()),
1499 qt_("Select a document templates directory"));
1500 if (!file.isEmpty())
1501 templateDirED->setText(file);
1505 void PrefPaths::selectTempdir()
1507 QString file = browseDir(internalPath(tempDirED->text()),
1508 qt_("Select a temporary directory"));
1509 if (!file.isEmpty())
1510 tempDirED->setText(file);
1514 void PrefPaths::selectBackupdir()
1516 QString file = browseDir(internalPath(backupDirED->text()),
1517 qt_("Select a backups directory"));
1518 if (!file.isEmpty())
1519 backupDirED->setText(file);
1523 void PrefPaths::selectWorkingdir()
1525 QString file = browseDir(internalPath(workingDirED->text()),
1526 qt_("Select a document directory"));
1527 if (!file.isEmpty())
1528 workingDirED->setText(file);
1532 void PrefPaths::selectThesaurusdir()
1534 QString file = browseDir(internalPath(thesaurusDirED->text()),
1535 qt_("Set the path to the thesaurus dictionaries"));
1536 if (!file.isEmpty())
1537 thesaurusDirED->setText(file);
1541 void PrefPaths::selectHunspelldir()
1543 QString file = browseDir(internalPath(hunspellDirED->text()),
1544 qt_("Set the path to the Hunspell dictionaries"));
1545 if (!file.isEmpty())
1546 hunspellDirED->setText(file);
1550 void PrefPaths::selectLyxPipe()
1552 QString file = form_->browse(internalPath(lyxserverDirED->text()),
1553 qt_("Give a filename for the LyX server pipe"));
1554 if (!file.isEmpty())
1555 lyxserverDirED->setText(file);
1559 /////////////////////////////////////////////////////////////////////
1563 /////////////////////////////////////////////////////////////////////
1565 PrefSpellchecker::PrefSpellchecker(GuiPreferences * form)
1566 : PrefModule(catLanguage, N_("Spellchecker"), form)
1570 // FIXME: this check should test the target platform (darwin)
1571 #if defined(USE_MACOSX_PACKAGING)
1572 spellcheckerCB->addItem(qt_("Native"), QString("native"));
1573 #define CONNECT_APPLESPELL
1575 #undef CONNECT_APPLESPELL
1577 #if defined(USE_ASPELL)
1578 spellcheckerCB->addItem(qt_("Aspell"), QString("aspell"));
1580 #if defined(USE_ENCHANT)
1581 spellcheckerCB->addItem(qt_("Enchant"), QString("enchant"));
1583 #if defined(USE_HUNSPELL)
1584 spellcheckerCB->addItem(qt_("Hunspell"), QString("hunspell"));
1587 #if defined(CONNECT_APPLESPELL) || defined(USE_ASPELL) || defined(USE_ENCHANT) || defined(USE_HUNSPELL)
1588 connect(spellcheckerCB, SIGNAL(currentIndexChanged(int)),
1589 this, SIGNAL(changed()));
1590 connect(altLanguageED, SIGNAL(textChanged(QString)),
1591 this, SIGNAL(changed()));
1592 connect(escapeCharactersED, SIGNAL(textChanged(QString)),
1593 this, SIGNAL(changed()));
1594 connect(compoundWordCB, SIGNAL(clicked()),
1595 this, SIGNAL(changed()));
1596 connect(spellcheckContinuouslyCB, SIGNAL(clicked()),
1597 this, SIGNAL(changed()));
1598 connect(spellcheckNotesCB, SIGNAL(clicked()),
1599 this, SIGNAL(changed()));
1601 altLanguageED->setValidator(new NoNewLineValidator(altLanguageED));
1602 escapeCharactersED->setValidator(new NoNewLineValidator(escapeCharactersED));
1604 spellcheckerCB->setEnabled(false);
1605 altLanguageED->setEnabled(false);
1606 escapeCharactersED->setEnabled(false);
1607 compoundWordCB->setEnabled(false);
1608 spellcheckContinuouslyCB->setEnabled(false);
1609 spellcheckNotesCB->setEnabled(false);
1614 void PrefSpellchecker::applyRC(LyXRC & rc) const
1616 string const speller = fromqstr(spellcheckerCB->
1617 itemData(spellcheckerCB->currentIndex()).toString());
1618 if (!speller.empty())
1619 rc.spellchecker = speller;
1620 rc.spellchecker_alt_lang = fromqstr(altLanguageED->text());
1621 rc.spellchecker_esc_chars = fromqstr(escapeCharactersED->text());
1622 rc.spellchecker_accept_compound = compoundWordCB->isChecked();
1623 rc.spellcheck_continuously = spellcheckContinuouslyCB->isChecked();
1624 rc.spellcheck_notes = spellcheckNotesCB->isChecked();
1628 void PrefSpellchecker::updateRC(LyXRC const & rc)
1630 spellcheckerCB->setCurrentIndex(
1631 spellcheckerCB->findData(toqstr(rc.spellchecker)));
1632 altLanguageED->setText(toqstr(rc.spellchecker_alt_lang));
1633 escapeCharactersED->setText(toqstr(rc.spellchecker_esc_chars));
1634 compoundWordCB->setChecked(rc.spellchecker_accept_compound);
1635 spellcheckContinuouslyCB->setChecked(rc.spellcheck_continuously);
1636 spellcheckNotesCB->setChecked(rc.spellcheck_notes);
1640 void PrefSpellchecker::on_spellcheckerCB_currentIndexChanged(int index)
1642 QString spellchecker = spellcheckerCB->itemData(index).toString();
1644 compoundWordCB->setEnabled(spellchecker == QString("aspell"));
1649 /////////////////////////////////////////////////////////////////////
1653 /////////////////////////////////////////////////////////////////////
1656 PrefConverters::PrefConverters(GuiPreferences * form)
1657 : PrefModule(catFiles, N_("Converters"), form)
1661 connect(converterNewPB, SIGNAL(clicked()),
1662 this, SLOT(updateConverter()));
1663 connect(converterRemovePB, SIGNAL(clicked()),
1664 this, SLOT(removeConverter()));
1665 connect(converterModifyPB, SIGNAL(clicked()),
1666 this, SLOT(updateConverter()));
1667 connect(convertersLW, SIGNAL(currentRowChanged(int)),
1668 this, SLOT(switchConverter()));
1669 connect(converterFromCO, SIGNAL(activated(QString)),
1670 this, SLOT(changeConverter()));
1671 connect(converterToCO, SIGNAL(activated(QString)),
1672 this, SLOT(changeConverter()));
1673 connect(converterED, SIGNAL(textEdited(QString)),
1674 this, SLOT(changeConverter()));
1675 connect(converterFlagED, SIGNAL(textEdited(QString)),
1676 this, SLOT(changeConverter()));
1677 connect(converterNewPB, SIGNAL(clicked()),
1678 this, SIGNAL(changed()));
1679 connect(converterRemovePB, SIGNAL(clicked()),
1680 this, SIGNAL(changed()));
1681 connect(converterModifyPB, SIGNAL(clicked()),
1682 this, SIGNAL(changed()));
1683 connect(maxAgeLE, SIGNAL(textEdited(QString)),
1684 this, SIGNAL(changed()));
1685 connect(needauthForbiddenCB, SIGNAL(toggled(bool)),
1686 this, SIGNAL(changed()));
1688 converterED->setValidator(new NoNewLineValidator(converterED));
1689 converterFlagED->setValidator(new NoNewLineValidator(converterFlagED));
1690 maxAgeLE->setValidator(new QDoubleValidator(0, HUGE_VAL, 6, maxAgeLE));
1691 //converterDefGB->setFocusProxy(convertersLW);
1695 void PrefConverters::applyRC(LyXRC & rc) const
1697 rc.use_converter_cache = cacheCB->isChecked();
1698 rc.use_converter_needauth_forbidden = needauthForbiddenCB->isChecked();
1699 rc.use_converter_needauth = needauthCB->isChecked();
1700 rc.converter_cache_maxage = int(widgetToDouble(maxAgeLE) * 86400.0);
1704 static void setCheckboxBlockSignals(QCheckBox *cb, bool checked) {
1705 cb->blockSignals(true);
1706 cb->setChecked(checked);
1707 cb->blockSignals(false);
1711 void PrefConverters::updateRC(LyXRC const & rc)
1713 cacheCB->setChecked(rc.use_converter_cache);
1714 needauthForbiddenCB->setChecked(rc.use_converter_needauth_forbidden);
1715 setCheckboxBlockSignals(needauthCB, rc.use_converter_needauth);
1717 doubleToWidget(maxAgeLE, (double(rc.converter_cache_maxage) / 86400.0), 'g', 6);
1722 void PrefConverters::updateGui()
1724 QString const pattern("%1 -> %2");
1725 form_->formats().sort();
1726 form_->converters().update(form_->formats());
1727 // save current selection
1730 .arg(converterFromCO->currentText())
1731 .arg(converterToCO->currentText());
1733 converterFromCO->clear();
1734 converterToCO->clear();
1736 for (Format const & f : form_->formats()) {
1737 QString const name = toqstr(translateIfPossible(f.prettyname()));
1738 converterFromCO->addItem(name);
1739 converterToCO->addItem(name);
1742 // currentRowChanged(int) is also triggered when updating the listwidget
1743 // block signals to avoid unnecessary calls to switchConverter()
1744 convertersLW->blockSignals(true);
1745 convertersLW->clear();
1747 for (Converter const & c : form_->converters()) {
1748 QString const name =
1750 .arg(toqstr(translateIfPossible(c.From()->prettyname())))
1751 .arg(toqstr(translateIfPossible(c.To()->prettyname())));
1752 int type = form_->converters().getNumber(c.From()->name(),
1754 new QListWidgetItem(name, convertersLW, type);
1756 convertersLW->sortItems(Qt::AscendingOrder);
1757 convertersLW->blockSignals(false);
1759 // restore selection
1760 if (current != pattern.arg(QString()).arg(QString())) {
1761 QList<QListWidgetItem *> const item =
1762 convertersLW->findItems(current, Qt::MatchExactly);
1763 if (!item.isEmpty())
1764 convertersLW->setCurrentItem(item.at(0));
1767 // select first element if restoring failed
1768 if (convertersLW->currentRow() == -1)
1769 convertersLW->setCurrentRow(0);
1775 void PrefConverters::switchConverter()
1777 int const cnr = convertersLW->currentItem()->type();
1778 Converter const & c(form_->converters().get(cnr));
1779 converterFromCO->setCurrentIndex(form_->formats().getNumber(c.from()));
1780 converterToCO->setCurrentIndex(form_->formats().getNumber(c.to()));
1781 converterED->setText(toqstr(c.command()));
1782 converterFlagED->setText(toqstr(c.flags()));
1788 void PrefConverters::changeConverter()
1794 void PrefConverters::updateButtons()
1796 if (form_->formats().empty())
1798 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1799 Format const & to = form_->formats().get(converterToCO->currentIndex());
1800 int const sel = form_->converters().getNumber(from.name(), to.name());
1801 bool const known = sel >= 0;
1802 bool const valid = !(converterED->text().isEmpty()
1803 || from.name() == to.name());
1808 if (convertersLW->count() > 0) {
1809 int const cnr = convertersLW->currentItem()->type();
1810 Converter const & c = form_->converters().get(cnr);
1811 old_command = c.command();
1812 old_flag = c.flags();
1815 string const new_command = fromqstr(converterED->text());
1816 string const new_flag = fromqstr(converterFlagED->text());
1818 bool modified = (old_command != new_command || old_flag != new_flag);
1820 converterModifyPB->setEnabled(valid && known && modified);
1821 converterNewPB->setEnabled(valid && !known);
1822 converterRemovePB->setEnabled(known);
1824 maxAgeLE->setEnabled(cacheCB->isChecked());
1825 maxAgeLA->setEnabled(cacheCB->isChecked());
1830 // specify unique from/to or it doesn't appear. This is really bad UI
1831 // this is why we can use the same function for both new and modify
1832 void PrefConverters::updateConverter()
1834 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1835 Format const & to = form_->formats().get(converterToCO->currentIndex());
1836 string const flags = fromqstr(converterFlagED->text());
1837 string const command = fromqstr(converterED->text());
1839 Converter const * old =
1840 form_->converters().getConverter(from.name(), to.name());
1841 form_->converters().add(from.name(), to.name(), command, flags);
1844 form_->converters().updateLast(form_->formats());
1848 // Remove all files created by this converter from the cache, since
1849 // the modified converter might create different files.
1850 ConverterCache::get().remove_all(from.name(), to.name());
1854 void PrefConverters::removeConverter()
1856 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1857 Format const & to = form_->formats().get(converterToCO->currentIndex());
1858 form_->converters().erase(from.name(), to.name());
1862 // Remove all files created by this converter from the cache, since
1863 // a possible new converter might create different files.
1864 ConverterCache::get().remove_all(from.name(), to.name());
1868 void PrefConverters::on_cacheCB_stateChanged(int state)
1870 maxAgeLE->setEnabled(state == Qt::Checked);
1871 maxAgeLA->setEnabled(state == Qt::Checked);
1876 void PrefConverters::on_needauthForbiddenCB_toggled(bool checked)
1878 needauthCB->setEnabled(!checked);
1882 void PrefConverters::on_needauthCB_toggled(bool checked)
1889 int ret = frontend::Alert::prompt(
1890 _("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!"),
1891 0, 0, _("&No"), _("&Yes"));
1895 setCheckboxBlockSignals(needauthCB, true);
1899 /////////////////////////////////////////////////////////////////////
1903 /////////////////////////////////////////////////////////////////////
1905 class FormatValidator : public QValidator
1908 FormatValidator(QWidget *, Formats const & f);
1909 void fixup(QString & input) const;
1910 QValidator::State validate(QString & input, int & pos) const;
1912 virtual QString toString(Format const & format) const = 0;
1914 Formats const & formats_;
1918 FormatValidator::FormatValidator(QWidget * parent, Formats const & f)
1919 : QValidator(parent), formats_(f)
1924 void FormatValidator::fixup(QString & input) const
1926 Formats::const_iterator cit = formats_.begin();
1927 Formats::const_iterator end = formats_.end();
1928 for (; cit != end; ++cit) {
1929 QString const name = toString(*cit);
1930 if (distance(formats_.begin(), cit) == nr()) {
1938 QValidator::State FormatValidator::validate(QString & input, int & /*pos*/) const
1940 Formats::const_iterator cit = formats_.begin();
1941 Formats::const_iterator end = formats_.end();
1942 bool unknown = true;
1943 for (; unknown && cit != end; ++cit) {
1944 QString const name = toString(*cit);
1945 if (distance(formats_.begin(), cit) != nr())
1946 unknown = name != input;
1949 if (unknown && !input.isEmpty())
1950 return QValidator::Acceptable;
1952 return QValidator::Intermediate;
1956 int FormatValidator::nr() const
1958 QComboBox * p = qobject_cast<QComboBox *>(parent());
1959 return p->itemData(p->currentIndex()).toInt();
1963 /////////////////////////////////////////////////////////////////////
1965 // FormatNameValidator
1967 /////////////////////////////////////////////////////////////////////
1969 class FormatNameValidator : public FormatValidator
1972 FormatNameValidator(QWidget * parent, Formats const & f)
1973 : FormatValidator(parent, f)
1976 QString toString(Format const & format) const
1978 return toqstr(format.name());
1983 /////////////////////////////////////////////////////////////////////
1985 // FormatPrettynameValidator
1987 /////////////////////////////////////////////////////////////////////
1989 class FormatPrettynameValidator : public FormatValidator
1992 FormatPrettynameValidator(QWidget * parent, Formats const & f)
1993 : FormatValidator(parent, f)
1996 QString toString(Format const & format) const
1998 return toqstr(translateIfPossible(format.prettyname()));
2003 /////////////////////////////////////////////////////////////////////
2007 /////////////////////////////////////////////////////////////////////
2009 PrefFileformats::PrefFileformats(GuiPreferences * form)
2010 : PrefModule(catFiles, N_("File Formats"), form)
2014 formatED->setValidator(new FormatNameValidator(formatsCB, form_->formats()));
2015 formatsCB->setValidator(new FormatPrettynameValidator(formatsCB, form_->formats()));
2016 extensionsED->setValidator(new NoNewLineValidator(extensionsED));
2017 shortcutED->setValidator(new NoNewLineValidator(shortcutED));
2018 editorED->setValidator(new NoNewLineValidator(editorED));
2019 viewerED->setValidator(new NoNewLineValidator(viewerED));
2020 copierED->setValidator(new NoNewLineValidator(copierED));
2022 connect(documentCB, SIGNAL(clicked()),
2023 this, SLOT(setFlags()));
2024 connect(vectorCB, SIGNAL(clicked()),
2025 this, SLOT(setFlags()));
2026 connect(exportMenuCB, SIGNAL(clicked()),
2027 this, SLOT(setFlags()));
2028 connect(formatsCB->lineEdit(), SIGNAL(editingFinished()),
2029 this, SLOT(updatePrettyname()));
2030 connect(formatsCB->lineEdit(), SIGNAL(textEdited(QString)),
2031 this, SIGNAL(changed()));
2032 connect(defaultFormatCB, SIGNAL(activated(QString)),
2033 this, SIGNAL(changed()));
2034 connect(defaultOTFFormatCB, SIGNAL(activated(QString)),
2035 this, SIGNAL(changed()));
2036 connect(defaultPlatexFormatCB, SIGNAL(activated(QString)),
2037 this, SIGNAL(changed()));
2038 connect(viewerCO, SIGNAL(activated(int)),
2039 this, SIGNAL(changed()));
2040 connect(editorCO, SIGNAL(activated(int)),
2041 this, SIGNAL(changed()));
2047 string const l10n_shortcut(docstring const & prettyname, string const & shortcut)
2049 if (shortcut.empty())
2052 string l10n_format =
2053 to_utf8(_(to_utf8(prettyname) + '|' + shortcut));
2054 return split(l10n_format, '|');
2060 void PrefFileformats::applyRC(LyXRC & rc) const
2062 QString const default_format = defaultFormatCB->itemData(
2063 defaultFormatCB->currentIndex()).toString();
2064 rc.default_view_format = fromqstr(default_format);
2065 QString const default_otf_format = defaultOTFFormatCB->itemData(
2066 defaultOTFFormatCB->currentIndex()).toString();
2067 rc.default_otf_view_format = fromqstr(default_otf_format);
2068 QString const default_platex_format = defaultPlatexFormatCB->itemData(
2069 defaultPlatexFormatCB->currentIndex()).toString();
2070 rc.default_platex_view_format = fromqstr(default_platex_format);
2074 void PrefFileformats::updateRC(LyXRC const & rc)
2076 viewer_alternatives = rc.viewer_alternatives;
2077 editor_alternatives = rc.editor_alternatives;
2078 bool const init = defaultFormatCB->currentText().isEmpty();
2082 defaultFormatCB->findData(toqstr(rc.default_view_format));
2083 defaultFormatCB->setCurrentIndex(pos);
2084 pos = defaultOTFFormatCB->findData(toqstr(rc.default_otf_view_format));
2085 defaultOTFFormatCB->setCurrentIndex(pos);
2086 defaultOTFFormatCB->setCurrentIndex(pos);
2087 pos = defaultPlatexFormatCB->findData(toqstr(rc.default_platex_view_format));
2088 defaultPlatexFormatCB->setCurrentIndex(pos);
2089 defaultPlatexFormatCB->setCurrentIndex(pos);
2094 void PrefFileformats::updateView()
2096 QString const current = formatsCB->currentText();
2097 QString const current_def = defaultFormatCB->currentText();
2098 QString const current_def_otf = defaultOTFFormatCB->currentText();
2099 QString const current_def_platex = defaultPlatexFormatCB->currentText();
2101 // update comboboxes with formats
2102 formatsCB->blockSignals(true);
2103 defaultFormatCB->blockSignals(true);
2104 defaultOTFFormatCB->blockSignals(true);
2105 defaultPlatexFormatCB->blockSignals(true);
2107 defaultFormatCB->clear();
2108 defaultOTFFormatCB->clear();
2109 defaultPlatexFormatCB->clear();
2110 form_->formats().sort();
2111 for (Format const & f : form_->formats()) {
2112 QString const prettyname = toqstr(translateIfPossible(f.prettyname()));
2113 formatsCB->addItem(prettyname,
2114 QVariant(form_->formats().getNumber(f.name())));
2115 if (f.viewer().empty())
2117 if (form_->converters().isReachable("xhtml", f.name())
2118 || form_->converters().isReachable("dviluatex", f.name())
2119 || form_->converters().isReachable("luatex", f.name())
2120 || form_->converters().isReachable("xetex", f.name())) {
2121 defaultFormatCB->addItem(prettyname,
2122 QVariant(toqstr(f.name())));
2123 defaultOTFFormatCB->addItem(prettyname,
2124 QVariant(toqstr(f.name())));
2126 if (form_->converters().isReachable("latex", f.name())
2127 || form_->converters().isReachable("pdflatex", f.name()))
2128 defaultFormatCB->addItem(prettyname,
2129 QVariant(toqstr(f.name())));
2130 if (form_->converters().isReachable("platex", f.name()))
2131 defaultPlatexFormatCB->addItem(prettyname,
2132 QVariant(toqstr(f.name())));
2136 // restore selections
2137 int item = formatsCB->findText(current, Qt::MatchExactly);
2138 formatsCB->setCurrentIndex(item < 0 ? 0 : item);
2139 on_formatsCB_currentIndexChanged(item < 0 ? 0 : item);
2140 item = defaultFormatCB->findText(current_def, Qt::MatchExactly);
2141 defaultFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2142 item = defaultOTFFormatCB->findText(current_def_otf, Qt::MatchExactly);
2143 defaultOTFFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2144 item = defaultPlatexFormatCB->findText(current_def_platex, Qt::MatchExactly);
2145 defaultPlatexFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2146 formatsCB->blockSignals(false);
2147 defaultFormatCB->blockSignals(false);
2148 defaultOTFFormatCB->blockSignals(false);
2149 defaultPlatexFormatCB->blockSignals(false);
2153 void PrefFileformats::on_formatsCB_currentIndexChanged(int i)
2155 if (form_->formats().empty())
2157 int const nr = formatsCB->itemData(i).toInt();
2158 Format const f = form_->formats().get(nr);
2160 formatED->setText(toqstr(f.name()));
2161 copierED->setText(toqstr(form_->movers().command(f.name())));
2162 extensionsED->setText(toqstr(f.extensions()));
2163 mimeED->setText(toqstr(f.mime()));
2164 shortcutED->setText(
2165 toqstr(l10n_shortcut(f.prettyname(), f.shortcut())));
2166 documentCB->setChecked((f.documentFormat()));
2167 vectorCB->setChecked((f.vectorFormat()));
2168 exportMenuCB->setChecked((f.inExportMenu()));
2169 exportMenuCB->setEnabled((f.documentFormat()));
2175 void PrefFileformats::setFlags()
2177 int flags = Format::none;
2178 if (documentCB->isChecked())
2179 flags |= Format::document;
2180 if (vectorCB->isChecked())
2181 flags |= Format::vector;
2182 if (exportMenuCB->isChecked())
2183 flags |= Format::export_menu;
2184 currentFormat().setFlags(flags);
2185 exportMenuCB->setEnabled(documentCB->isChecked());
2190 void PrefFileformats::on_copierED_textEdited(const QString & s)
2192 string const fmt = fromqstr(formatED->text());
2193 form_->movers().set(fmt, fromqstr(s));
2198 void PrefFileformats::on_extensionsED_textEdited(const QString & s)
2200 currentFormat().setExtensions(fromqstr(s));
2205 void PrefFileformats::on_viewerED_textEdited(const QString & s)
2207 currentFormat().setViewer(fromqstr(s));
2212 void PrefFileformats::on_editorED_textEdited(const QString & s)
2214 currentFormat().setEditor(fromqstr(s));
2219 void PrefFileformats::on_mimeED_textEdited(const QString & s)
2221 currentFormat().setMime(fromqstr(s));
2226 void PrefFileformats::on_shortcutED_textEdited(const QString & s)
2228 string const new_shortcut = fromqstr(s);
2229 if (new_shortcut == l10n_shortcut(currentFormat().prettyname(),
2230 currentFormat().shortcut()))
2232 currentFormat().setShortcut(new_shortcut);
2237 void PrefFileformats::on_formatED_editingFinished()
2239 string const newname = fromqstr(formatED->displayText());
2240 string const oldname = currentFormat().name();
2241 if (newname == oldname)
2243 if (form_->converters().formatIsUsed(oldname)) {
2244 Alert::error(_("Format in use"),
2245 _("You cannot change a format's short name "
2246 "if the format is used by a converter. "
2247 "Please remove the converter first."));
2252 currentFormat().setName(newname);
2257 void PrefFileformats::on_formatED_textChanged(const QString &)
2259 QString t = formatED->text();
2261 bool valid = formatED->validator()->validate(t, p) == QValidator::Acceptable;
2262 setValid(formatLA, valid);
2266 void PrefFileformats::on_formatsCB_editTextChanged(const QString &)
2268 QString t = formatsCB->currentText();
2270 bool valid = formatsCB->validator()->validate(t, p) == QValidator::Acceptable;
2271 setValid(formatsLA, valid);
2275 void PrefFileformats::updatePrettyname()
2277 QString const newname = formatsCB->currentText();
2278 if (newname == toqstr(translateIfPossible(currentFormat().prettyname())))
2281 currentFormat().setPrettyname(qstring_to_ucs4(newname));
2289 void updateComboBox(LyXRC::Alternatives const & alts,
2290 string const & fmt, QComboBox * combo)
2292 LyXRC::Alternatives::const_iterator it =
2294 if (it != alts.end()) {
2295 LyXRC::CommandSet const & cmds = it->second;
2296 LyXRC::CommandSet::const_iterator sit =
2298 LyXRC::CommandSet::const_iterator const sen =
2300 for (; sit != sen; ++sit) {
2301 QString const qcmd = toqstr(*sit);
2302 combo->addItem(qcmd, qcmd);
2309 void PrefFileformats::updateViewers()
2311 Format const f = currentFormat();
2312 viewerCO->blockSignals(true);
2314 viewerCO->addItem(qt_("None"), QString());
2315 updateComboBox(viewer_alternatives, f.name(), viewerCO);
2316 viewerCO->addItem(qt_("Custom"), QString("custom viewer"));
2317 viewerCO->blockSignals(false);
2319 int pos = viewerCO->findData(toqstr(f.viewer()));
2322 viewerED->setEnabled(false);
2323 viewerCO->setCurrentIndex(pos);
2325 viewerED->setEnabled(true);
2326 viewerED->setText(toqstr(f.viewer()));
2327 viewerCO->setCurrentIndex(viewerCO->findData(toqstr("custom viewer")));
2332 void PrefFileformats::updateEditors()
2334 Format const f = currentFormat();
2335 editorCO->blockSignals(true);
2337 editorCO->addItem(qt_("None"), QString());
2338 updateComboBox(editor_alternatives, f.name(), editorCO);
2339 editorCO->addItem(qt_("Custom"), QString("custom editor"));
2340 editorCO->blockSignals(false);
2342 int pos = editorCO->findData(toqstr(f.editor()));
2345 editorED->setEnabled(false);
2346 editorCO->setCurrentIndex(pos);
2348 editorED->setEnabled(true);
2349 editorED->setText(toqstr(f.editor()));
2350 editorCO->setCurrentIndex(editorCO->findData(toqstr("custom editor")));
2355 void PrefFileformats::on_viewerCO_currentIndexChanged(int i)
2357 bool const custom = viewerCO->itemData(i).toString() == "custom viewer";
2358 viewerED->setEnabled(custom);
2360 currentFormat().setViewer(fromqstr(viewerCO->itemData(i).toString()));
2364 void PrefFileformats::on_editorCO_currentIndexChanged(int i)
2366 bool const custom = editorCO->itemData(i).toString() == "custom editor";
2367 editorED->setEnabled(custom);
2369 currentFormat().setEditor(fromqstr(editorCO->itemData(i).toString()));
2373 Format & PrefFileformats::currentFormat()
2375 int const i = formatsCB->currentIndex();
2376 int const nr = formatsCB->itemData(i).toInt();
2377 return form_->formats().get(nr);
2381 void PrefFileformats::on_formatNewPB_clicked()
2383 form_->formats().add("", "", docstring(), "", "", "", "", Format::none);
2385 formatsCB->setCurrentIndex(0);
2386 formatsCB->setFocus(Qt::OtherFocusReason);
2390 void PrefFileformats::on_formatRemovePB_clicked()
2392 int const i = formatsCB->currentIndex();
2393 int const nr = formatsCB->itemData(i).toInt();
2394 string const current_text = form_->formats().get(nr).name();
2395 if (form_->converters().formatIsUsed(current_text)) {
2396 Alert::error(_("Format in use"),
2397 _("Cannot remove a Format used by a Converter. "
2398 "Remove the converter first."));
2402 form_->formats().erase(current_text);
2405 on_formatsCB_editTextChanged(formatsCB->currentText());
2410 /////////////////////////////////////////////////////////////////////
2414 /////////////////////////////////////////////////////////////////////
2416 PrefLanguage::PrefLanguage(GuiPreferences * form)
2417 : PrefModule(catLanguage, N_("Language"), form)
2421 connect(visualCursorRB, SIGNAL(clicked()),
2422 this, SIGNAL(changed()));
2423 connect(logicalCursorRB, SIGNAL(clicked()),
2424 this, SIGNAL(changed()));
2425 connect(markForeignCB, SIGNAL(clicked()),
2426 this, SIGNAL(changed()));
2427 connect(autoBeginCB, SIGNAL(clicked()),
2428 this, SIGNAL(changed()));
2429 connect(autoEndCB, SIGNAL(clicked()),
2430 this, SIGNAL(changed()));
2431 connect(languagePackageCO, SIGNAL(activated(int)),
2432 this, SIGNAL(changed()));
2433 connect(languagePackageED, SIGNAL(textChanged(QString)),
2434 this, SIGNAL(changed()));
2435 connect(globalCB, SIGNAL(clicked()),
2436 this, SIGNAL(changed()));
2437 connect(startCommandED, SIGNAL(textChanged(QString)),
2438 this, SIGNAL(changed()));
2439 connect(endCommandED, SIGNAL(textChanged(QString)),
2440 this, SIGNAL(changed()));
2441 connect(uiLanguageCO, SIGNAL(activated(int)),
2442 this, SIGNAL(changed()));
2443 connect(defaultDecimalPointLE, SIGNAL(textChanged(QString)),
2444 this, SIGNAL(changed()));
2445 connect(defaultLengthUnitCO, SIGNAL(activated(int)),
2446 this, SIGNAL(changed()));
2448 languagePackageED->setValidator(new NoNewLineValidator(languagePackageED));
2449 startCommandED->setValidator(new NoNewLineValidator(startCommandED));
2450 endCommandED->setValidator(new NoNewLineValidator(endCommandED));
2452 defaultDecimalPointLE->setInputMask("X; ");
2453 defaultDecimalPointLE->setMaxLength(1);
2455 defaultLengthUnitCO->addItem(lyx::qt_(unit_name_gui[Length::CM]), Length::CM);
2456 defaultLengthUnitCO->addItem(lyx::qt_(unit_name_gui[Length::IN]), Length::IN);
2458 QAbstractItemModel * language_model = guiApp->languageModel();
2459 language_model->sort(0);
2460 uiLanguageCO->blockSignals(true);
2461 uiLanguageCO->clear();
2462 uiLanguageCO->addItem(qt_("Default"), toqstr("auto"));
2463 for (int i = 0; i != language_model->rowCount(); ++i) {
2464 QModelIndex index = language_model->index(i, 0);
2465 // Filter the list based on the available translation and add
2466 // each language code only once
2467 string const name = fromqstr(index.data(Qt::UserRole).toString());
2468 Language const * lang = languages.getLanguage(name);
2471 // never remove the currently selected language
2472 if (name != form->rc().gui_language
2473 && name != lyxrc.gui_language
2474 && (!Messages::available(lang->code())
2475 || !lang->hasGuiSupport()))
2477 uiLanguageCO->addItem(index.data(Qt::DisplayRole).toString(),
2478 index.data(Qt::UserRole).toString());
2480 uiLanguageCO->blockSignals(false);
2484 void PrefLanguage::on_uiLanguageCO_currentIndexChanged(int)
2486 QMessageBox::information(this, qt_("LyX needs to be restarted!"),
2487 qt_("The change of user interface language will be fully "
2488 "effective only after a restart."));
2492 void PrefLanguage::on_languagePackageCO_currentIndexChanged(int i)
2494 languagePackageED->setEnabled(i == 2);
2498 void PrefLanguage::applyRC(LyXRC & rc) const
2500 rc.visual_cursor = visualCursorRB->isChecked();
2501 rc.mark_foreign_language = markForeignCB->isChecked();
2502 rc.language_auto_begin = autoBeginCB->isChecked();
2503 rc.language_auto_end = autoEndCB->isChecked();
2504 int const p = languagePackageCO->currentIndex();
2506 rc.language_package_selection = LyXRC::LP_AUTO;
2508 rc.language_package_selection = LyXRC::LP_BABEL;
2510 rc.language_package_selection = LyXRC::LP_CUSTOM;
2512 rc.language_package_selection = LyXRC::LP_NONE;
2513 rc.language_custom_package = fromqstr(languagePackageED->text());
2514 rc.language_global_options = globalCB->isChecked();
2515 rc.language_command_begin = fromqstr(startCommandED->text());
2516 rc.language_command_end = fromqstr(endCommandED->text());
2517 rc.gui_language = fromqstr(
2518 uiLanguageCO->itemData(uiLanguageCO->currentIndex()).toString());
2519 rc.default_decimal_point = fromqstr(defaultDecimalPointLE->text());
2520 rc.default_length_unit = (Length::UNIT) defaultLengthUnitCO->itemData(defaultLengthUnitCO->currentIndex()).toInt();
2524 void PrefLanguage::updateRC(LyXRC const & rc)
2526 if (rc.visual_cursor)
2527 visualCursorRB->setChecked(true);
2529 logicalCursorRB->setChecked(true);
2530 markForeignCB->setChecked(rc.mark_foreign_language);
2531 autoBeginCB->setChecked(rc.language_auto_begin);
2532 autoEndCB->setChecked(rc.language_auto_end);
2533 languagePackageCO->setCurrentIndex(rc.language_package_selection);
2534 languagePackageED->setText(toqstr(rc.language_custom_package));
2535 languagePackageED->setEnabled(languagePackageCO->currentIndex() == 2);
2536 globalCB->setChecked(rc.language_global_options);
2537 startCommandED->setText(toqstr(rc.language_command_begin));
2538 endCommandED->setText(toqstr(rc.language_command_end));
2539 defaultDecimalPointLE->setText(toqstr(rc.default_decimal_point));
2540 int pos = defaultLengthUnitCO->findData(int(rc.default_length_unit));
2541 defaultLengthUnitCO->setCurrentIndex(pos);
2543 pos = uiLanguageCO->findData(toqstr(rc.gui_language));
2544 uiLanguageCO->blockSignals(true);
2545 uiLanguageCO->setCurrentIndex(pos);
2546 uiLanguageCO->blockSignals(false);
2550 /////////////////////////////////////////////////////////////////////
2552 // PrefUserInterface
2554 /////////////////////////////////////////////////////////////////////
2556 PrefUserInterface::PrefUserInterface(GuiPreferences * form)
2557 : PrefModule(catLookAndFeel, N_("User Interface"), form)
2561 connect(uiFilePB, SIGNAL(clicked()),
2562 this, SLOT(selectUi()));
2563 connect(uiFileED, SIGNAL(textChanged(QString)),
2564 this, SIGNAL(changed()));
2565 connect(iconSetCO, SIGNAL(activated(int)),
2566 this, SIGNAL(changed()));
2567 connect(useSystemThemeIconsCB, SIGNAL(clicked()),
2568 this, SIGNAL(changed()));
2569 connect(lastfilesSB, SIGNAL(valueChanged(int)),
2570 this, SIGNAL(changed()));
2571 connect(tooltipCB, SIGNAL(toggled(bool)),
2572 this, SIGNAL(changed()));
2573 lastfilesSB->setMaximum(maxlastfiles);
2575 iconSetCO->addItem(qt_("Default"), QString());
2576 iconSetCO->addItem(qt_("Classic"), "classic");
2577 iconSetCO->addItem(qt_("Oxygen"), "oxygen");
2579 #if (!(defined Q_WS_X11 || defined(QPA_XCB)) || QT_VERSION < 0x040600)
2580 useSystemThemeIconsCB->hide();
2585 void PrefUserInterface::applyRC(LyXRC & rc) const
2587 rc.icon_set = fromqstr(iconSetCO->itemData(
2588 iconSetCO->currentIndex()).toString());
2590 rc.ui_file = internal_path(fromqstr(uiFileED->text()));
2591 rc.use_system_theme_icons = useSystemThemeIconsCB->isChecked();
2592 rc.num_lastfiles = lastfilesSB->value();
2593 rc.use_tooltip = tooltipCB->isChecked();
2597 void PrefUserInterface::updateRC(LyXRC const & rc)
2599 int iconset = iconSetCO->findData(toqstr(rc.icon_set));
2602 iconSetCO->setCurrentIndex(iconset);
2603 useSystemThemeIconsCB->setChecked(rc.use_system_theme_icons);
2604 uiFileED->setText(toqstr(external_path(rc.ui_file)));
2605 lastfilesSB->setValue(rc.num_lastfiles);
2606 tooltipCB->setChecked(rc.use_tooltip);
2610 void PrefUserInterface::selectUi()
2612 QString file = form_->browseUI(internalPath(uiFileED->text()));
2613 if (!file.isEmpty())
2614 uiFileED->setText(file);
2618 /////////////////////////////////////////////////////////////////////
2620 // PrefDocumentHandling
2622 /////////////////////////////////////////////////////////////////////
2624 PrefDocHandling::PrefDocHandling(GuiPreferences * form)
2625 : PrefModule(catLookAndFeel, N_("Document Handling"), form)
2629 connect(autoSaveCB, SIGNAL(toggled(bool)),
2630 autoSaveSB, SLOT(setEnabled(bool)));
2631 connect(autoSaveCB, SIGNAL(toggled(bool)),
2632 TextLabel1, SLOT(setEnabled(bool)));
2633 connect(openDocumentsInTabsCB, SIGNAL(clicked()),
2634 this, SIGNAL(changed()));
2635 connect(singleInstanceCB, SIGNAL(clicked()),
2636 this, SIGNAL(changed()));
2637 connect(singleCloseTabButtonCB, SIGNAL(clicked()),
2638 this, SIGNAL(changed()));
2639 connect(closeLastViewCO, SIGNAL(activated(int)),
2640 this, SIGNAL(changed()));
2641 connect(restoreCursorCB, SIGNAL(clicked()),
2642 this, SIGNAL(changed()));
2643 connect(loadSessionCB, SIGNAL(clicked()),
2644 this, SIGNAL(changed()));
2645 connect(allowGeometrySessionCB, SIGNAL(clicked()),
2646 this, SIGNAL(changed()));
2647 connect(autoSaveSB, SIGNAL(valueChanged(int)),
2648 this, SIGNAL(changed()));
2649 connect(autoSaveCB, SIGNAL(clicked()),
2650 this, SIGNAL(changed()));
2651 connect(backupCB, SIGNAL(clicked()),
2652 this, SIGNAL(changed()));
2653 connect(saveCompressedCB, SIGNAL(clicked()),
2654 this, SIGNAL(changed()));
2655 connect(saveOriginCB, SIGNAL(clicked()),
2656 this, SIGNAL(changed()));
2660 void PrefDocHandling::applyRC(LyXRC & rc) const
2662 rc.use_lastfilepos = restoreCursorCB->isChecked();
2663 rc.load_session = loadSessionCB->isChecked();
2664 rc.allow_geometry_session = allowGeometrySessionCB->isChecked();
2665 rc.autosave = autoSaveCB->isChecked() ? autoSaveSB->value() * 60 : 0;
2666 rc.make_backup = backupCB->isChecked();
2667 rc.save_compressed = saveCompressedCB->isChecked();
2668 rc.save_origin = saveOriginCB->isChecked();
2669 rc.open_buffers_in_tabs = openDocumentsInTabsCB->isChecked();
2670 rc.single_instance = singleInstanceCB->isChecked();
2671 rc.single_close_tab_button = singleCloseTabButtonCB->isChecked();
2673 switch (closeLastViewCO->currentIndex()) {
2675 rc.close_buffer_with_last_view = "yes";
2678 rc.close_buffer_with_last_view = "no";
2681 rc.close_buffer_with_last_view = "ask";
2689 void PrefDocHandling::updateRC(LyXRC const & rc)
2691 restoreCursorCB->setChecked(rc.use_lastfilepos);
2692 loadSessionCB->setChecked(rc.load_session);
2693 allowGeometrySessionCB->setChecked(rc.allow_geometry_session);
2694 // convert to minutes
2695 bool autosave = rc.autosave > 0;
2696 int mins = rc.autosave / 60;
2699 autoSaveSB->setValue(mins);
2700 autoSaveCB->setChecked(autosave);
2701 autoSaveSB->setEnabled(autosave);
2702 backupCB->setChecked(rc.make_backup);
2703 saveCompressedCB->setChecked(rc.save_compressed);
2704 saveOriginCB->setChecked(rc.save_origin);
2705 openDocumentsInTabsCB->setChecked(rc.open_buffers_in_tabs);
2706 singleInstanceCB->setChecked(rc.single_instance && !rc.lyxpipes.empty());
2707 singleInstanceCB->setEnabled(!rc.lyxpipes.empty());
2708 singleCloseTabButtonCB->setChecked(rc.single_close_tab_button);
2709 if (rc.close_buffer_with_last_view == "yes")
2710 closeLastViewCO->setCurrentIndex(0);
2711 else if (rc.close_buffer_with_last_view == "no")
2712 closeLastViewCO->setCurrentIndex(1);
2713 else if (rc.close_buffer_with_last_view == "ask")
2714 closeLastViewCO->setCurrentIndex(2);
2718 void PrefDocHandling::on_clearSessionPB_clicked()
2720 guiApp->clearSession();
2725 /////////////////////////////////////////////////////////////////////
2729 /////////////////////////////////////////////////////////////////////
2731 PrefEdit::PrefEdit(GuiPreferences * form)
2732 : PrefModule(catEditing, N_("Control"), form)
2736 connect(cursorFollowsCB, SIGNAL(clicked()),
2737 this, SIGNAL(changed()));
2738 connect(scrollBelowCB, SIGNAL(clicked()),
2739 this, SIGNAL(changed()));
2740 connect(macLikeCursorMovementCB, SIGNAL(clicked()),
2741 this, SIGNAL(changed()));
2742 connect(sortEnvironmentsCB, SIGNAL(clicked()),
2743 this, SIGNAL(changed()));
2744 connect(groupEnvironmentsCB, SIGNAL(clicked()),
2745 this, SIGNAL(changed()));
2746 connect(macroEditStyleCO, SIGNAL(activated(int)),
2747 this, SIGNAL(changed()));
2748 connect(cursorWidthSB, SIGNAL(valueChanged(int)),
2749 this, SIGNAL(changed()));
2750 connect(fullscreenLimitGB, SIGNAL(clicked()),
2751 this, SIGNAL(changed()));
2752 connect(fullscreenWidthSB, SIGNAL(valueChanged(int)),
2753 this, SIGNAL(changed()));
2754 connect(toggleTabbarCB, SIGNAL(toggled(bool)),
2755 this, SIGNAL(changed()));
2756 connect(toggleMenubarCB, SIGNAL(toggled(bool)),
2757 this, SIGNAL(changed()));
2758 connect(toggleScrollbarCB, SIGNAL(toggled(bool)),
2759 this, SIGNAL(changed()));
2760 connect(toggleStatusbarCB, SIGNAL(toggled(bool)),
2761 this, SIGNAL(changed()));
2762 connect(toggleToolbarsCB, SIGNAL(toggled(bool)),
2763 this, SIGNAL(changed()));
2767 void PrefEdit::applyRC(LyXRC & rc) const
2769 rc.cursor_follows_scrollbar = cursorFollowsCB->isChecked();
2770 rc.scroll_below_document = scrollBelowCB->isChecked();
2771 rc.mac_like_cursor_movement = macLikeCursorMovementCB->isChecked();
2772 rc.sort_layouts = sortEnvironmentsCB->isChecked();
2773 rc.group_layouts = groupEnvironmentsCB->isChecked();
2774 switch (macroEditStyleCO->currentIndex()) {
2775 case 0: rc.macro_edit_style = LyXRC::MACRO_EDIT_INLINE_BOX; break;
2776 case 1: rc.macro_edit_style = LyXRC::MACRO_EDIT_INLINE; break;
2777 case 2: rc.macro_edit_style = LyXRC::MACRO_EDIT_LIST; break;
2779 rc.cursor_width = cursorWidthSB->value();
2780 rc.full_screen_toolbars = toggleToolbarsCB->isChecked();
2781 rc.full_screen_scrollbar = toggleScrollbarCB->isChecked();
2782 rc.full_screen_statusbar = toggleStatusbarCB->isChecked();
2783 rc.full_screen_tabbar = toggleTabbarCB->isChecked();
2784 rc.full_screen_menubar = toggleMenubarCB->isChecked();
2785 rc.full_screen_width = fullscreenWidthSB->value();
2786 rc.full_screen_limit = fullscreenLimitGB->isChecked();
2790 void PrefEdit::updateRC(LyXRC const & rc)
2792 cursorFollowsCB->setChecked(rc.cursor_follows_scrollbar);
2793 scrollBelowCB->setChecked(rc.scroll_below_document);
2794 macLikeCursorMovementCB->setChecked(rc.mac_like_cursor_movement);
2795 sortEnvironmentsCB->setChecked(rc.sort_layouts);
2796 groupEnvironmentsCB->setChecked(rc.group_layouts);
2797 macroEditStyleCO->setCurrentIndex(rc.macro_edit_style);
2798 cursorWidthSB->setValue(rc.cursor_width);
2799 toggleScrollbarCB->setChecked(rc.full_screen_scrollbar);
2800 toggleStatusbarCB->setChecked(rc.full_screen_statusbar);
2801 toggleToolbarsCB->setChecked(rc.full_screen_toolbars);
2802 toggleTabbarCB->setChecked(rc.full_screen_tabbar);
2803 toggleMenubarCB->setChecked(rc.full_screen_menubar);
2804 fullscreenWidthSB->setValue(rc.full_screen_width);
2805 fullscreenLimitGB->setChecked(rc.full_screen_limit);
2809 /////////////////////////////////////////////////////////////////////
2813 /////////////////////////////////////////////////////////////////////
2816 GuiShortcutDialog::GuiShortcutDialog(QWidget * parent) : QDialog(parent)
2818 Ui::shortcutUi::setupUi(this);
2819 QDialog::setModal(true);
2823 PrefShortcuts::PrefShortcuts(GuiPreferences * form)
2824 : PrefModule(catEditing, N_("Shortcuts"), form),
2825 editItem_(0), mathItem_(0), bufferItem_(0), layoutItem_(0),
2830 shortcutsTW->setColumnCount(2);
2831 shortcutsTW->headerItem()->setText(0, qt_("Function"));
2832 shortcutsTW->headerItem()->setText(1, qt_("Shortcut"));
2833 shortcutsTW->setSortingEnabled(true);
2834 // Multi-selection can be annoying.
2835 // shortcutsTW->setSelectionMode(QAbstractItemView::MultiSelection);
2837 connect(bindFilePB, SIGNAL(clicked()),
2838 this, SLOT(selectBind()));
2839 connect(bindFileED, SIGNAL(textChanged(QString)),
2840 this, SIGNAL(changed()));
2842 shortcut_ = new GuiShortcutDialog(this);
2843 shortcut_bc_.setPolicy(ButtonPolicy::OkCancelPolicy);
2844 shortcut_bc_.setOK(shortcut_->okPB);
2845 shortcut_bc_.setCancel(shortcut_->cancelPB);
2847 connect(shortcut_->okPB, SIGNAL(clicked()),
2848 this, SIGNAL(changed()));
2849 connect(shortcut_->cancelPB, SIGNAL(clicked()),
2850 shortcut_, SLOT(reject()));
2851 connect(shortcut_->clearPB, SIGNAL(clicked()),
2852 this, SLOT(shortcutClearPressed()));
2853 connect(shortcut_->removePB, SIGNAL(clicked()),
2854 this, SLOT(shortcutRemovePressed()));
2855 connect(shortcut_->okPB, SIGNAL(clicked()),
2856 this, SLOT(shortcutOkPressed()));
2857 connect(shortcut_->cancelPB, SIGNAL(clicked()),
2858 this, SLOT(shortcutCancelPressed()));
2862 void PrefShortcuts::applyRC(LyXRC & rc) const
2864 rc.bind_file = internal_path(fromqstr(bindFileED->text()));
2865 // write user_bind and user_unbind to .lyx/bind/user.bind
2866 FileName bind_dir(addPath(package().user_support().absFileName(), "bind"));
2867 if (!bind_dir.exists() && !bind_dir.createDirectory(0777)) {
2868 lyxerr << "LyX could not create the user bind directory '"
2869 << bind_dir << "'. All user-defined key bindings will be lost." << endl;
2872 if (!bind_dir.isDirWritable()) {
2873 lyxerr << "LyX could not write to the user bind directory '"
2874 << bind_dir << "'. All user-defined key bindings will be lost." << endl;
2877 FileName user_bind_file(bind_dir.absFileName() + "/user.bind");
2878 user_unbind_.write(user_bind_file.toFilesystemEncoding(), false, true);
2879 user_bind_.write(user_bind_file.toFilesystemEncoding(), true, false);
2880 // immediately apply the keybindings. Why this is not done before?
2881 // The good thing is that the menus are updated automatically.
2882 theTopLevelKeymap().clear();
2883 theTopLevelKeymap().read("site");
2884 theTopLevelKeymap().read(rc.bind_file, 0, KeyMap::Fallback);
2885 theTopLevelKeymap().read("user", 0, KeyMap::MissingOK);
2889 void PrefShortcuts::updateRC(LyXRC const & rc)
2891 bindFileED->setText(toqstr(external_path(rc.bind_file)));
2893 system_bind_.clear();
2895 user_unbind_.clear();
2896 system_bind_.read("site");
2897 system_bind_.read(rc.bind_file);
2898 // \unbind in user.bind is added to user_unbind_
2899 user_bind_.read("user", &user_unbind_, KeyMap::MissingOK);
2900 updateShortcutsTW();
2904 void PrefShortcuts::updateShortcutsTW()
2906 shortcutsTW->clear();
2908 editItem_ = new QTreeWidgetItem(shortcutsTW);
2909 editItem_->setText(0, qt_("Cursor, Mouse and Editing Functions"));
2910 editItem_->setFlags(editItem_->flags() & ~Qt::ItemIsSelectable);
2912 mathItem_ = new QTreeWidgetItem(shortcutsTW);
2913 mathItem_->setText(0, qt_("Mathematical Symbols"));
2914 mathItem_->setFlags(mathItem_->flags() & ~Qt::ItemIsSelectable);
2916 bufferItem_ = new QTreeWidgetItem(shortcutsTW);
2917 bufferItem_->setText(0, qt_("Document and Window"));
2918 bufferItem_->setFlags(bufferItem_->flags() & ~Qt::ItemIsSelectable);
2920 layoutItem_ = new QTreeWidgetItem(shortcutsTW);
2921 layoutItem_->setText(0, qt_("Font, Layouts and Textclasses"));
2922 layoutItem_->setFlags(layoutItem_->flags() & ~Qt::ItemIsSelectable);
2924 systemItem_ = new QTreeWidgetItem(shortcutsTW);
2925 systemItem_->setText(0, qt_("System and Miscellaneous"));
2926 systemItem_->setFlags(systemItem_->flags() & ~Qt::ItemIsSelectable);
2928 // listBindings(unbound=true) lists all bound and unbound lfuns
2929 // Items in this list is tagged by its source.
2930 KeyMap::BindingList bindinglist = system_bind_.listBindings(true,
2932 KeyMap::BindingList user_bindinglist = user_bind_.listBindings(false,
2934 KeyMap::BindingList user_unbindinglist = user_unbind_.listBindings(false,
2935 KeyMap::UserUnbind);
2936 bindinglist.insert(bindinglist.end(), user_bindinglist.begin(),
2937 user_bindinglist.end());
2938 bindinglist.insert(bindinglist.end(), user_unbindinglist.begin(),
2939 user_unbindinglist.end());
2941 KeyMap::BindingList::const_iterator it = bindinglist.begin();
2942 KeyMap::BindingList::const_iterator it_end = bindinglist.end();
2943 for (; it != it_end; ++it)
2944 insertShortcutItem(it->request, it->sequence, it->tag);
2946 shortcutsTW->sortItems(0, Qt::AscendingOrder);
2947 on_shortcutsTW_itemSelectionChanged();
2948 on_searchLE_textEdited();
2949 shortcutsTW->resizeColumnToContents(0);
2954 KeyMap::ItemType PrefShortcuts::itemType(QTreeWidgetItem & item)
2956 return static_cast<KeyMap::ItemType>(item.data(0, Qt::UserRole).toInt());
2961 bool PrefShortcuts::isAlwaysHidden(QTreeWidgetItem & item)
2963 // Hide rebound system settings that are empty
2964 return itemType(item) == KeyMap::UserUnbind && item.text(1).isEmpty();
2968 void PrefShortcuts::setItemType(QTreeWidgetItem * item, KeyMap::ItemType tag)
2970 item->setData(0, Qt::UserRole, QVariant(tag));
2974 case KeyMap::System:
2976 case KeyMap::UserBind:
2979 case KeyMap::UserUnbind:
2980 font.setStrikeOut(true);
2982 // this item is not displayed now.
2983 case KeyMap::UserExtraUnbind:
2984 font.setStrikeOut(true);
2987 item->setHidden(isAlwaysHidden(*item));
2988 item->setFont(1, font);
2992 QTreeWidgetItem * PrefShortcuts::insertShortcutItem(FuncRequest const & lfun,
2993 KeySequence const & seq, KeyMap::ItemType tag)
2995 FuncCode const action = lfun.action();
2996 string const action_name = lyxaction.getActionName(action);
2997 QString const lfun_name = toqstr(from_utf8(action_name)
2998 + ' ' + lfun.argument());
2999 QString const shortcut = toqstr(seq.print(KeySequence::ForGui));
3001 QTreeWidgetItem * newItem = 0;
3002 // for unbind items, try to find an existing item in the system bind list
3003 if (tag == KeyMap::UserUnbind) {
3004 QList<QTreeWidgetItem*> const items = shortcutsTW->findItems(lfun_name,
3005 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 0);
3006 for (int i = 0; i < items.size(); ++i) {
3007 if (items[i]->text(1) == shortcut) {
3012 // if not found, this unbind item is KeyMap::UserExtraUnbind
3013 // Such an item is not displayed to avoid confusion (what is
3014 // unmatched removed?).
3020 switch(lyxaction.getActionType(action)) {
3021 case LyXAction::Hidden:
3023 case LyXAction::Edit:
3024 newItem = new QTreeWidgetItem(editItem_);
3026 case LyXAction::Math:
3027 newItem = new QTreeWidgetItem(mathItem_);
3029 case LyXAction::Buffer:
3030 newItem = new QTreeWidgetItem(bufferItem_);
3032 case LyXAction::Layout:
3033 newItem = new QTreeWidgetItem(layoutItem_);
3035 case LyXAction::System:
3036 newItem = new QTreeWidgetItem(systemItem_);
3039 // this should not happen
3040 newItem = new QTreeWidgetItem(shortcutsTW);
3044 newItem->setText(0, lfun_name);
3045 newItem->setText(1, shortcut);
3046 // record BindFile representation to recover KeySequence when needed.
3047 newItem->setData(1, Qt::UserRole, toqstr(seq.print(KeySequence::BindFile)));
3048 setItemType(newItem, tag);
3053 void PrefShortcuts::on_shortcutsTW_itemSelectionChanged()
3055 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
3056 removePB->setEnabled(!items.isEmpty() && !items[0]->text(1).isEmpty());
3057 modifyPB->setEnabled(!items.isEmpty());
3058 if (items.isEmpty())
3061 if (itemType(*items[0]) == KeyMap::UserUnbind)
3062 removePB->setText(qt_("Res&tore"));
3064 removePB->setText(qt_("Remo&ve"));
3068 void PrefShortcuts::on_shortcutsTW_itemDoubleClicked()
3074 void PrefShortcuts::modifyShortcut()
3076 QTreeWidgetItem * item = shortcutsTW->currentItem();
3077 if (item->flags() & Qt::ItemIsSelectable) {
3078 shortcut_->lfunLE->setText(item->text(0));
3079 save_lfun_ = item->text(0).trimmed();
3080 shortcut_->shortcutWG->setText(item->text(1));
3082 seq.parse(fromqstr(item->data(1, Qt::UserRole).toString()));
3083 shortcut_->shortcutWG->setKeySequence(seq);
3084 shortcut_->shortcutWG->setFocus();
3090 void PrefShortcuts::unhideEmpty(QString const & lfun, bool select)
3092 // list of items that match lfun
3093 QList<QTreeWidgetItem*> items = shortcutsTW->findItems(lfun,
3094 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 0);
3095 for (int i = 0; i < items.size(); ++i) {
3096 QTreeWidgetItem * item = items[i];
3097 if (isAlwaysHidden(*item)) {
3098 setItemType(item, KeyMap::System);
3100 shortcutsTW->setCurrentItem(item);
3107 void PrefShortcuts::removeShortcut()
3109 // it seems that only one item can be selected, but I am
3110 // removing all selected items anyway.
3111 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
3112 for (int i = 0; i < items.size(); ++i) {
3113 string shortcut = fromqstr(items[i]->data(1, Qt::UserRole).toString());
3114 string lfun = fromqstr(items[i]->text(0));
3115 FuncRequest func = lyxaction.lookupFunc(lfun);
3117 switch (itemType(*items[i])) {
3118 case KeyMap::System: {
3119 // for system bind, we do not touch the item
3120 // but add an user unbind item
3121 user_unbind_.bind(shortcut, func);
3122 setItemType(items[i], KeyMap::UserUnbind);
3123 removePB->setText(qt_("Res&tore"));
3126 case KeyMap::UserBind: {
3127 // for user_bind, we remove this bind
3128 QTreeWidgetItem * parent = items[i]->parent();
3129 int itemIdx = parent->indexOfChild(items[i]);
3130 parent->takeChild(itemIdx);
3132 shortcutsTW->scrollToItem(parent->child(itemIdx - 1));
3134 shortcutsTW->scrollToItem(parent);
3135 user_bind_.unbind(shortcut, func);
3136 // If this user binding hid an empty system binding, unhide the
3137 // latter and select it.
3138 unhideEmpty(items[i]->text(0), true);
3141 case KeyMap::UserUnbind: {
3142 // for user_unbind, we remove the unbind, and the item
3143 // become KeyMap::System again.
3145 seq.parse(shortcut);
3146 // Ask the user to replace current binding
3147 if (!validateNewShortcut(func, seq, QString()))
3149 user_unbind_.unbind(shortcut, func);
3150 setItemType(items[i], KeyMap::System);
3151 removePB->setText(qt_("Remo&ve"));
3154 case KeyMap::UserExtraUnbind: {
3155 // for user unbind that is not in system bind file,
3156 // remove this unbind file
3157 QTreeWidgetItem * parent = items[i]->parent();
3158 parent->takeChild(parent->indexOfChild(items[i]));
3159 user_unbind_.unbind(shortcut, func);
3166 void PrefShortcuts::deactivateShortcuts(QList<QTreeWidgetItem*> const & items)
3168 for (int i = 0; i < items.size(); ++i) {
3169 string shortcut = fromqstr(items[i]->data(1, Qt::UserRole).toString());
3170 string lfun = fromqstr(items[i]->text(0));
3171 FuncRequest func = lyxaction.lookupFunc(lfun);
3173 switch (itemType(*items[i])) {
3174 case KeyMap::System:
3175 // for system bind, we do not touch the item
3176 // but add an user unbind item
3177 user_unbind_.bind(shortcut, func);
3178 setItemType(items[i], KeyMap::UserUnbind);
3181 case KeyMap::UserBind: {
3182 // for user_bind, we remove this bind
3183 QTreeWidgetItem * parent = items[i]->parent();
3184 int itemIdx = parent->indexOfChild(items[i]);
3185 parent->takeChild(itemIdx);
3186 user_bind_.unbind(shortcut, func);
3187 unhideEmpty(items[i]->text(0), false);
3197 void PrefShortcuts::selectBind()
3199 QString file = form_->browsebind(internalPath(bindFileED->text()));
3200 if (!file.isEmpty()) {
3201 bindFileED->setText(file);
3202 system_bind_ = KeyMap();
3203 system_bind_.read(fromqstr(file));
3204 updateShortcutsTW();
3209 void PrefShortcuts::on_modifyPB_pressed()
3215 void PrefShortcuts::on_newPB_pressed()
3217 shortcut_->lfunLE->clear();
3218 shortcut_->shortcutWG->reset();
3219 save_lfun_ = QString();
3224 void PrefShortcuts::on_removePB_pressed()
3231 void PrefShortcuts::on_searchLE_textEdited()
3233 if (searchLE->text().isEmpty()) {
3234 // show all hidden items
3235 QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Hidden);
3237 shortcutsTW->setItemHidden(*it, isAlwaysHidden(**it));
3238 // close all categories
3239 for (int i = 0; i < shortcutsTW->topLevelItemCount(); ++i)
3240 shortcutsTW->collapseItem(shortcutsTW->topLevelItem(i));
3243 // search both columns
3244 QList<QTreeWidgetItem *> matched = shortcutsTW->findItems(searchLE->text(),
3245 Qt::MatchFlags(Qt::MatchContains | Qt::MatchRecursive), 0);
3246 matched += shortcutsTW->findItems(searchLE->text(),
3247 Qt::MatchFlags(Qt::MatchContains | Qt::MatchRecursive), 1);
3249 // hide everyone (to avoid searching in matched QList repeatedly
3250 QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Selectable);
3252 shortcutsTW->setItemHidden(*it++, true);
3253 // show matched items
3254 for (int i = 0; i < matched.size(); ++i)
3255 if (!isAlwaysHidden(*matched[i])) {
3256 shortcutsTW->setItemHidden(matched[i], false);
3257 shortcutsTW->setItemExpanded(matched[i]->parent(), true);
3262 docstring makeCmdString(FuncRequest const & f)
3264 docstring actionStr = from_ascii(lyxaction.getActionName(f.action()));
3265 if (!f.argument().empty())
3266 actionStr += " " + f.argument();
3271 FuncRequest PrefShortcuts::currentBinding(KeySequence const & k)
3273 FuncRequest res = user_bind_.getBinding(k);
3274 if (res.action() != LFUN_UNKNOWN_ACTION)
3276 res = system_bind_.getBinding(k);
3277 // Check if it is unbound. Note: user_unbind_ can only unbind one
3278 // FuncRequest per key sequence.
3279 if (user_unbind_.getBinding(k) == res)
3280 return FuncRequest::unknown;
3285 bool PrefShortcuts::validateNewShortcut(FuncRequest const & func,
3286 KeySequence const & k,
3287 QString const & lfun_to_modify)
3289 if (func.action() == LFUN_UNKNOWN_ACTION) {
3290 Alert::error(_("Failed to create shortcut"),
3291 _("Unknown or invalid LyX function"));
3295 // It is not currently possible to bind Hidden lfuns such as self-insert. In
3296 // the future, to remove this limitation, see GuiPrefs::insertShortcutItem
3297 // and how it is used in GuiPrefs::shortcutOkPressed.
3298 if (lyxaction.getActionType(func.action()) == LyXAction::Hidden) {
3299 Alert::error(_("Failed to create shortcut"),
3300 _("This LyX function is hidden and cannot be bound."));
3304 if (k.length() == 0) {
3305 Alert::error(_("Failed to create shortcut"),
3306 _("Invalid or empty key sequence"));
3310 FuncRequest oldBinding = currentBinding(k);
3311 if (oldBinding == func)
3312 // nothing to change
3315 // make sure this key isn't already bound---and, if so, prompt user
3316 // (exclude the lfun the user already wants to modify)
3317 docstring const action_string = makeCmdString(oldBinding);
3318 if (oldBinding.action() != LFUN_UNKNOWN_ACTION
3319 && lfun_to_modify != toqstr(action_string)) {
3320 docstring const new_action_string = makeCmdString(func);
3321 docstring const text = bformat(_("Shortcut `%1$s' is already bound to "
3323 "Are you sure you want to unbind the "
3324 "current shortcut and bind it to %3$s?"),
3325 k.print(KeySequence::ForGui), action_string,
3327 int ret = Alert::prompt(_("Redefine shortcut?"),
3328 text, 0, 1, _("&Redefine"), _("&Cancel"));
3331 QString const sequence_text = toqstr(k.print(KeySequence::ForGui));
3332 QList<QTreeWidgetItem*> items = shortcutsTW->findItems(sequence_text,
3333 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 1);
3334 deactivateShortcuts(items);
3340 void PrefShortcuts::shortcutOkPressed()
3342 QString const new_lfun = shortcut_->lfunLE->text();
3343 FuncRequest func = lyxaction.lookupFunc(fromqstr(new_lfun));
3344 KeySequence k = shortcut_->shortcutWG->getKeySequence();
3346 // save_lfun_ contains the text of the lfun to modify, if the user clicked
3347 // "modify", or is empty if they clicked "new" (which I do not really like)
3348 if (!validateNewShortcut(func, k, save_lfun_))
3351 if (!save_lfun_.isEmpty()) {
3352 // real modification of the lfun's shortcut,
3353 // so remove the previous one
3354 QList<QTreeWidgetItem*> to_modify = shortcutsTW->selectedItems();
3355 deactivateShortcuts(to_modify);
3358 shortcut_->accept();
3360 QTreeWidgetItem * item = insertShortcutItem(func, k, KeyMap::UserBind);
3362 user_bind_.bind(&k, func);
3363 shortcutsTW->sortItems(0, Qt::AscendingOrder);
3364 shortcutsTW->setItemExpanded(item->parent(), true);
3365 shortcutsTW->setCurrentItem(item);
3366 shortcutsTW->scrollToItem(item);
3368 Alert::error(_("Failed to create shortcut"),
3369 _("Can not insert shortcut to the list"));
3375 void PrefShortcuts::shortcutCancelPressed()
3377 shortcut_->shortcutWG->reset();
3381 void PrefShortcuts::shortcutClearPressed()
3383 shortcut_->shortcutWG->reset();
3387 void PrefShortcuts::shortcutRemovePressed()
3389 shortcut_->shortcutWG->removeFromSequence();
3393 /////////////////////////////////////////////////////////////////////
3397 /////////////////////////////////////////////////////////////////////
3399 PrefIdentity::PrefIdentity(GuiPreferences * form)
3400 : PrefModule(QString(), N_("Identity"), form)
3404 connect(nameED, SIGNAL(textChanged(QString)),
3405 this, SIGNAL(changed()));
3406 connect(emailED, SIGNAL(textChanged(QString)),
3407 this, SIGNAL(changed()));
3409 nameED->setValidator(new NoNewLineValidator(nameED));
3410 emailED->setValidator(new NoNewLineValidator(emailED));
3414 void PrefIdentity::applyRC(LyXRC & rc) const
3416 rc.user_name = fromqstr(nameED->text());
3417 rc.user_email = fromqstr(emailED->text());
3421 void PrefIdentity::updateRC(LyXRC const & rc)
3423 nameED->setText(toqstr(rc.user_name));
3424 emailED->setText(toqstr(rc.user_email));
3429 /////////////////////////////////////////////////////////////////////
3433 /////////////////////////////////////////////////////////////////////
3435 GuiPreferences::GuiPreferences(GuiView & lv)
3436 : GuiDialog(lv, "prefs", qt_("Preferences")), update_screen_font_(false),
3437 update_previews_(false)
3441 QDialog::setModal(false);
3443 connect(savePB, SIGNAL(clicked()), this, SLOT(slotOK()));
3444 connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
3445 connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
3446 connect(restorePB, SIGNAL(clicked()), this, SLOT(slotRestore()));
3448 addModule(new PrefUserInterface(this));
3449 addModule(new PrefDocHandling(this));
3450 addModule(new PrefEdit(this));
3451 addModule(new PrefShortcuts(this));
3452 PrefScreenFonts * screenfonts = new PrefScreenFonts(this);
3453 connect(this, SIGNAL(prefsApplied(LyXRC const &)),
3454 screenfonts, SLOT(updateScreenFontSizes(LyXRC const &)));
3455 addModule(screenfonts);
3456 addModule(new PrefColors(this));
3457 addModule(new PrefDisplay(this));
3458 addModule(new PrefInput(this));
3459 addModule(new PrefCompletion(this));
3461 addModule(new PrefPaths(this));
3463 addModule(new PrefIdentity(this));
3465 addModule(new PrefLanguage(this));
3466 addModule(new PrefSpellchecker(this));
3468 //for strftime validator
3469 PrefOutput * output = new PrefOutput(this);
3471 addModule(new PrefLatex(this));
3473 PrefConverters * converters = new PrefConverters(this);
3474 PrefFileformats * formats = new PrefFileformats(this);
3475 connect(formats, SIGNAL(formatsChanged()),
3476 converters, SLOT(updateGui()));
3477 addModule(converters);
3480 prefsPS->setCurrentPanel("User Interface");
3481 // FIXME: hack to work around resizing bug in Qt >= 4.2
3482 // bug verified with Qt 4.2.{0-3} (JSpitzm)
3483 #if QT_VERSION >= 0x040200
3484 prefsPS->updateGeometry();
3487 bc().setPolicy(ButtonPolicy::PreferencesPolicy);
3489 bc().setApply(applyPB);
3490 bc().setCancel(closePB);
3491 bc().setRestore(restorePB);
3493 // initialize the strftime validator
3494 bc().addCheckedLineEdit(output->DateED);
3498 void GuiPreferences::addModule(PrefModule * module)
3500 LASSERT(module, return);
3501 if (module->category().isEmpty())
3502 prefsPS->addPanel(module, module->title());
3504 prefsPS->addPanel(module, module->title(), module->category());
3505 connect(module, SIGNAL(changed()), this, SLOT(change_adaptor()));
3506 modules_.push_back(module);
3510 void GuiPreferences::change_adaptor()
3516 void GuiPreferences::applyRC(LyXRC & rc) const
3518 size_t end = modules_.size();
3519 for (size_t i = 0; i != end; ++i)
3520 modules_[i]->applyRC(rc);
3524 void GuiPreferences::updateRC(LyXRC const & rc)
3526 size_t const end = modules_.size();
3527 for (size_t i = 0; i != end; ++i)
3528 modules_[i]->updateRC(rc);
3532 void GuiPreferences::applyView()
3538 bool GuiPreferences::initialiseParams(string const &)
3541 formats_ = theFormats();
3542 converters_ = theConverters();
3543 converters_.update(formats_);
3544 movers_ = theMovers();
3546 update_screen_font_ = false;
3547 update_previews_ = false;
3550 // Make sure that the bc is in the INITIAL state
3551 if (bc().policy().buttonStatus(ButtonPolicy::RESTORE))
3558 void GuiPreferences::dispatchParams()
3561 rc_.write(ss, true);
3562 dispatch(FuncRequest(LFUN_LYXRC_APPLY, ss.str()));
3563 // issue prefsApplied signal. This will update the
3564 // localized screen font sizes.
3566 // FIXME: these need lfuns
3568 Author const & author =
3569 Author(from_utf8(rc_.user_name), from_utf8(rc_.user_email));
3570 theBufferList().recordCurrentAuthor(author);
3572 theFormats() = formats_;
3574 theConverters() = converters_;
3575 theConverters().update(formats_);
3576 theConverters().buildGraph();
3577 theBufferList().invalidateConverterCache();
3579 theMovers() = movers_;
3581 vector<string>::const_iterator it = colors_.begin();
3582 vector<string>::const_iterator const end = colors_.end();
3583 for (; it != end; ++it)
3584 dispatch(FuncRequest(LFUN_SET_COLOR, *it));
3587 if (update_screen_font_) {
3588 dispatch(FuncRequest(LFUN_SCREEN_FONT_UPDATE));
3589 // resets flag in case second apply in same dialog
3590 update_screen_font_ = false;
3593 if (update_previews_) {
3594 // resets flag in case second apply in same dialog
3595 theBufferList().updatePreviews();
3596 update_previews_ = false;
3599 // The Save button has been pressed
3601 dispatch(FuncRequest(LFUN_PREFERENCES_SAVE));
3605 void GuiPreferences::setColor(ColorCode col, QString const & hex)
3607 colors_.push_back(lcolor.getLyXName(col) + ' ' + fromqstr(hex));
3611 void GuiPreferences::updateScreenFonts()
3613 update_screen_font_ = true;
3617 void GuiPreferences::updatePreviews()
3619 update_previews_ = true;
3623 QString GuiPreferences::browsebind(QString const & file) const
3625 return browseLibFile("bind", file, "bind", qt_("Choose bind file"),
3626 QStringList(qt_("LyX bind files (*.bind)")));
3630 QString GuiPreferences::browseUI(QString const & file) const
3632 return browseLibFile("ui", file, "ui", qt_("Choose UI file"),
3633 QStringList(qt_("LyX UI files (*.ui)")));
3637 QString GuiPreferences::browsekbmap(QString const & file) const
3639 return browseLibFile("kbd", file, "kmap", qt_("Choose keyboard map"),
3640 QStringList(qt_("LyX keyboard maps (*.kmap)")));
3644 QString GuiPreferences::browse(QString const & file,
3645 QString const & title) const
3647 return browseFile(file, title, QStringList(), true);
3651 Dialog * createGuiPreferences(GuiView & lv) { return new GuiPreferences(lv); }
3654 } // namespace frontend
3657 #include "moc_GuiPrefs.cpp"