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();
1107 void PrefScreenFonts::updateRC(LyXRC const & rc)
1109 setComboxFont(screenRomanCO, rc.roman_font_name,
1110 rc.roman_font_foundry);
1111 setComboxFont(screenSansCO, rc.sans_font_name,
1112 rc.sans_font_foundry);
1113 setComboxFont(screenTypewriterCO, rc.typewriter_font_name,
1114 rc.typewriter_font_foundry);
1116 selectRoman(screenRomanCO->currentText());
1117 selectSans(screenSansCO->currentText());
1118 selectTypewriter(screenTypewriterCO->currentText());
1120 screenZoomSB->setValue(rc.defaultZoom);
1121 updateScreenFontSizes(rc);
1123 pixmapCacheCB->setChecked(rc.use_pixmap_cache);
1124 #if defined(Q_WS_X11) || defined(QPA_XCB)
1125 pixmapCacheCB->setEnabled(false);
1127 pixmapCacheCB->hide();
1131 void PrefScreenFonts::updateScreenFontSizes(LyXRC const & rc)
1133 doubleToWidget(screenTinyED, rc.font_sizes[FONT_SIZE_TINY]);
1134 doubleToWidget(screenSmallestED, rc.font_sizes[FONT_SIZE_SCRIPT]);
1135 doubleToWidget(screenSmallerED, rc.font_sizes[FONT_SIZE_FOOTNOTE]);
1136 doubleToWidget(screenSmallED, rc.font_sizes[FONT_SIZE_SMALL]);
1137 doubleToWidget(screenNormalED, rc.font_sizes[FONT_SIZE_NORMAL]);
1138 doubleToWidget(screenLargeED, rc.font_sizes[FONT_SIZE_LARGE]);
1139 doubleToWidget(screenLargerED, rc.font_sizes[FONT_SIZE_LARGER]);
1140 doubleToWidget(screenLargestED, rc.font_sizes[FONT_SIZE_LARGEST]);
1141 doubleToWidget(screenHugeED, rc.font_sizes[FONT_SIZE_HUGE]);
1142 doubleToWidget(screenHugerED, rc.font_sizes[FONT_SIZE_HUGER]);
1146 void PrefScreenFonts::selectRoman(const QString & name)
1148 screenRomanFE->set(QFont(name), name);
1152 void PrefScreenFonts::selectSans(const QString & name)
1154 screenSansFE->set(QFont(name), name);
1158 void PrefScreenFonts::selectTypewriter(const QString & name)
1160 screenTypewriterFE->set(QFont(name), name);
1164 /////////////////////////////////////////////////////////////////////
1168 /////////////////////////////////////////////////////////////////////
1171 PrefColors::PrefColors(GuiPreferences * form)
1172 : PrefModule(catLookAndFeel, N_("Colors"), form)
1176 // FIXME: all of this initialization should be put into the controller.
1177 // See http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg113301.html
1178 // for some discussion of why that is not trivial.
1179 QPixmap icon(32, 32);
1180 for (int i = 0; i < Color_ignore; ++i) {
1181 ColorCode lc = static_cast<ColorCode>(i);
1182 if (lc == Color_none
1183 || lc == Color_black
1184 || lc == Color_white
1186 || lc == Color_brown
1188 || lc == Color_darkgray
1190 || lc == Color_green
1191 || lc == Color_lightgray
1193 || lc == Color_magenta
1194 || lc == Color_olive
1195 || lc == Color_orange
1197 || lc == Color_purple
1200 || lc == Color_violet
1201 || lc == Color_yellow
1202 || lc == Color_inherit
1203 || lc == Color_ignore)
1205 lcolors_.push_back(lc);
1207 sort(lcolors_.begin(), lcolors_.end(), ColorSorter);
1208 vector<ColorCode>::const_iterator cit = lcolors_.begin();
1209 vector<ColorCode>::const_iterator const end = lcolors_.end();
1210 for (; cit != end; ++cit) {
1211 (void) new QListWidgetItem(QIcon(icon),
1212 toqstr(lcolor.getGUIName(*cit)), lyxObjectsLW);
1214 curcolors_.resize(lcolors_.size());
1215 newcolors_.resize(lcolors_.size());
1216 // End initialization
1218 connect(colorChangePB, SIGNAL(clicked()),
1219 this, SLOT(changeColor()));
1220 connect(colorResetPB, SIGNAL(clicked()),
1221 this, SLOT(resetColor()));
1222 connect(colorResetAllPB, SIGNAL(clicked()),
1223 this, SLOT(resetAllColor()));
1224 connect(lyxObjectsLW, SIGNAL(itemSelectionChanged()),
1225 this, SLOT(changeLyxObjectsSelection()));
1226 connect(lyxObjectsLW, SIGNAL(itemActivated(QListWidgetItem*)),
1227 this, SLOT(changeColor()));
1228 connect(syscolorsCB, SIGNAL(toggled(bool)),
1229 this, SIGNAL(changed()));
1230 connect(syscolorsCB, SIGNAL(toggled(bool)),
1231 this, SLOT(changeSysColor()));
1235 void PrefColors::applyRC(LyXRC & rc) const
1239 for (unsigned int i = 0; i < lcolors_.size(); ++i)
1240 if (curcolors_[i] != newcolors_[i])
1241 form_->setColor(lcolors_[i], newcolors_[i]);
1242 rc.use_system_colors = syscolorsCB->isChecked();
1244 if (oldrc.use_system_colors != rc.use_system_colors)
1245 guiApp->colorCache().clear();
1249 void PrefColors::updateRC(LyXRC const & rc)
1251 for (size_type i = 0; i < lcolors_.size(); ++i) {
1252 QColor color = QColor(guiApp->colorCache().get(lcolors_[i], false));
1253 QPixmap coloritem(32, 32);
1254 coloritem.fill(color);
1255 lyxObjectsLW->item(int(i))->setIcon(QIcon(coloritem));
1256 newcolors_[i] = curcolors_[i] = color.name();
1258 syscolorsCB->setChecked(rc.use_system_colors);
1259 changeLyxObjectsSelection();
1261 setDisabledResets();
1265 void PrefColors::changeColor()
1267 int const row = lyxObjectsLW->currentRow();
1273 QString const color = newcolors_[size_t(row)];
1274 QColor const c = QColorDialog::getColor(QColor(color), qApp->focusWidget());
1276 if (setColor(row, c, color)) {
1277 setDisabledResets();
1284 void PrefColors::resetColor()
1286 int const row = lyxObjectsLW->currentRow();
1292 QString const color = newcolors_[size_t(row)];
1293 QColor const c = getDefaultColorByRow(row);
1295 if (setColor(row, c, color)) {
1296 setDisabledResets();
1303 void PrefColors::resetAllColor()
1305 bool isChanged = false;
1307 colorResetAllPB->setDisabled(true);
1309 for (int irow = 0, count = lyxObjectsLW->count(); irow < count; ++irow) {
1310 QString const color = newcolors_[size_t(irow)];
1311 QColor const c = getDefaultColorByRow(irow);
1313 if (setColor(irow, c, color))
1318 setDisabledResets();
1325 bool PrefColors::setColor(int const row, QColor const new_color,
1326 QString const old_color)
1328 if (new_color.isValid() && new_color.name() != old_color) {
1329 newcolors_[size_t(row)] = new_color.name();
1330 QPixmap coloritem(32, 32);
1331 coloritem.fill(new_color);
1332 lyxObjectsLW->item(row)->setIcon(QIcon(coloritem));
1339 void PrefColors::setDisabledResets()
1341 int const row = lyxObjectsLW->currentRow();
1342 // set disable reset buttons ...
1344 colorResetPB->setDisabled(isDefaultColor(row, newcolors_[size_t(row)]));
1346 colorResetAllPB->setDisabled(true);
1348 // ... in between process qt events to give quicker visual feedback to the user ...
1349 guiApp->processEvents();
1351 // ... set disable Reset All button
1352 for (int irow = 0, count = lyxObjectsLW->count(); irow < count; ++irow) {
1353 if (!isDefaultColor(irow, newcolors_[size_t(irow)])) {
1354 colorResetAllPB->setDisabled(false);
1355 // the break condition might hide performance issues
1356 // if a non-default color is at the top of the list
1363 bool PrefColors::isDefaultColor(int const row, QString const color)
1365 return color == getDefaultColorByRow(row).name();
1369 QColor PrefColors::getDefaultColorByRow(int const row)
1371 ColorSet const defaultcolor;
1372 return defaultcolor.getX11Name(lcolors_[size_t(row)]).c_str();
1376 void PrefColors::changeSysColor()
1378 for (int row = 0 ; row < lyxObjectsLW->count() ; ++row) {
1379 // skip colors that are taken from system palette
1380 bool const disable = syscolorsCB->isChecked()
1381 && guiApp->colorCache().isSystem(lcolors_[size_t(row)]);
1383 QListWidgetItem * const item = lyxObjectsLW->item(row);
1384 Qt::ItemFlags const flags = item->flags();
1387 item->setFlags(flags & ~Qt::ItemIsEnabled);
1389 item->setFlags(flags | Qt::ItemIsEnabled);
1394 void PrefColors::changeLyxObjectsSelection()
1396 int currentRow = lyxObjectsLW->currentRow();
1397 colorChangePB->setDisabled(currentRow < 0);
1400 colorResetPB->setDisabled(true);
1402 colorResetPB->setDisabled(
1403 isDefaultColor(currentRow, newcolors_[size_t(currentRow)]));
1407 /////////////////////////////////////////////////////////////////////
1411 /////////////////////////////////////////////////////////////////////
1413 PrefDisplay::PrefDisplay(GuiPreferences * form)
1414 : PrefModule(catLookAndFeel, N_("Display"), form)
1417 connect(displayGraphicsCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1418 connect(instantPreviewCO, SIGNAL(activated(int)), this, SIGNAL(changed()));
1419 connect(previewSizeSB, SIGNAL(valueChanged(double)), this, SIGNAL(changed()));
1420 connect(paragraphMarkerCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1424 void PrefDisplay::on_instantPreviewCO_currentIndexChanged(int index)
1426 previewSizeSB->setEnabled(index != 0);
1430 void PrefDisplay::applyRC(LyXRC & rc) const
1432 switch (instantPreviewCO->currentIndex()) {
1434 rc.preview = LyXRC::PREVIEW_OFF;
1437 rc.preview = LyXRC::PREVIEW_NO_MATH;
1440 rc.preview = LyXRC::PREVIEW_ON;
1444 rc.display_graphics = displayGraphicsCB->isChecked();
1445 rc.preview_scale_factor = previewSizeSB->value();
1446 rc.paragraph_markers = paragraphMarkerCB->isChecked();
1448 // FIXME!! The graphics cache no longer has a changeDisplay method.
1450 if (old_value != rc.display_graphics) {
1451 graphics::GCache & gc = graphics::GCache::get();
1458 void PrefDisplay::updateRC(LyXRC const & rc)
1460 switch (rc.preview) {
1461 case LyXRC::PREVIEW_OFF:
1462 instantPreviewCO->setCurrentIndex(0);
1464 case LyXRC::PREVIEW_NO_MATH :
1465 instantPreviewCO->setCurrentIndex(1);
1467 case LyXRC::PREVIEW_ON :
1468 instantPreviewCO->setCurrentIndex(2);
1472 displayGraphicsCB->setChecked(rc.display_graphics);
1473 previewSizeSB->setValue(rc.preview_scale_factor);
1474 paragraphMarkerCB->setChecked(rc.paragraph_markers);
1475 previewSizeSB->setEnabled(
1477 && rc.preview != LyXRC::PREVIEW_OFF);
1481 /////////////////////////////////////////////////////////////////////
1485 /////////////////////////////////////////////////////////////////////
1487 PrefPaths::PrefPaths(GuiPreferences * form)
1488 : PrefModule(QString(), N_("Paths"), form)
1492 connect(workingDirPB, SIGNAL(clicked()), this, SLOT(selectWorkingdir()));
1493 connect(workingDirED, SIGNAL(textChanged(QString)),
1494 this, SIGNAL(changed()));
1496 connect(templateDirPB, SIGNAL(clicked()), this, SLOT(selectTemplatedir()));
1497 connect(templateDirED, SIGNAL(textChanged(QString)),
1498 this, SIGNAL(changed()));
1500 connect(exampleDirPB, SIGNAL(clicked()), this, SLOT(selectExampledir()));
1501 connect(exampleDirED, SIGNAL(textChanged(QString)),
1502 this, SIGNAL(changed()));
1504 connect(backupDirPB, SIGNAL(clicked()), this, SLOT(selectBackupdir()));
1505 connect(backupDirED, SIGNAL(textChanged(QString)),
1506 this, SIGNAL(changed()));
1508 connect(lyxserverDirPB, SIGNAL(clicked()), this, SLOT(selectLyxPipe()));
1509 connect(lyxserverDirED, SIGNAL(textChanged(QString)),
1510 this, SIGNAL(changed()));
1512 connect(thesaurusDirPB, SIGNAL(clicked()), this, SLOT(selectThesaurusdir()));
1513 connect(thesaurusDirED, SIGNAL(textChanged(QString)),
1514 this, SIGNAL(changed()));
1516 connect(tempDirPB, SIGNAL(clicked()), this, SLOT(selectTempdir()));
1517 connect(tempDirED, SIGNAL(textChanged(QString)),
1518 this, SIGNAL(changed()));
1520 #if defined(USE_HUNSPELL)
1521 connect(hunspellDirPB, SIGNAL(clicked()), this, SLOT(selectHunspelldir()));
1522 connect(hunspellDirED, SIGNAL(textChanged(QString)),
1523 this, SIGNAL(changed()));
1525 hunspellDirPB->setEnabled(false);
1526 hunspellDirED->setEnabled(false);
1529 connect(pathPrefixED, SIGNAL(textChanged(QString)),
1530 this, SIGNAL(changed()));
1532 connect(texinputsPrefixED, SIGNAL(textChanged(QString)),
1533 this, SIGNAL(changed()));
1535 pathPrefixED->setValidator(new NoNewLineValidator(pathPrefixED));
1536 texinputsPrefixED->setValidator(new NoNewLineValidator(texinputsPrefixED));
1540 void PrefPaths::applyRC(LyXRC & rc) const
1542 rc.document_path = internal_path(fromqstr(workingDirED->text()));
1543 rc.example_path = internal_path(fromqstr(exampleDirED->text()));
1544 rc.template_path = internal_path(fromqstr(templateDirED->text()));
1545 rc.backupdir_path = internal_path(fromqstr(backupDirED->text()));
1546 rc.tempdir_path = internal_path(fromqstr(tempDirED->text()));
1547 rc.thesaurusdir_path = internal_path(fromqstr(thesaurusDirED->text()));
1548 rc.hunspelldir_path = internal_path(fromqstr(hunspellDirED->text()));
1549 rc.path_prefix = internal_path_list(fromqstr(pathPrefixED->text()));
1550 rc.texinputs_prefix = internal_path_list(fromqstr(texinputsPrefixED->text()));
1551 // FIXME: should be a checkbox only
1552 rc.lyxpipes = internal_path(fromqstr(lyxserverDirED->text()));
1556 void PrefPaths::updateRC(LyXRC const & rc)
1558 workingDirED->setText(toqstr(external_path(rc.document_path)));
1559 exampleDirED->setText(toqstr(external_path(rc.example_path)));
1560 templateDirED->setText(toqstr(external_path(rc.template_path)));
1561 backupDirED->setText(toqstr(external_path(rc.backupdir_path)));
1562 tempDirED->setText(toqstr(external_path(rc.tempdir_path)));
1563 thesaurusDirED->setText(toqstr(external_path(rc.thesaurusdir_path)));
1564 hunspellDirED->setText(toqstr(external_path(rc.hunspelldir_path)));
1565 pathPrefixED->setText(toqstr(external_path_list(rc.path_prefix)));
1566 texinputsPrefixED->setText(toqstr(external_path_list(rc.texinputs_prefix)));
1567 // FIXME: should be a checkbox only
1568 lyxserverDirED->setText(toqstr(external_path(rc.lyxpipes)));
1572 void PrefPaths::selectExampledir()
1574 QString file = browseDir(internalPath(exampleDirED->text()),
1575 qt_("Select directory for example files"));
1576 if (!file.isEmpty())
1577 exampleDirED->setText(file);
1581 void PrefPaths::selectTemplatedir()
1583 QString file = browseDir(internalPath(templateDirED->text()),
1584 qt_("Select a document templates directory"));
1585 if (!file.isEmpty())
1586 templateDirED->setText(file);
1590 void PrefPaths::selectTempdir()
1592 QString file = browseDir(internalPath(tempDirED->text()),
1593 qt_("Select a temporary directory"));
1594 if (!file.isEmpty())
1595 tempDirED->setText(file);
1599 void PrefPaths::selectBackupdir()
1601 QString file = browseDir(internalPath(backupDirED->text()),
1602 qt_("Select a backups directory"));
1603 if (!file.isEmpty())
1604 backupDirED->setText(file);
1608 void PrefPaths::selectWorkingdir()
1610 QString file = browseDir(internalPath(workingDirED->text()),
1611 qt_("Select a document directory"));
1612 if (!file.isEmpty())
1613 workingDirED->setText(file);
1617 void PrefPaths::selectThesaurusdir()
1619 QString file = browseDir(internalPath(thesaurusDirED->text()),
1620 qt_("Set the path to the thesaurus dictionaries"));
1621 if (!file.isEmpty())
1622 thesaurusDirED->setText(file);
1626 void PrefPaths::selectHunspelldir()
1628 QString file = browseDir(internalPath(hunspellDirED->text()),
1629 qt_("Set the path to the Hunspell dictionaries"));
1630 if (!file.isEmpty())
1631 hunspellDirED->setText(file);
1635 void PrefPaths::selectLyxPipe()
1637 QString file = form_->browse(internalPath(lyxserverDirED->text()),
1638 qt_("Give a filename for the LyX server pipe"));
1639 if (!file.isEmpty())
1640 lyxserverDirED->setText(file);
1644 /////////////////////////////////////////////////////////////////////
1648 /////////////////////////////////////////////////////////////////////
1650 PrefSpellchecker::PrefSpellchecker(GuiPreferences * form)
1651 : PrefModule(catLanguage, N_("Spellchecker"), form)
1655 // FIXME: this check should test the target platform (darwin)
1656 #if defined(USE_MACOSX_PACKAGING)
1657 spellcheckerCB->addItem(qt_("Native"), QString("native"));
1658 #define CONNECT_APPLESPELL
1660 #undef CONNECT_APPLESPELL
1662 #if defined(USE_ASPELL)
1663 spellcheckerCB->addItem(qt_("Aspell"), QString("aspell"));
1665 #if defined(USE_ENCHANT)
1666 spellcheckerCB->addItem(qt_("Enchant"), QString("enchant"));
1668 #if defined(USE_HUNSPELL)
1669 spellcheckerCB->addItem(qt_("Hunspell"), QString("hunspell"));
1672 #if defined(CONNECT_APPLESPELL) || defined(USE_ASPELL) || defined(USE_ENCHANT) || defined(USE_HUNSPELL)
1673 connect(spellcheckerCB, SIGNAL(currentIndexChanged(int)),
1674 this, SIGNAL(changed()));
1675 connect(altLanguageED, SIGNAL(textChanged(QString)),
1676 this, SIGNAL(changed()));
1677 connect(escapeCharactersED, SIGNAL(textChanged(QString)),
1678 this, SIGNAL(changed()));
1679 connect(compoundWordCB, SIGNAL(clicked()),
1680 this, SIGNAL(changed()));
1681 connect(spellcheckContinuouslyCB, SIGNAL(clicked()),
1682 this, SIGNAL(changed()));
1683 connect(spellcheckNotesCB, SIGNAL(clicked()),
1684 this, SIGNAL(changed()));
1686 altLanguageED->setValidator(new NoNewLineValidator(altLanguageED));
1687 escapeCharactersED->setValidator(new NoNewLineValidator(escapeCharactersED));
1689 spellcheckerCB->setEnabled(false);
1690 altLanguageED->setEnabled(false);
1691 escapeCharactersED->setEnabled(false);
1692 compoundWordCB->setEnabled(false);
1693 spellcheckContinuouslyCB->setEnabled(false);
1694 spellcheckNotesCB->setEnabled(false);
1699 void PrefSpellchecker::applyRC(LyXRC & rc) const
1701 string const speller = fromqstr(spellcheckerCB->
1702 itemData(spellcheckerCB->currentIndex()).toString());
1703 if (!speller.empty())
1704 rc.spellchecker = speller;
1705 rc.spellchecker_alt_lang = fromqstr(altLanguageED->text());
1706 rc.spellchecker_esc_chars = fromqstr(escapeCharactersED->text());
1707 rc.spellchecker_accept_compound = compoundWordCB->isChecked();
1708 rc.spellcheck_continuously = spellcheckContinuouslyCB->isChecked();
1709 rc.spellcheck_notes = spellcheckNotesCB->isChecked();
1713 void PrefSpellchecker::updateRC(LyXRC const & rc)
1715 spellcheckerCB->setCurrentIndex(
1716 spellcheckerCB->findData(toqstr(rc.spellchecker)));
1717 altLanguageED->setText(toqstr(rc.spellchecker_alt_lang));
1718 escapeCharactersED->setText(toqstr(rc.spellchecker_esc_chars));
1719 compoundWordCB->setChecked(rc.spellchecker_accept_compound);
1720 spellcheckContinuouslyCB->setChecked(rc.spellcheck_continuously);
1721 spellcheckNotesCB->setChecked(rc.spellcheck_notes);
1725 void PrefSpellchecker::on_spellcheckerCB_currentIndexChanged(int index)
1727 QString spellchecker = spellcheckerCB->itemData(index).toString();
1729 compoundWordCB->setEnabled(spellchecker == QString("aspell"));
1734 /////////////////////////////////////////////////////////////////////
1738 /////////////////////////////////////////////////////////////////////
1741 PrefConverters::PrefConverters(GuiPreferences * form)
1742 : PrefModule(catFiles, N_("Converters"), form)
1746 connect(converterNewPB, SIGNAL(clicked()),
1747 this, SLOT(updateConverter()));
1748 connect(converterRemovePB, SIGNAL(clicked()),
1749 this, SLOT(removeConverter()));
1750 connect(converterModifyPB, SIGNAL(clicked()),
1751 this, SLOT(updateConverter()));
1752 connect(convertersLW, SIGNAL(currentRowChanged(int)),
1753 this, SLOT(switchConverter()));
1754 connect(converterFromCO, SIGNAL(activated(QString)),
1755 this, SLOT(changeConverter()));
1756 connect(converterToCO, SIGNAL(activated(QString)),
1757 this, SLOT(changeConverter()));
1758 connect(converterED, SIGNAL(textEdited(QString)),
1759 this, SLOT(changeConverter()));
1760 connect(converterFlagED, SIGNAL(textEdited(QString)),
1761 this, SLOT(changeConverter()));
1762 connect(converterNewPB, SIGNAL(clicked()),
1763 this, SIGNAL(changed()));
1764 connect(converterRemovePB, SIGNAL(clicked()),
1765 this, SIGNAL(changed()));
1766 connect(converterModifyPB, SIGNAL(clicked()),
1767 this, SIGNAL(changed()));
1768 connect(maxAgeLE, SIGNAL(textEdited(QString)),
1769 this, SIGNAL(changed()));
1770 connect(needauthForbiddenCB, SIGNAL(toggled(bool)),
1771 this, SIGNAL(changed()));
1773 converterED->setValidator(new NoNewLineValidator(converterED));
1774 converterFlagED->setValidator(new NoNewLineValidator(converterFlagED));
1775 maxAgeLE->setValidator(new QDoubleValidator(0, HUGE_VAL, 6, maxAgeLE));
1776 //converterDefGB->setFocusProxy(convertersLW);
1780 void PrefConverters::applyRC(LyXRC & rc) const
1782 rc.use_converter_cache = cacheCB->isChecked();
1783 rc.use_converter_needauth_forbidden = needauthForbiddenCB->isChecked();
1784 rc.use_converter_needauth = needauthCB->isChecked();
1785 rc.converter_cache_maxage = int(widgetToDouble(maxAgeLE) * 86400.0);
1789 static void setCheckboxBlockSignals(QCheckBox *cb, bool checked) {
1790 cb->blockSignals(true);
1791 cb->setChecked(checked);
1792 cb->blockSignals(false);
1796 void PrefConverters::updateRC(LyXRC const & rc)
1798 cacheCB->setChecked(rc.use_converter_cache);
1799 needauthForbiddenCB->setChecked(rc.use_converter_needauth_forbidden);
1800 setCheckboxBlockSignals(needauthCB, rc.use_converter_needauth);
1802 doubleToWidget(maxAgeLE, (double(rc.converter_cache_maxage) / 86400.0), 'g', 6);
1807 void PrefConverters::updateGui()
1809 QString const pattern("%1 -> %2");
1810 form_->formats().sort();
1811 form_->converters().update(form_->formats());
1812 // save current selection
1815 .arg(converterFromCO->currentText())
1816 .arg(converterToCO->currentText());
1818 converterFromCO->clear();
1819 converterToCO->clear();
1821 for (Format const & f : form_->formats()) {
1822 QString const name = toqstr(translateIfPossible(f.prettyname()));
1823 converterFromCO->addItem(name);
1824 converterToCO->addItem(name);
1827 // currentRowChanged(int) is also triggered when updating the listwidget
1828 // block signals to avoid unnecessary calls to switchConverter()
1829 convertersLW->blockSignals(true);
1830 convertersLW->clear();
1832 for (Converter const & c : form_->converters()) {
1833 QString const name =
1835 .arg(toqstr(translateIfPossible(c.From()->prettyname())))
1836 .arg(toqstr(translateIfPossible(c.To()->prettyname())));
1837 int type = form_->converters().getNumber(c.From()->name(),
1839 new QListWidgetItem(name, convertersLW, type);
1841 convertersLW->sortItems(Qt::AscendingOrder);
1842 convertersLW->blockSignals(false);
1844 // restore selection
1845 if (current != pattern.arg(QString()).arg(QString())) {
1846 QList<QListWidgetItem *> const item =
1847 convertersLW->findItems(current, Qt::MatchExactly);
1848 if (!item.isEmpty())
1849 convertersLW->setCurrentItem(item.at(0));
1852 // select first element if restoring failed
1853 if (convertersLW->currentRow() == -1)
1854 convertersLW->setCurrentRow(0);
1860 void PrefConverters::switchConverter()
1862 int const cnr = convertersLW->currentItem()->type();
1863 Converter const & c(form_->converters().get(cnr));
1864 converterFromCO->setCurrentIndex(form_->formats().getNumber(c.from()));
1865 converterToCO->setCurrentIndex(form_->formats().getNumber(c.to()));
1866 converterED->setText(toqstr(c.command()));
1867 converterFlagED->setText(toqstr(c.flags()));
1873 void PrefConverters::changeConverter()
1879 void PrefConverters::updateButtons()
1881 if (form_->formats().empty())
1883 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1884 Format const & to = form_->formats().get(converterToCO->currentIndex());
1885 int const sel = form_->converters().getNumber(from.name(), to.name());
1886 bool const known = sel >= 0;
1887 bool const valid = !(converterED->text().isEmpty()
1888 || from.name() == to.name());
1893 if (convertersLW->count() > 0) {
1894 int const cnr = convertersLW->currentItem()->type();
1895 Converter const & c = form_->converters().get(cnr);
1896 old_command = c.command();
1897 old_flag = c.flags();
1900 string const new_command = fromqstr(converterED->text());
1901 string const new_flag = fromqstr(converterFlagED->text());
1903 bool modified = (old_command != new_command || old_flag != new_flag);
1905 converterModifyPB->setEnabled(valid && known && modified);
1906 converterNewPB->setEnabled(valid && !known);
1907 converterRemovePB->setEnabled(known);
1909 maxAgeLE->setEnabled(cacheCB->isChecked());
1910 maxAgeLA->setEnabled(cacheCB->isChecked());
1915 // specify unique from/to or it doesn't appear. This is really bad UI
1916 // this is why we can use the same function for both new and modify
1917 void PrefConverters::updateConverter()
1919 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1920 Format const & to = form_->formats().get(converterToCO->currentIndex());
1921 string const flags = fromqstr(converterFlagED->text());
1922 string const command = fromqstr(converterED->text());
1924 Converter const * old =
1925 form_->converters().getConverter(from.name(), to.name());
1926 form_->converters().add(from.name(), to.name(), command, flags);
1929 form_->converters().updateLast(form_->formats());
1933 // Remove all files created by this converter from the cache, since
1934 // the modified converter might create different files.
1935 ConverterCache::get().remove_all(from.name(), to.name());
1939 void PrefConverters::removeConverter()
1941 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1942 Format const & to = form_->formats().get(converterToCO->currentIndex());
1943 form_->converters().erase(from.name(), to.name());
1947 // Remove all files created by this converter from the cache, since
1948 // a possible new converter might create different files.
1949 ConverterCache::get().remove_all(from.name(), to.name());
1953 void PrefConverters::on_cacheCB_stateChanged(int state)
1955 maxAgeLE->setEnabled(state == Qt::Checked);
1956 maxAgeLA->setEnabled(state == Qt::Checked);
1961 void PrefConverters::on_needauthForbiddenCB_toggled(bool checked)
1963 needauthCB->setEnabled(!checked);
1967 void PrefConverters::on_needauthCB_toggled(bool checked)
1974 int ret = frontend::Alert::prompt(
1975 _("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!"),
1976 0, 0, _("&No"), _("&Yes"));
1980 setCheckboxBlockSignals(needauthCB, true);
1984 /////////////////////////////////////////////////////////////////////
1988 /////////////////////////////////////////////////////////////////////
1990 class FormatValidator : public QValidator
1993 FormatValidator(QWidget *, Formats const & f);
1994 void fixup(QString & input) const;
1995 QValidator::State validate(QString & input, int & pos) const;
1997 virtual QString toString(Format const & format) const = 0;
1999 Formats const & formats_;
2003 FormatValidator::FormatValidator(QWidget * parent, Formats const & f)
2004 : QValidator(parent), formats_(f)
2009 void FormatValidator::fixup(QString & input) const
2011 Formats::const_iterator cit = formats_.begin();
2012 Formats::const_iterator end = formats_.end();
2013 for (; cit != end; ++cit) {
2014 QString const name = toString(*cit);
2015 if (distance(formats_.begin(), cit) == nr()) {
2023 QValidator::State FormatValidator::validate(QString & input, int & /*pos*/) const
2025 Formats::const_iterator cit = formats_.begin();
2026 Formats::const_iterator end = formats_.end();
2027 bool unknown = true;
2028 for (; unknown && cit != end; ++cit) {
2029 QString const name = toString(*cit);
2030 if (distance(formats_.begin(), cit) != nr())
2031 unknown = name != input;
2034 if (unknown && !input.isEmpty())
2035 return QValidator::Acceptable;
2037 return QValidator::Intermediate;
2041 int FormatValidator::nr() const
2043 QComboBox * p = qobject_cast<QComboBox *>(parent());
2044 return p->itemData(p->currentIndex()).toInt();
2048 /////////////////////////////////////////////////////////////////////
2050 // FormatNameValidator
2052 /////////////////////////////////////////////////////////////////////
2054 class FormatNameValidator : public FormatValidator
2057 FormatNameValidator(QWidget * parent, Formats const & f)
2058 : FormatValidator(parent, f)
2061 QString toString(Format const & format) const
2063 return toqstr(format.name());
2068 /////////////////////////////////////////////////////////////////////
2070 // FormatPrettynameValidator
2072 /////////////////////////////////////////////////////////////////////
2074 class FormatPrettynameValidator : public FormatValidator
2077 FormatPrettynameValidator(QWidget * parent, Formats const & f)
2078 : FormatValidator(parent, f)
2081 QString toString(Format const & format) const
2083 return toqstr(translateIfPossible(format.prettyname()));
2088 /////////////////////////////////////////////////////////////////////
2092 /////////////////////////////////////////////////////////////////////
2094 PrefFileformats::PrefFileformats(GuiPreferences * form)
2095 : PrefModule(catFiles, N_("File Formats"), form)
2099 formatED->setValidator(new FormatNameValidator(formatsCB, form_->formats()));
2100 formatsCB->setValidator(new FormatPrettynameValidator(formatsCB, form_->formats()));
2101 extensionsED->setValidator(new NoNewLineValidator(extensionsED));
2102 shortcutED->setValidator(new NoNewLineValidator(shortcutED));
2103 editorED->setValidator(new NoNewLineValidator(editorED));
2104 viewerED->setValidator(new NoNewLineValidator(viewerED));
2105 copierED->setValidator(new NoNewLineValidator(copierED));
2107 connect(documentCB, SIGNAL(clicked()),
2108 this, SLOT(setFlags()));
2109 connect(vectorCB, SIGNAL(clicked()),
2110 this, SLOT(setFlags()));
2111 connect(exportMenuCB, SIGNAL(clicked()),
2112 this, SLOT(setFlags()));
2113 connect(formatsCB->lineEdit(), SIGNAL(editingFinished()),
2114 this, SLOT(updatePrettyname()));
2115 connect(formatsCB->lineEdit(), SIGNAL(textEdited(QString)),
2116 this, SIGNAL(changed()));
2117 connect(defaultFormatCB, SIGNAL(activated(QString)),
2118 this, SIGNAL(changed()));
2119 connect(defaultOTFFormatCB, SIGNAL(activated(QString)),
2120 this, SIGNAL(changed()));
2121 connect(defaultPlatexFormatCB, SIGNAL(activated(QString)),
2122 this, SIGNAL(changed()));
2123 connect(viewerCO, SIGNAL(activated(int)),
2124 this, SIGNAL(changed()));
2125 connect(editorCO, SIGNAL(activated(int)),
2126 this, SIGNAL(changed()));
2132 string const l10n_shortcut(docstring const & prettyname, string const & shortcut)
2134 if (shortcut.empty())
2137 string l10n_format =
2138 to_utf8(_(to_utf8(prettyname) + '|' + shortcut));
2139 return split(l10n_format, '|');
2145 void PrefFileformats::applyRC(LyXRC & rc) const
2147 QString const default_format = defaultFormatCB->itemData(
2148 defaultFormatCB->currentIndex()).toString();
2149 rc.default_view_format = fromqstr(default_format);
2150 QString const default_otf_format = defaultOTFFormatCB->itemData(
2151 defaultOTFFormatCB->currentIndex()).toString();
2152 rc.default_otf_view_format = fromqstr(default_otf_format);
2153 QString const default_platex_format = defaultPlatexFormatCB->itemData(
2154 defaultPlatexFormatCB->currentIndex()).toString();
2155 rc.default_platex_view_format = fromqstr(default_platex_format);
2159 void PrefFileformats::updateRC(LyXRC const & rc)
2161 viewer_alternatives = rc.viewer_alternatives;
2162 editor_alternatives = rc.editor_alternatives;
2163 bool const init = defaultFormatCB->currentText().isEmpty();
2167 defaultFormatCB->findData(toqstr(rc.default_view_format));
2168 defaultFormatCB->setCurrentIndex(pos);
2169 pos = defaultOTFFormatCB->findData(toqstr(rc.default_otf_view_format));
2170 defaultOTFFormatCB->setCurrentIndex(pos);
2171 defaultOTFFormatCB->setCurrentIndex(pos);
2172 pos = defaultPlatexFormatCB->findData(toqstr(rc.default_platex_view_format));
2173 defaultPlatexFormatCB->setCurrentIndex(pos);
2174 defaultPlatexFormatCB->setCurrentIndex(pos);
2179 void PrefFileformats::updateView()
2181 QString const current = formatsCB->currentText();
2182 QString const current_def = defaultFormatCB->currentText();
2183 QString const current_def_otf = defaultOTFFormatCB->currentText();
2184 QString const current_def_platex = defaultPlatexFormatCB->currentText();
2186 // update comboboxes with formats
2187 formatsCB->blockSignals(true);
2188 defaultFormatCB->blockSignals(true);
2189 defaultOTFFormatCB->blockSignals(true);
2190 defaultPlatexFormatCB->blockSignals(true);
2192 defaultFormatCB->clear();
2193 defaultOTFFormatCB->clear();
2194 defaultPlatexFormatCB->clear();
2195 form_->formats().sort();
2196 for (Format const & f : form_->formats()) {
2197 QString const prettyname = toqstr(translateIfPossible(f.prettyname()));
2198 formatsCB->addItem(prettyname,
2199 QVariant(form_->formats().getNumber(f.name())));
2200 if (f.viewer().empty())
2202 if (form_->converters().isReachable("xhtml", f.name())
2203 || form_->converters().isReachable("dviluatex", f.name())
2204 || form_->converters().isReachable("luatex", f.name())
2205 || form_->converters().isReachable("xetex", f.name())) {
2206 defaultFormatCB->addItem(prettyname,
2207 QVariant(toqstr(f.name())));
2208 defaultOTFFormatCB->addItem(prettyname,
2209 QVariant(toqstr(f.name())));
2211 if (form_->converters().isReachable("latex", f.name())
2212 || form_->converters().isReachable("pdflatex", f.name()))
2213 defaultFormatCB->addItem(prettyname,
2214 QVariant(toqstr(f.name())));
2215 if (form_->converters().isReachable("platex", f.name()))
2216 defaultPlatexFormatCB->addItem(prettyname,
2217 QVariant(toqstr(f.name())));
2221 // restore selections
2222 int item = formatsCB->findText(current, Qt::MatchExactly);
2223 formatsCB->setCurrentIndex(item < 0 ? 0 : item);
2224 on_formatsCB_currentIndexChanged(item < 0 ? 0 : item);
2225 item = defaultFormatCB->findText(current_def, Qt::MatchExactly);
2226 defaultFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2227 item = defaultOTFFormatCB->findText(current_def_otf, Qt::MatchExactly);
2228 defaultOTFFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2229 item = defaultPlatexFormatCB->findText(current_def_platex, Qt::MatchExactly);
2230 defaultPlatexFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2231 formatsCB->blockSignals(false);
2232 defaultFormatCB->blockSignals(false);
2233 defaultOTFFormatCB->blockSignals(false);
2234 defaultPlatexFormatCB->blockSignals(false);
2238 void PrefFileformats::on_formatsCB_currentIndexChanged(int i)
2240 if (form_->formats().empty())
2242 int const nr = formatsCB->itemData(i).toInt();
2243 Format const f = form_->formats().get(nr);
2245 formatED->setText(toqstr(f.name()));
2246 copierED->setText(toqstr(form_->movers().command(f.name())));
2247 extensionsED->setText(toqstr(f.extensions()));
2248 mimeED->setText(toqstr(f.mime()));
2249 shortcutED->setText(
2250 toqstr(l10n_shortcut(f.prettyname(), f.shortcut())));
2251 documentCB->setChecked((f.documentFormat()));
2252 vectorCB->setChecked((f.vectorFormat()));
2253 exportMenuCB->setChecked((f.inExportMenu()));
2254 exportMenuCB->setEnabled((f.documentFormat()));
2260 void PrefFileformats::setFlags()
2262 int flags = Format::none;
2263 if (documentCB->isChecked())
2264 flags |= Format::document;
2265 if (vectorCB->isChecked())
2266 flags |= Format::vector;
2267 if (exportMenuCB->isChecked())
2268 flags |= Format::export_menu;
2269 currentFormat().setFlags(flags);
2270 exportMenuCB->setEnabled(documentCB->isChecked());
2275 void PrefFileformats::on_copierED_textEdited(const QString & s)
2277 string const fmt = fromqstr(formatED->text());
2278 form_->movers().set(fmt, fromqstr(s));
2283 void PrefFileformats::on_extensionsED_textEdited(const QString & s)
2285 currentFormat().setExtensions(fromqstr(s));
2290 void PrefFileformats::on_viewerED_textEdited(const QString & s)
2292 currentFormat().setViewer(fromqstr(s));
2297 void PrefFileformats::on_editorED_textEdited(const QString & s)
2299 currentFormat().setEditor(fromqstr(s));
2304 void PrefFileformats::on_mimeED_textEdited(const QString & s)
2306 currentFormat().setMime(fromqstr(s));
2311 void PrefFileformats::on_shortcutED_textEdited(const QString & s)
2313 string const new_shortcut = fromqstr(s);
2314 if (new_shortcut == l10n_shortcut(currentFormat().prettyname(),
2315 currentFormat().shortcut()))
2317 currentFormat().setShortcut(new_shortcut);
2322 void PrefFileformats::on_formatED_editingFinished()
2324 string const newname = fromqstr(formatED->displayText());
2325 string const oldname = currentFormat().name();
2326 if (newname == oldname)
2328 if (form_->converters().formatIsUsed(oldname)) {
2329 Alert::error(_("Format in use"),
2330 _("You cannot change a format's short name "
2331 "if the format is used by a converter. "
2332 "Please remove the converter first."));
2337 currentFormat().setName(newname);
2342 void PrefFileformats::on_formatED_textChanged(const QString &)
2344 QString t = formatED->text();
2346 bool valid = formatED->validator()->validate(t, p) == QValidator::Acceptable;
2347 setValid(formatLA, valid);
2351 void PrefFileformats::on_formatsCB_editTextChanged(const QString &)
2353 QString t = formatsCB->currentText();
2355 bool valid = formatsCB->validator()->validate(t, p) == QValidator::Acceptable;
2356 setValid(formatsLA, valid);
2360 void PrefFileformats::updatePrettyname()
2362 QString const newname = formatsCB->currentText();
2363 if (newname == toqstr(translateIfPossible(currentFormat().prettyname())))
2366 currentFormat().setPrettyname(qstring_to_ucs4(newname));
2374 void updateComboBox(LyXRC::Alternatives const & alts,
2375 string const & fmt, QComboBox * combo)
2377 LyXRC::Alternatives::const_iterator it =
2379 if (it != alts.end()) {
2380 LyXRC::CommandSet const & cmds = it->second;
2381 LyXRC::CommandSet::const_iterator sit =
2383 LyXRC::CommandSet::const_iterator const sen =
2385 for (; sit != sen; ++sit) {
2386 QString const qcmd = toqstr(*sit);
2387 combo->addItem(qcmd, qcmd);
2394 void PrefFileformats::updateViewers()
2396 Format const f = currentFormat();
2397 viewerCO->blockSignals(true);
2399 viewerCO->addItem(qt_("None"), QString());
2400 updateComboBox(viewer_alternatives, f.name(), viewerCO);
2401 viewerCO->addItem(qt_("Custom"), QString("custom viewer"));
2402 viewerCO->blockSignals(false);
2404 int pos = viewerCO->findData(toqstr(f.viewer()));
2407 viewerED->setEnabled(false);
2408 viewerCO->setCurrentIndex(pos);
2410 viewerED->setEnabled(true);
2411 viewerED->setText(toqstr(f.viewer()));
2412 viewerCO->setCurrentIndex(viewerCO->findData(toqstr("custom viewer")));
2417 void PrefFileformats::updateEditors()
2419 Format const f = currentFormat();
2420 editorCO->blockSignals(true);
2422 editorCO->addItem(qt_("None"), QString());
2423 updateComboBox(editor_alternatives, f.name(), editorCO);
2424 editorCO->addItem(qt_("Custom"), QString("custom editor"));
2425 editorCO->blockSignals(false);
2427 int pos = editorCO->findData(toqstr(f.editor()));
2430 editorED->setEnabled(false);
2431 editorCO->setCurrentIndex(pos);
2433 editorED->setEnabled(true);
2434 editorED->setText(toqstr(f.editor()));
2435 editorCO->setCurrentIndex(editorCO->findData(toqstr("custom editor")));
2440 void PrefFileformats::on_viewerCO_currentIndexChanged(int i)
2442 bool const custom = viewerCO->itemData(i).toString() == "custom viewer";
2443 viewerED->setEnabled(custom);
2445 currentFormat().setViewer(fromqstr(viewerCO->itemData(i).toString()));
2449 void PrefFileformats::on_editorCO_currentIndexChanged(int i)
2451 bool const custom = editorCO->itemData(i).toString() == "custom editor";
2452 editorED->setEnabled(custom);
2454 currentFormat().setEditor(fromqstr(editorCO->itemData(i).toString()));
2458 Format & PrefFileformats::currentFormat()
2460 int const i = formatsCB->currentIndex();
2461 int const nr = formatsCB->itemData(i).toInt();
2462 return form_->formats().get(nr);
2466 void PrefFileformats::on_formatNewPB_clicked()
2468 form_->formats().add("", "", docstring(), "", "", "", "", Format::none);
2470 formatsCB->setCurrentIndex(0);
2471 formatsCB->setFocus(Qt::OtherFocusReason);
2475 void PrefFileformats::on_formatRemovePB_clicked()
2477 int const i = formatsCB->currentIndex();
2478 int const nr = formatsCB->itemData(i).toInt();
2479 string const current_text = form_->formats().get(nr).name();
2480 if (form_->converters().formatIsUsed(current_text)) {
2481 Alert::error(_("Format in use"),
2482 _("Cannot remove a Format used by a Converter. "
2483 "Remove the converter first."));
2487 form_->formats().erase(current_text);
2490 on_formatsCB_editTextChanged(formatsCB->currentText());
2495 /////////////////////////////////////////////////////////////////////
2499 /////////////////////////////////////////////////////////////////////
2501 PrefLanguage::PrefLanguage(GuiPreferences * form)
2502 : PrefModule(catLanguage, N_("Language"), form)
2506 connect(visualCursorRB, SIGNAL(clicked()),
2507 this, SIGNAL(changed()));
2508 connect(logicalCursorRB, SIGNAL(clicked()),
2509 this, SIGNAL(changed()));
2510 connect(markForeignCB, SIGNAL(clicked()),
2511 this, SIGNAL(changed()));
2512 connect(autoBeginCB, SIGNAL(clicked()),
2513 this, SIGNAL(changed()));
2514 connect(autoEndCB, SIGNAL(clicked()),
2515 this, SIGNAL(changed()));
2516 connect(languagePackageCO, SIGNAL(activated(int)),
2517 this, SIGNAL(changed()));
2518 connect(languagePackageED, SIGNAL(textChanged(QString)),
2519 this, SIGNAL(changed()));
2520 connect(globalCB, SIGNAL(clicked()),
2521 this, SIGNAL(changed()));
2522 connect(startCommandED, SIGNAL(textChanged(QString)),
2523 this, SIGNAL(changed()));
2524 connect(endCommandED, SIGNAL(textChanged(QString)),
2525 this, SIGNAL(changed()));
2526 connect(uiLanguageCO, SIGNAL(activated(int)),
2527 this, SIGNAL(changed()));
2528 connect(defaultDecimalPointLE, SIGNAL(textChanged(QString)),
2529 this, SIGNAL(changed()));
2530 connect(defaultLengthUnitCO, SIGNAL(activated(int)),
2531 this, SIGNAL(changed()));
2533 languagePackageED->setValidator(new NoNewLineValidator(languagePackageED));
2534 startCommandED->setValidator(new NoNewLineValidator(startCommandED));
2535 endCommandED->setValidator(new NoNewLineValidator(endCommandED));
2537 defaultDecimalPointLE->setInputMask("X; ");
2538 defaultDecimalPointLE->setMaxLength(1);
2540 defaultLengthUnitCO->addItem(lyx::qt_(unit_name_gui[Length::CM]), Length::CM);
2541 defaultLengthUnitCO->addItem(lyx::qt_(unit_name_gui[Length::IN]), Length::IN);
2543 QAbstractItemModel * language_model = guiApp->languageModel();
2544 language_model->sort(0);
2545 uiLanguageCO->blockSignals(true);
2546 uiLanguageCO->clear();
2547 uiLanguageCO->addItem(qt_("Default"), toqstr("auto"));
2548 for (int i = 0; i != language_model->rowCount(); ++i) {
2549 QModelIndex index = language_model->index(i, 0);
2550 // Filter the list based on the available translation and add
2551 // each language code only once
2552 string const name = fromqstr(index.data(Qt::UserRole).toString());
2553 Language const * lang = languages.getLanguage(name);
2556 // never remove the currently selected language
2557 if (name != form->rc().gui_language
2558 && name != lyxrc.gui_language
2559 && (!Messages::available(lang->code())
2560 || !lang->hasGuiSupport()))
2562 uiLanguageCO->addItem(index.data(Qt::DisplayRole).toString(),
2563 index.data(Qt::UserRole).toString());
2565 uiLanguageCO->blockSignals(false);
2569 void PrefLanguage::on_uiLanguageCO_currentIndexChanged(int)
2571 QMessageBox::information(this, qt_("LyX needs to be restarted!"),
2572 qt_("The change of user interface language will be fully "
2573 "effective only after a restart."));
2577 void PrefLanguage::on_languagePackageCO_currentIndexChanged(int i)
2579 languagePackageED->setEnabled(i == 2);
2583 void PrefLanguage::applyRC(LyXRC & rc) const
2585 rc.visual_cursor = visualCursorRB->isChecked();
2586 rc.mark_foreign_language = markForeignCB->isChecked();
2587 rc.language_auto_begin = autoBeginCB->isChecked();
2588 rc.language_auto_end = autoEndCB->isChecked();
2589 int const p = languagePackageCO->currentIndex();
2591 rc.language_package_selection = LyXRC::LP_AUTO;
2593 rc.language_package_selection = LyXRC::LP_BABEL;
2595 rc.language_package_selection = LyXRC::LP_CUSTOM;
2597 rc.language_package_selection = LyXRC::LP_NONE;
2598 rc.language_custom_package = fromqstr(languagePackageED->text());
2599 rc.language_global_options = globalCB->isChecked();
2600 rc.language_command_begin = fromqstr(startCommandED->text());
2601 rc.language_command_end = fromqstr(endCommandED->text());
2602 rc.gui_language = fromqstr(
2603 uiLanguageCO->itemData(uiLanguageCO->currentIndex()).toString());
2604 rc.default_decimal_point = fromqstr(defaultDecimalPointLE->text());
2605 rc.default_length_unit = (Length::UNIT) defaultLengthUnitCO->itemData(defaultLengthUnitCO->currentIndex()).toInt();
2609 void PrefLanguage::updateRC(LyXRC const & rc)
2611 if (rc.visual_cursor)
2612 visualCursorRB->setChecked(true);
2614 logicalCursorRB->setChecked(true);
2615 markForeignCB->setChecked(rc.mark_foreign_language);
2616 autoBeginCB->setChecked(rc.language_auto_begin);
2617 autoEndCB->setChecked(rc.language_auto_end);
2618 languagePackageCO->setCurrentIndex(rc.language_package_selection);
2619 languagePackageED->setText(toqstr(rc.language_custom_package));
2620 languagePackageED->setEnabled(languagePackageCO->currentIndex() == 2);
2621 globalCB->setChecked(rc.language_global_options);
2622 startCommandED->setText(toqstr(rc.language_command_begin));
2623 endCommandED->setText(toqstr(rc.language_command_end));
2624 defaultDecimalPointLE->setText(toqstr(rc.default_decimal_point));
2625 int pos = defaultLengthUnitCO->findData(int(rc.default_length_unit));
2626 defaultLengthUnitCO->setCurrentIndex(pos);
2628 pos = uiLanguageCO->findData(toqstr(rc.gui_language));
2629 uiLanguageCO->blockSignals(true);
2630 uiLanguageCO->setCurrentIndex(pos);
2631 uiLanguageCO->blockSignals(false);
2635 /////////////////////////////////////////////////////////////////////
2637 // PrefUserInterface
2639 /////////////////////////////////////////////////////////////////////
2641 PrefUserInterface::PrefUserInterface(GuiPreferences * form)
2642 : PrefModule(catLookAndFeel, N_("User Interface"), form)
2646 connect(uiFilePB, SIGNAL(clicked()),
2647 this, SLOT(selectUi()));
2648 connect(uiFileED, SIGNAL(textChanged(QString)),
2649 this, SIGNAL(changed()));
2650 connect(iconSetCO, SIGNAL(activated(int)),
2651 this, SIGNAL(changed()));
2652 connect(useSystemThemeIconsCB, SIGNAL(clicked()),
2653 this, SIGNAL(changed()));
2654 connect(lastfilesSB, SIGNAL(valueChanged(int)),
2655 this, SIGNAL(changed()));
2656 connect(tooltipCB, SIGNAL(toggled(bool)),
2657 this, SIGNAL(changed()));
2658 lastfilesSB->setMaximum(maxlastfiles);
2660 iconSetCO->addItem(qt_("Default"), QString());
2661 iconSetCO->addItem(qt_("Classic"), "classic");
2662 iconSetCO->addItem(qt_("Oxygen"), "oxygen");
2664 #if (!(defined Q_WS_X11 || defined(QPA_XCB)) || QT_VERSION < 0x040600)
2665 useSystemThemeIconsCB->hide();
2670 void PrefUserInterface::applyRC(LyXRC & rc) const
2672 rc.icon_set = fromqstr(iconSetCO->itemData(
2673 iconSetCO->currentIndex()).toString());
2675 rc.ui_file = internal_path(fromqstr(uiFileED->text()));
2676 rc.use_system_theme_icons = useSystemThemeIconsCB->isChecked();
2677 rc.num_lastfiles = lastfilesSB->value();
2678 rc.use_tooltip = tooltipCB->isChecked();
2682 void PrefUserInterface::updateRC(LyXRC const & rc)
2684 int iconset = iconSetCO->findData(toqstr(rc.icon_set));
2687 iconSetCO->setCurrentIndex(iconset);
2688 useSystemThemeIconsCB->setChecked(rc.use_system_theme_icons);
2689 uiFileED->setText(toqstr(external_path(rc.ui_file)));
2690 lastfilesSB->setValue(rc.num_lastfiles);
2691 tooltipCB->setChecked(rc.use_tooltip);
2695 void PrefUserInterface::selectUi()
2697 QString file = form_->browseUI(internalPath(uiFileED->text()));
2698 if (!file.isEmpty())
2699 uiFileED->setText(file);
2703 /////////////////////////////////////////////////////////////////////
2705 // PrefDocumentHandling
2707 /////////////////////////////////////////////////////////////////////
2709 PrefDocHandling::PrefDocHandling(GuiPreferences * form)
2710 : PrefModule(catLookAndFeel, N_("Document Handling"), form)
2714 connect(autoSaveCB, SIGNAL(toggled(bool)),
2715 autoSaveSB, SLOT(setEnabled(bool)));
2716 connect(autoSaveCB, SIGNAL(toggled(bool)),
2717 TextLabel1, SLOT(setEnabled(bool)));
2718 connect(openDocumentsInTabsCB, SIGNAL(clicked()),
2719 this, SIGNAL(changed()));
2720 connect(singleInstanceCB, SIGNAL(clicked()),
2721 this, SIGNAL(changed()));
2722 connect(singleCloseTabButtonCB, SIGNAL(clicked()),
2723 this, SIGNAL(changed()));
2724 connect(closeLastViewCO, SIGNAL(activated(int)),
2725 this, SIGNAL(changed()));
2726 connect(restoreCursorCB, SIGNAL(clicked()),
2727 this, SIGNAL(changed()));
2728 connect(loadSessionCB, SIGNAL(clicked()),
2729 this, SIGNAL(changed()));
2730 connect(allowGeometrySessionCB, SIGNAL(clicked()),
2731 this, SIGNAL(changed()));
2732 connect(autoSaveSB, SIGNAL(valueChanged(int)),
2733 this, SIGNAL(changed()));
2734 connect(autoSaveCB, SIGNAL(clicked()),
2735 this, SIGNAL(changed()));
2736 connect(backupCB, SIGNAL(clicked()),
2737 this, SIGNAL(changed()));
2738 connect(saveCompressedCB, SIGNAL(clicked()),
2739 this, SIGNAL(changed()));
2740 connect(saveOriginCB, SIGNAL(clicked()),
2741 this, SIGNAL(changed()));
2745 void PrefDocHandling::applyRC(LyXRC & rc) const
2747 rc.use_lastfilepos = restoreCursorCB->isChecked();
2748 rc.load_session = loadSessionCB->isChecked();
2749 rc.allow_geometry_session = allowGeometrySessionCB->isChecked();
2750 rc.autosave = autoSaveCB->isChecked() ? autoSaveSB->value() * 60 : 0;
2751 rc.make_backup = backupCB->isChecked();
2752 rc.save_compressed = saveCompressedCB->isChecked();
2753 rc.save_origin = saveOriginCB->isChecked();
2754 rc.open_buffers_in_tabs = openDocumentsInTabsCB->isChecked();
2755 rc.single_instance = singleInstanceCB->isChecked();
2756 rc.single_close_tab_button = singleCloseTabButtonCB->isChecked();
2758 switch (closeLastViewCO->currentIndex()) {
2760 rc.close_buffer_with_last_view = "yes";
2763 rc.close_buffer_with_last_view = "no";
2766 rc.close_buffer_with_last_view = "ask";
2774 void PrefDocHandling::updateRC(LyXRC const & rc)
2776 restoreCursorCB->setChecked(rc.use_lastfilepos);
2777 loadSessionCB->setChecked(rc.load_session);
2778 allowGeometrySessionCB->setChecked(rc.allow_geometry_session);
2779 // convert to minutes
2780 bool autosave = rc.autosave > 0;
2781 int mins = rc.autosave / 60;
2784 autoSaveSB->setValue(mins);
2785 autoSaveCB->setChecked(autosave);
2786 autoSaveSB->setEnabled(autosave);
2787 backupCB->setChecked(rc.make_backup);
2788 saveCompressedCB->setChecked(rc.save_compressed);
2789 saveOriginCB->setChecked(rc.save_origin);
2790 openDocumentsInTabsCB->setChecked(rc.open_buffers_in_tabs);
2791 singleInstanceCB->setChecked(rc.single_instance && !rc.lyxpipes.empty());
2792 singleInstanceCB->setEnabled(!rc.lyxpipes.empty());
2793 singleCloseTabButtonCB->setChecked(rc.single_close_tab_button);
2794 if (rc.close_buffer_with_last_view == "yes")
2795 closeLastViewCO->setCurrentIndex(0);
2796 else if (rc.close_buffer_with_last_view == "no")
2797 closeLastViewCO->setCurrentIndex(1);
2798 else if (rc.close_buffer_with_last_view == "ask")
2799 closeLastViewCO->setCurrentIndex(2);
2803 void PrefDocHandling::on_clearSessionPB_clicked()
2805 guiApp->clearSession();
2810 /////////////////////////////////////////////////////////////////////
2814 /////////////////////////////////////////////////////////////////////
2816 PrefEdit::PrefEdit(GuiPreferences * form)
2817 : PrefModule(catEditing, N_("Control"), form)
2821 connect(cursorFollowsCB, SIGNAL(clicked()),
2822 this, SIGNAL(changed()));
2823 connect(scrollBelowCB, SIGNAL(clicked()),
2824 this, SIGNAL(changed()));
2825 connect(macLikeCursorMovementCB, SIGNAL(clicked()),
2826 this, SIGNAL(changed()));
2827 connect(sortEnvironmentsCB, SIGNAL(clicked()),
2828 this, SIGNAL(changed()));
2829 connect(groupEnvironmentsCB, SIGNAL(clicked()),
2830 this, SIGNAL(changed()));
2831 connect(macroEditStyleCO, SIGNAL(activated(int)),
2832 this, SIGNAL(changed()));
2833 connect(cursorWidthSB, SIGNAL(valueChanged(int)),
2834 this, SIGNAL(changed()));
2835 connect(fullscreenLimitGB, SIGNAL(clicked()),
2836 this, SIGNAL(changed()));
2837 connect(fullscreenWidthSB, SIGNAL(valueChanged(int)),
2838 this, SIGNAL(changed()));
2839 connect(toggleTabbarCB, SIGNAL(toggled(bool)),
2840 this, SIGNAL(changed()));
2841 connect(toggleMenubarCB, SIGNAL(toggled(bool)),
2842 this, SIGNAL(changed()));
2843 connect(toggleScrollbarCB, SIGNAL(toggled(bool)),
2844 this, SIGNAL(changed()));
2845 connect(toggleStatusbarCB, SIGNAL(toggled(bool)),
2846 this, SIGNAL(changed()));
2847 connect(toggleToolbarsCB, SIGNAL(toggled(bool)),
2848 this, SIGNAL(changed()));
2852 void PrefEdit::applyRC(LyXRC & rc) const
2854 rc.cursor_follows_scrollbar = cursorFollowsCB->isChecked();
2855 rc.scroll_below_document = scrollBelowCB->isChecked();
2856 rc.mac_like_cursor_movement = macLikeCursorMovementCB->isChecked();
2857 rc.sort_layouts = sortEnvironmentsCB->isChecked();
2858 rc.group_layouts = groupEnvironmentsCB->isChecked();
2859 switch (macroEditStyleCO->currentIndex()) {
2860 case 0: rc.macro_edit_style = LyXRC::MACRO_EDIT_INLINE_BOX; break;
2861 case 1: rc.macro_edit_style = LyXRC::MACRO_EDIT_INLINE; break;
2862 case 2: rc.macro_edit_style = LyXRC::MACRO_EDIT_LIST; break;
2864 rc.cursor_width = cursorWidthSB->value();
2865 rc.full_screen_toolbars = toggleToolbarsCB->isChecked();
2866 rc.full_screen_scrollbar = toggleScrollbarCB->isChecked();
2867 rc.full_screen_statusbar = toggleStatusbarCB->isChecked();
2868 rc.full_screen_tabbar = toggleTabbarCB->isChecked();
2869 rc.full_screen_menubar = toggleMenubarCB->isChecked();
2870 rc.full_screen_width = fullscreenWidthSB->value();
2871 rc.full_screen_limit = fullscreenLimitGB->isChecked();
2875 void PrefEdit::updateRC(LyXRC const & rc)
2877 cursorFollowsCB->setChecked(rc.cursor_follows_scrollbar);
2878 scrollBelowCB->setChecked(rc.scroll_below_document);
2879 macLikeCursorMovementCB->setChecked(rc.mac_like_cursor_movement);
2880 sortEnvironmentsCB->setChecked(rc.sort_layouts);
2881 groupEnvironmentsCB->setChecked(rc.group_layouts);
2882 macroEditStyleCO->setCurrentIndex(rc.macro_edit_style);
2883 cursorWidthSB->setValue(rc.cursor_width);
2884 toggleScrollbarCB->setChecked(rc.full_screen_scrollbar);
2885 toggleStatusbarCB->setChecked(rc.full_screen_statusbar);
2886 toggleToolbarsCB->setChecked(rc.full_screen_toolbars);
2887 toggleTabbarCB->setChecked(rc.full_screen_tabbar);
2888 toggleMenubarCB->setChecked(rc.full_screen_menubar);
2889 fullscreenWidthSB->setValue(rc.full_screen_width);
2890 fullscreenLimitGB->setChecked(rc.full_screen_limit);
2894 /////////////////////////////////////////////////////////////////////
2898 /////////////////////////////////////////////////////////////////////
2901 GuiShortcutDialog::GuiShortcutDialog(QWidget * parent) : QDialog(parent)
2903 Ui::shortcutUi::setupUi(this);
2904 QDialog::setModal(true);
2905 lfunLE->setValidator(new NoNewLineValidator(lfunLE));
2909 PrefShortcuts::PrefShortcuts(GuiPreferences * form)
2910 : PrefModule(catEditing, N_("Shortcuts"), form),
2911 editItem_(0), mathItem_(0), bufferItem_(0), layoutItem_(0),
2916 shortcutsTW->setColumnCount(2);
2917 shortcutsTW->headerItem()->setText(0, qt_("Function"));
2918 shortcutsTW->headerItem()->setText(1, qt_("Shortcut"));
2919 shortcutsTW->setSortingEnabled(true);
2920 // Multi-selection can be annoying.
2921 // shortcutsTW->setSelectionMode(QAbstractItemView::MultiSelection);
2923 connect(bindFilePB, SIGNAL(clicked()),
2924 this, SLOT(selectBind()));
2925 connect(bindFileED, SIGNAL(textChanged(QString)),
2926 this, SIGNAL(changed()));
2928 shortcut_ = new GuiShortcutDialog(this);
2929 shortcut_bc_.setPolicy(ButtonPolicy::OkCancelPolicy);
2930 shortcut_bc_.setOK(shortcut_->okPB);
2931 shortcut_bc_.setCancel(shortcut_->cancelPB);
2933 connect(shortcut_->okPB, SIGNAL(clicked()),
2934 this, SIGNAL(changed()));
2935 connect(shortcut_->cancelPB, SIGNAL(clicked()),
2936 shortcut_, SLOT(reject()));
2937 connect(shortcut_->clearPB, SIGNAL(clicked()),
2938 this, SLOT(shortcutClearPressed()));
2939 connect(shortcut_->removePB, SIGNAL(clicked()),
2940 this, SLOT(shortcutRemovePressed()));
2941 connect(shortcut_->okPB, SIGNAL(clicked()),
2942 this, SLOT(shortcutOkPressed()));
2943 connect(shortcut_->cancelPB, SIGNAL(clicked()),
2944 this, SLOT(shortcutCancelPressed()));
2948 void PrefShortcuts::applyRC(LyXRC & rc) const
2950 rc.bind_file = internal_path(fromqstr(bindFileED->text()));
2951 // write user_bind and user_unbind to .lyx/bind/user.bind
2952 FileName bind_dir(addPath(package().user_support().absFileName(), "bind"));
2953 if (!bind_dir.exists() && !bind_dir.createDirectory(0777)) {
2954 lyxerr << "LyX could not create the user bind directory '"
2955 << bind_dir << "'. All user-defined key bindings will be lost." << endl;
2958 if (!bind_dir.isDirWritable()) {
2959 lyxerr << "LyX could not write to the user bind directory '"
2960 << bind_dir << "'. All user-defined key bindings will be lost." << endl;
2963 FileName user_bind_file(bind_dir.absFileName() + "/user.bind");
2964 user_unbind_.write(user_bind_file.toFilesystemEncoding(), false, true);
2965 user_bind_.write(user_bind_file.toFilesystemEncoding(), true, false);
2966 // immediately apply the keybindings. Why this is not done before?
2967 // The good thing is that the menus are updated automatically.
2968 theTopLevelKeymap().clear();
2969 theTopLevelKeymap().read("site");
2970 theTopLevelKeymap().read(rc.bind_file, 0, KeyMap::Fallback);
2971 theTopLevelKeymap().read("user", 0, KeyMap::MissingOK);
2975 void PrefShortcuts::updateRC(LyXRC const & rc)
2977 bindFileED->setText(toqstr(external_path(rc.bind_file)));
2979 system_bind_.clear();
2981 user_unbind_.clear();
2982 system_bind_.read("site");
2983 system_bind_.read(rc.bind_file);
2984 // \unbind in user.bind is added to user_unbind_
2985 user_bind_.read("user", &user_unbind_, KeyMap::MissingOK);
2986 updateShortcutsTW();
2990 void PrefShortcuts::updateShortcutsTW()
2992 shortcutsTW->clear();
2994 editItem_ = new QTreeWidgetItem(shortcutsTW);
2995 editItem_->setText(0, qt_("Cursor, Mouse and Editing Functions"));
2996 editItem_->setFlags(editItem_->flags() & ~Qt::ItemIsSelectable);
2998 mathItem_ = new QTreeWidgetItem(shortcutsTW);
2999 mathItem_->setText(0, qt_("Mathematical Symbols"));
3000 mathItem_->setFlags(mathItem_->flags() & ~Qt::ItemIsSelectable);
3002 bufferItem_ = new QTreeWidgetItem(shortcutsTW);
3003 bufferItem_->setText(0, qt_("Document and Window"));
3004 bufferItem_->setFlags(bufferItem_->flags() & ~Qt::ItemIsSelectable);
3006 layoutItem_ = new QTreeWidgetItem(shortcutsTW);
3007 layoutItem_->setText(0, qt_("Font, Layouts and Textclasses"));
3008 layoutItem_->setFlags(layoutItem_->flags() & ~Qt::ItemIsSelectable);
3010 systemItem_ = new QTreeWidgetItem(shortcutsTW);
3011 systemItem_->setText(0, qt_("System and Miscellaneous"));
3012 systemItem_->setFlags(systemItem_->flags() & ~Qt::ItemIsSelectable);
3014 // listBindings(unbound=true) lists all bound and unbound lfuns
3015 // Items in this list is tagged by its source.
3016 KeyMap::BindingList bindinglist = system_bind_.listBindings(true,
3018 KeyMap::BindingList user_bindinglist = user_bind_.listBindings(false,
3020 KeyMap::BindingList user_unbindinglist = user_unbind_.listBindings(false,
3021 KeyMap::UserUnbind);
3022 bindinglist.insert(bindinglist.end(), user_bindinglist.begin(),
3023 user_bindinglist.end());
3024 bindinglist.insert(bindinglist.end(), user_unbindinglist.begin(),
3025 user_unbindinglist.end());
3027 KeyMap::BindingList::const_iterator it = bindinglist.begin();
3028 KeyMap::BindingList::const_iterator it_end = bindinglist.end();
3029 for (; it != it_end; ++it)
3030 insertShortcutItem(it->request, it->sequence, it->tag);
3032 shortcutsTW->sortItems(0, Qt::AscendingOrder);
3033 on_shortcutsTW_itemSelectionChanged();
3034 on_searchLE_textEdited();
3035 shortcutsTW->resizeColumnToContents(0);
3040 KeyMap::ItemType PrefShortcuts::itemType(QTreeWidgetItem & item)
3042 return static_cast<KeyMap::ItemType>(item.data(0, Qt::UserRole).toInt());
3047 bool PrefShortcuts::isAlwaysHidden(QTreeWidgetItem & item)
3049 // Hide rebound system settings that are empty
3050 return itemType(item) == KeyMap::UserUnbind && item.text(1).isEmpty();
3054 void PrefShortcuts::setItemType(QTreeWidgetItem * item, KeyMap::ItemType tag)
3056 item->setData(0, Qt::UserRole, QVariant(tag));
3060 case KeyMap::System:
3062 case KeyMap::UserBind:
3065 case KeyMap::UserUnbind:
3066 font.setStrikeOut(true);
3068 // this item is not displayed now.
3069 case KeyMap::UserExtraUnbind:
3070 font.setStrikeOut(true);
3073 item->setHidden(isAlwaysHidden(*item));
3074 item->setFont(1, font);
3078 QTreeWidgetItem * PrefShortcuts::insertShortcutItem(FuncRequest const & lfun,
3079 KeySequence const & seq, KeyMap::ItemType tag)
3081 FuncCode const action = lfun.action();
3082 string const action_name = lyxaction.getActionName(action);
3083 QString const lfun_name = toqstr(from_utf8(action_name)
3084 + ' ' + lfun.argument());
3085 QString const shortcut = toqstr(seq.print(KeySequence::ForGui));
3087 QTreeWidgetItem * newItem = 0;
3088 // for unbind items, try to find an existing item in the system bind list
3089 if (tag == KeyMap::UserUnbind) {
3090 QList<QTreeWidgetItem*> const items = shortcutsTW->findItems(lfun_name,
3091 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 0);
3092 for (int i = 0; i < items.size(); ++i) {
3093 if (items[i]->text(1) == shortcut) {
3098 // if not found, this unbind item is KeyMap::UserExtraUnbind
3099 // Such an item is not displayed to avoid confusion (what is
3100 // unmatched removed?).
3106 switch(lyxaction.getActionType(action)) {
3107 case LyXAction::Hidden:
3109 case LyXAction::Edit:
3110 newItem = new QTreeWidgetItem(editItem_);
3112 case LyXAction::Math:
3113 newItem = new QTreeWidgetItem(mathItem_);
3115 case LyXAction::Buffer:
3116 newItem = new QTreeWidgetItem(bufferItem_);
3118 case LyXAction::Layout:
3119 newItem = new QTreeWidgetItem(layoutItem_);
3121 case LyXAction::System:
3122 newItem = new QTreeWidgetItem(systemItem_);
3125 // this should not happen
3126 newItem = new QTreeWidgetItem(shortcutsTW);
3130 newItem->setText(0, lfun_name);
3131 newItem->setText(1, shortcut);
3132 // record BindFile representation to recover KeySequence when needed.
3133 newItem->setData(1, Qt::UserRole, toqstr(seq.print(KeySequence::BindFile)));
3134 setItemType(newItem, tag);
3139 void PrefShortcuts::on_shortcutsTW_itemSelectionChanged()
3141 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
3142 removePB->setEnabled(!items.isEmpty() && !items[0]->text(1).isEmpty());
3143 modifyPB->setEnabled(!items.isEmpty());
3144 if (items.isEmpty())
3147 if (itemType(*items[0]) == KeyMap::UserUnbind)
3148 removePB->setText(qt_("Res&tore"));
3150 removePB->setText(qt_("Remo&ve"));
3154 void PrefShortcuts::on_shortcutsTW_itemDoubleClicked()
3160 void PrefShortcuts::modifyShortcut()
3162 QTreeWidgetItem * item = shortcutsTW->currentItem();
3163 if (item->flags() & Qt::ItemIsSelectable) {
3164 shortcut_->lfunLE->setText(item->text(0));
3165 save_lfun_ = item->text(0).trimmed();
3166 shortcut_->shortcutWG->setText(item->text(1));
3168 seq.parse(fromqstr(item->data(1, Qt::UserRole).toString()));
3169 shortcut_->shortcutWG->setKeySequence(seq);
3170 shortcut_->shortcutWG->setFocus();
3176 void PrefShortcuts::unhideEmpty(QString const & lfun, bool select)
3178 // list of items that match lfun
3179 QList<QTreeWidgetItem*> items = shortcutsTW->findItems(lfun,
3180 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 0);
3181 for (int i = 0; i < items.size(); ++i) {
3182 QTreeWidgetItem * item = items[i];
3183 if (isAlwaysHidden(*item)) {
3184 setItemType(item, KeyMap::System);
3186 shortcutsTW->setCurrentItem(item);
3193 void PrefShortcuts::removeShortcut()
3195 // it seems that only one item can be selected, but I am
3196 // removing all selected items anyway.
3197 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
3198 for (int i = 0; i < items.size(); ++i) {
3199 string shortcut = fromqstr(items[i]->data(1, Qt::UserRole).toString());
3200 string lfun = fromqstr(items[i]->text(0));
3201 FuncRequest func = lyxaction.lookupFunc(lfun);
3203 switch (itemType(*items[i])) {
3204 case KeyMap::System: {
3205 // for system bind, we do not touch the item
3206 // but add an user unbind item
3207 user_unbind_.bind(shortcut, func);
3208 setItemType(items[i], KeyMap::UserUnbind);
3209 removePB->setText(qt_("Res&tore"));
3212 case KeyMap::UserBind: {
3213 // for user_bind, we remove this bind
3214 QTreeWidgetItem * parent = items[i]->parent();
3215 int itemIdx = parent->indexOfChild(items[i]);
3216 parent->takeChild(itemIdx);
3218 shortcutsTW->scrollToItem(parent->child(itemIdx - 1));
3220 shortcutsTW->scrollToItem(parent);
3221 user_bind_.unbind(shortcut, func);
3222 // If this user binding hid an empty system binding, unhide the
3223 // latter and select it.
3224 unhideEmpty(items[i]->text(0), true);
3227 case KeyMap::UserUnbind: {
3228 // for user_unbind, we remove the unbind, and the item
3229 // become KeyMap::System again.
3231 seq.parse(shortcut);
3232 // Ask the user to replace current binding
3233 if (!validateNewShortcut(func, seq, QString()))
3235 user_unbind_.unbind(shortcut, func);
3236 setItemType(items[i], KeyMap::System);
3237 removePB->setText(qt_("Remo&ve"));
3240 case KeyMap::UserExtraUnbind: {
3241 // for user unbind that is not in system bind file,
3242 // remove this unbind file
3243 QTreeWidgetItem * parent = items[i]->parent();
3244 parent->takeChild(parent->indexOfChild(items[i]));
3245 user_unbind_.unbind(shortcut, func);
3252 void PrefShortcuts::deactivateShortcuts(QList<QTreeWidgetItem*> const & items)
3254 for (int i = 0; i < items.size(); ++i) {
3255 string shortcut = fromqstr(items[i]->data(1, Qt::UserRole).toString());
3256 string lfun = fromqstr(items[i]->text(0));
3257 FuncRequest func = lyxaction.lookupFunc(lfun);
3259 switch (itemType(*items[i])) {
3260 case KeyMap::System:
3261 // for system bind, we do not touch the item
3262 // but add an user unbind item
3263 user_unbind_.bind(shortcut, func);
3264 setItemType(items[i], KeyMap::UserUnbind);
3267 case KeyMap::UserBind: {
3268 // for user_bind, we remove this bind
3269 QTreeWidgetItem * parent = items[i]->parent();
3270 int itemIdx = parent->indexOfChild(items[i]);
3271 parent->takeChild(itemIdx);
3272 user_bind_.unbind(shortcut, func);
3273 unhideEmpty(items[i]->text(0), false);
3283 void PrefShortcuts::selectBind()
3285 QString file = form_->browsebind(internalPath(bindFileED->text()));
3286 if (!file.isEmpty()) {
3287 bindFileED->setText(file);
3288 system_bind_ = KeyMap();
3289 system_bind_.read(fromqstr(file));
3290 updateShortcutsTW();
3295 void PrefShortcuts::on_modifyPB_pressed()
3301 void PrefShortcuts::on_newPB_pressed()
3303 shortcut_->lfunLE->clear();
3304 shortcut_->shortcutWG->reset();
3305 save_lfun_ = QString();
3310 void PrefShortcuts::on_removePB_pressed()
3317 void PrefShortcuts::on_searchLE_textEdited()
3319 if (searchLE->text().isEmpty()) {
3320 // show all hidden items
3321 QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Hidden);
3323 (*it)->setHidden(isAlwaysHidden(**it));
3324 // close all categories
3325 for (int i = 0; i < shortcutsTW->topLevelItemCount(); ++i)
3326 shortcutsTW->collapseItem(shortcutsTW->topLevelItem(i));
3329 // search both columns
3330 QList<QTreeWidgetItem *> matched = shortcutsTW->findItems(searchLE->text(),
3331 Qt::MatchFlags(Qt::MatchContains | Qt::MatchRecursive), 0);
3332 matched += shortcutsTW->findItems(searchLE->text(),
3333 Qt::MatchFlags(Qt::MatchContains | Qt::MatchRecursive), 1);
3335 // hide everyone (to avoid searching in matched QList repeatedly
3336 QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Selectable);
3338 (*it++)->setHidden(true);
3339 // show matched items
3340 for (int i = 0; i < matched.size(); ++i)
3341 if (!isAlwaysHidden(*matched[i])) {
3342 matched[i]->setHidden(false);
3343 if (matched[i]->parent())
3344 matched[i]->parent()->setExpanded(true);
3349 docstring makeCmdString(FuncRequest const & f)
3351 docstring actionStr = from_ascii(lyxaction.getActionName(f.action()));
3352 if (!f.argument().empty())
3353 actionStr += " " + f.argument();
3358 FuncRequest PrefShortcuts::currentBinding(KeySequence const & k)
3360 FuncRequest res = user_bind_.getBinding(k);
3361 if (res.action() != LFUN_UNKNOWN_ACTION)
3363 res = system_bind_.getBinding(k);
3364 // Check if it is unbound. Note: user_unbind_ can only unbind one
3365 // FuncRequest per key sequence.
3366 if (user_unbind_.getBinding(k) == res)
3367 return FuncRequest::unknown;
3372 bool PrefShortcuts::validateNewShortcut(FuncRequest const & func,
3373 KeySequence const & k,
3374 QString const & lfun_to_modify)
3376 if (func.action() == LFUN_UNKNOWN_ACTION) {
3377 Alert::error(_("Failed to create shortcut"),
3378 _("Unknown or invalid LyX function"));
3382 // It is not currently possible to bind Hidden lfuns such as self-insert. In
3383 // the future, to remove this limitation, see GuiPrefs::insertShortcutItem
3384 // and how it is used in GuiPrefs::shortcutOkPressed.
3385 if (lyxaction.getActionType(func.action()) == LyXAction::Hidden) {
3386 Alert::error(_("Failed to create shortcut"),
3387 _("This LyX function is hidden and cannot be bound."));
3391 if (k.length() == 0) {
3392 Alert::error(_("Failed to create shortcut"),
3393 _("Invalid or empty key sequence"));
3397 FuncRequest oldBinding = currentBinding(k);
3398 if (oldBinding == func)
3399 // nothing to change
3402 // make sure this key isn't already bound---and, if so, prompt user
3403 // (exclude the lfun the user already wants to modify)
3404 docstring const action_string = makeCmdString(oldBinding);
3405 if (oldBinding.action() != LFUN_UNKNOWN_ACTION
3406 && lfun_to_modify != toqstr(action_string)) {
3407 docstring const new_action_string = makeCmdString(func);
3408 docstring const text = bformat(_("Shortcut `%1$s' is already bound to "
3410 "Are you sure you want to unbind the "
3411 "current shortcut and bind it to %3$s?"),
3412 k.print(KeySequence::ForGui), action_string,
3414 int ret = Alert::prompt(_("Redefine shortcut?"),
3415 text, 0, 1, _("&Redefine"), _("&Cancel"));
3418 QString const sequence_text = toqstr(k.print(KeySequence::ForGui));
3419 QList<QTreeWidgetItem*> items = shortcutsTW->findItems(sequence_text,
3420 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 1);
3421 deactivateShortcuts(items);
3427 void PrefShortcuts::shortcutOkPressed()
3429 QString const new_lfun = shortcut_->lfunLE->text();
3430 FuncRequest func = lyxaction.lookupFunc(fromqstr(new_lfun));
3431 KeySequence k = shortcut_->shortcutWG->getKeySequence();
3433 // save_lfun_ contains the text of the lfun to modify, if the user clicked
3434 // "modify", or is empty if they clicked "new" (which I do not really like)
3435 if (!validateNewShortcut(func, k, save_lfun_))
3438 if (!save_lfun_.isEmpty()) {
3439 // real modification of the lfun's shortcut,
3440 // so remove the previous one
3441 QList<QTreeWidgetItem*> to_modify = shortcutsTW->selectedItems();
3442 deactivateShortcuts(to_modify);
3445 shortcut_->accept();
3447 QTreeWidgetItem * item = insertShortcutItem(func, k, KeyMap::UserBind);
3449 user_bind_.bind(&k, func);
3450 shortcutsTW->sortItems(0, Qt::AscendingOrder);
3452 item->parent()->setExpanded(true);
3453 shortcutsTW->setCurrentItem(item);
3454 shortcutsTW->scrollToItem(item);
3456 Alert::error(_("Failed to create shortcut"),
3457 _("Can not insert shortcut to the list"));
3463 void PrefShortcuts::shortcutCancelPressed()
3465 shortcut_->shortcutWG->reset();
3469 void PrefShortcuts::shortcutClearPressed()
3471 shortcut_->shortcutWG->reset();
3475 void PrefShortcuts::shortcutRemovePressed()
3477 shortcut_->shortcutWG->removeFromSequence();
3481 /////////////////////////////////////////////////////////////////////
3485 /////////////////////////////////////////////////////////////////////
3487 PrefIdentity::PrefIdentity(GuiPreferences * form)
3488 : PrefModule(QString(), N_("Identity"), form)
3492 connect(nameED, SIGNAL(textChanged(QString)),
3493 this, SIGNAL(changed()));
3494 connect(emailED, SIGNAL(textChanged(QString)),
3495 this, SIGNAL(changed()));
3497 nameED->setValidator(new NoNewLineValidator(nameED));
3498 emailED->setValidator(new NoNewLineValidator(emailED));
3502 void PrefIdentity::applyRC(LyXRC & rc) const
3504 rc.user_name = fromqstr(nameED->text());
3505 rc.user_email = fromqstr(emailED->text());
3509 void PrefIdentity::updateRC(LyXRC const & rc)
3511 nameED->setText(toqstr(rc.user_name));
3512 emailED->setText(toqstr(rc.user_email));
3517 /////////////////////////////////////////////////////////////////////
3521 /////////////////////////////////////////////////////////////////////
3523 GuiPreferences::GuiPreferences(GuiView & lv)
3524 : GuiDialog(lv, "prefs", qt_("Preferences"))
3528 QDialog::setModal(false);
3530 connect(okPB, SIGNAL(clicked()), this, SLOT(slotOK()));
3531 connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
3532 connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
3533 connect(restorePB, SIGNAL(clicked()), this, SLOT(slotRestore()));
3535 addModule(new PrefUserInterface(this));
3536 addModule(new PrefDocHandling(this));
3537 addModule(new PrefEdit(this));
3538 addModule(new PrefShortcuts(this));
3539 PrefScreenFonts * screenfonts = new PrefScreenFonts(this);
3540 connect(this, SIGNAL(prefsApplied(LyXRC const &)),
3541 screenfonts, SLOT(updateScreenFontSizes(LyXRC const &)));
3542 addModule(screenfonts);
3543 addModule(new PrefColors(this));
3544 addModule(new PrefDisplay(this));
3545 addModule(new PrefInput(this));
3546 addModule(new PrefCompletion(this));
3548 addModule(new PrefPaths(this));
3550 addModule(new PrefIdentity(this));
3552 addModule(new PrefLanguage(this));
3553 addModule(new PrefSpellchecker(this));
3555 //for strftime validator
3556 PrefOutput * output = new PrefOutput(this);
3558 addModule(new PrefLatex(this));
3560 PrefConverters * converters = new PrefConverters(this);
3561 PrefFileformats * formats = new PrefFileformats(this);
3562 connect(formats, SIGNAL(formatsChanged()),
3563 converters, SLOT(updateGui()));
3564 addModule(converters);
3567 prefsPS->setCurrentPanel("User Interface");
3568 // FIXME: hack to work around resizing bug in Qt >= 4.2
3569 // bug verified with Qt 4.2.{0-3} (JSpitzm)
3570 #if QT_VERSION >= 0x040200
3571 prefsPS->updateGeometry();
3574 bc().setPolicy(ButtonPolicy::PreferencesPolicy);
3576 bc().setApply(applyPB);
3577 bc().setCancel(closePB);
3578 bc().setRestore(restorePB);
3580 // initialize the strftime validator
3581 bc().addCheckedLineEdit(output->DateED);
3585 void GuiPreferences::addModule(PrefModule * module)
3587 LASSERT(module, return);
3588 if (module->category().isEmpty())
3589 prefsPS->addPanel(module, module->title());
3591 prefsPS->addPanel(module, module->title(), module->category());
3592 connect(module, SIGNAL(changed()), this, SLOT(change_adaptor()));
3593 modules_.push_back(module);
3597 void GuiPreferences::change_adaptor()
3603 void GuiPreferences::applyRC(LyXRC & rc) const
3605 size_t end = modules_.size();
3606 for (size_t i = 0; i != end; ++i)
3607 modules_[i]->applyRC(rc);
3611 void GuiPreferences::updateRC(LyXRC const & rc)
3613 size_t const end = modules_.size();
3614 for (size_t i = 0; i != end; ++i)
3615 modules_[i]->updateRC(rc);
3619 void GuiPreferences::applyView()
3625 bool GuiPreferences::initialiseParams(string const &)
3628 formats_ = theFormats();
3629 converters_ = theConverters();
3630 converters_.update(formats_);
3631 movers_ = theMovers();
3635 // Make sure that the bc is in the INITIAL state
3636 if (bc().policy().buttonStatus(ButtonPolicy::RESTORE))
3643 void GuiPreferences::dispatchParams()
3646 rc_.write(ss, true);
3647 dispatch(FuncRequest(LFUN_LYXRC_APPLY, ss.str()));
3648 // issue prefsApplied signal. This will update the
3649 // localized screen font sizes.
3651 // FIXME: these need lfuns
3653 Author const & author =
3654 Author(from_utf8(rc_.user_name), from_utf8(rc_.user_email));
3655 theBufferList().recordCurrentAuthor(author);
3657 theFormats() = formats_;
3659 theConverters() = converters_;
3660 theConverters().update(formats_);
3661 theConverters().buildGraph();
3662 theBufferList().invalidateConverterCache();
3664 theMovers() = movers_;
3666 for (string const & color : colors_)
3667 dispatch(FuncRequest(LFUN_SET_COLOR, color));
3671 if (!tempSaveCB->isChecked())
3672 dispatch(FuncRequest(LFUN_PREFERENCES_SAVE));
3676 void GuiPreferences::setColor(ColorCode col, QString const & hex)
3678 colors_.push_back(lcolor.getLyXName(col) + ' ' + fromqstr(hex));
3682 QString GuiPreferences::browsebind(QString const & file) const
3684 return browseLibFile("bind", file, "bind", qt_("Choose bind file"),
3685 QStringList(qt_("LyX bind files (*.bind)")));
3689 QString GuiPreferences::browseUI(QString const & file) const
3691 return browseLibFile("ui", file, "ui", qt_("Choose UI file"),
3692 QStringList(qt_("LyX UI files (*.ui)")));
3696 QString GuiPreferences::browsekbmap(QString const & file) const
3698 return browseLibFile("kbd", file, "kmap", qt_("Choose keyboard map"),
3699 QStringList(qt_("LyX keyboard maps (*.kmap)")));
3703 QString GuiPreferences::browse(QString const & file,
3704 QString const & title) const
3706 return browseFile(file, title, QStringList(), true);
3710 Dialog * createGuiPreferences(GuiView & lv) { return new GuiPreferences(lv); }
3713 } // namespace frontend
3716 #include "moc_GuiPrefs.cpp"