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 "GuiLyXFiles.h"
24 #include "qt_helpers.h"
25 #include "Validator.h"
28 #include "BufferList.h"
31 #include "ConverterCache.h"
32 #include "FontEnums.h"
33 #include "FuncRequest.h"
34 #include "KeySequence.h"
36 #include "LyXAction.h"
38 #include "PanelStack.h"
40 #include "SpellChecker.h"
42 #include "support/debug.h"
43 #include "support/FileName.h"
44 #include "support/filetools.h"
45 #include "support/gettext.h"
46 #include "support/lassert.h"
47 #include "support/lstrings.h"
48 #include "support/Messages.h"
49 #include "support/os.h"
50 #include "support/Package.h"
52 #include "frontends/alert.h"
53 #include "frontends/Application.h"
54 #include "frontends/FontLoader.h"
56 #include <QAbstractItemModel>
58 #include <QColorDialog>
59 #include <QFontDatabase>
60 #include <QHeaderView>
62 #include <QMessageBox>
63 #include <QPushButton>
66 #include <QTreeWidget>
67 #include <QTreeWidgetItem>
78 using namespace lyx::support;
79 using namespace lyx::support::os;
84 /////////////////////////////////////////////////////////////////////
88 /////////////////////////////////////////////////////////////////////
90 /** Launch a file dialog and return the chosen file.
91 filename: a suggested filename.
92 title: the title of the dialog.
94 dir1 = (name, dir), dir2 = (name, dir): extra buttons on the dialog.
96 QString browseFile(QString const & filename,
97 QString const & title,
98 QStringList const & filters,
100 QString const & label1 = QString(),
101 QString const & dir1 = QString(),
102 QString const & label2 = QString(),
103 QString const & dir2 = QString(),
104 QString const & fallback_dir = QString())
106 QString lastPath = ".";
107 if (!filename.isEmpty())
108 lastPath = onlyPath(filename);
109 else if(!fallback_dir.isEmpty())
110 lastPath = fallback_dir;
112 FileDialog dlg(title);
113 dlg.setButton1(label1, dir1);
114 dlg.setButton2(label2, dir2);
116 FileDialog::Result result;
119 result = dlg.save(lastPath, filters, onlyFileName(filename));
121 result = dlg.open(lastPath, filters, onlyFileName(filename));
123 return result.second;
127 /** Launch a file dialog and return the chosen directory.
128 pathname: a suggested pathname.
129 title: the title of the dialog.
130 dir1 = (name, dir), dir2 = (name, dir): extra buttons on the dialog.
132 QString browseDir(QString const & pathname,
133 QString const & title,
134 QString const & label1 = QString(),
135 QString const & dir1 = QString(),
136 QString const & label2 = QString(),
137 QString const & dir2 = QString())
139 QString lastPath = ".";
140 if (!pathname.isEmpty())
141 lastPath = onlyPath(pathname);
143 FileDialog dlg(title);
144 dlg.setButton1(label1, dir1);
145 dlg.setButton2(label2, dir2);
147 FileDialog::Result const result =
148 dlg.opendir(lastPath, onlyFileName(pathname));
150 return result.second;
154 } // namespace frontend
157 QString browseRelToParent(QString const & filename, QString const & relpath,
158 QString const & title, QStringList const & filters, bool save,
159 QString const & label1, QString const & dir1,
160 QString const & label2, QString const & dir2)
162 QString const fname = makeAbsPath(filename, relpath);
164 QString const outname =
165 frontend::browseFile(fname, title, filters, save, label1, dir1, label2, dir2);
167 QString const reloutname =
168 toqstr(makeRelPath(qstring_to_ucs4(outname), qstring_to_ucs4(relpath)));
170 if (reloutname.startsWith("../"))
177 QString browseRelToSub(QString const & filename, QString const & relpath,
178 QString const & title, QStringList const & filters, bool save,
179 QString const & label1, QString const & dir1,
180 QString const & label2, QString const & dir2)
182 QString const fname = makeAbsPath(filename, relpath);
184 QString const outname =
185 frontend::browseFile(fname, title, filters, save, label1, dir1, label2, dir2);
187 QString const reloutname =
188 toqstr(makeRelPath(qstring_to_ucs4(outname), qstring_to_ucs4(relpath)));
190 QString testname = reloutname;
191 #if QT_VERSION < 0x060000
192 testname.remove(QRegExp("^(\\.\\./)+"));
194 testname.remove(QRegularExpression("^(\\.\\./)+"));
197 if (testname.contains("/"))
205 /////////////////////////////////////////////////////////////////////
209 /////////////////////////////////////////////////////////////////////
213 QString const catLookAndFeel = N_("Look & Feel");
214 QString const catEditing = N_("Editing");
215 QString const catLanguage = N_("Language Settings");
216 QString const catOutput = N_("Output");
217 QString const catFiles = N_("File Handling");
219 static void parseFontName(QString const & mangled0,
220 string & name, string & foundry)
222 string mangled = fromqstr(mangled0);
223 size_t const idx = mangled.find('[');
224 if (idx == string::npos || idx == 0) {
228 name = mangled.substr(0, idx - 1);
229 foundry = mangled.substr(idx + 1, mangled.size() - idx - 2);
234 static void setComboxFont(QComboBox * cb, string const & family,
235 string const & foundry)
237 QString fontname = toqstr(family);
238 if (!foundry.empty())
239 fontname += " [" + toqstr(foundry) + ']';
241 for (int i = 0; i != cb->count(); ++i) {
242 if (cb->itemText(i) == fontname) {
243 cb->setCurrentIndex(i);
248 // Try matching without foundry name
250 // We count in reverse in order to prefer the Xft foundry
251 for (int i = cb->count(); --i >= 0;) {
252 string name, fnt_foundry;
253 parseFontName(cb->itemText(i), name, fnt_foundry);
254 if (compare_ascii_no_case(name, family) == 0) {
255 cb->setCurrentIndex(i);
260 // family alone can contain e.g. "Helvetica [Adobe]"
261 string tmpname, tmpfoundry;
262 parseFontName(toqstr(family), tmpname, tmpfoundry);
264 // We count in reverse in order to prefer the Xft foundry
265 for (int i = cb->count(); --i >= 0; ) {
266 string name, fnt_foundry;
267 parseFontName(cb->itemText(i), name, fnt_foundry);
268 if (compare_ascii_no_case(name, fnt_foundry) == 0) {
269 cb->setCurrentIndex(i);
274 // Bleh, default fonts, and the names couldn't be found. Hack
279 QString const font_family = toqstr(family);
280 if (font_family == guiApp->romanFontName()) {
281 font.setStyleHint(QFont::Serif);
282 font.setFamily(font_family);
283 } else if (font_family == guiApp->sansFontName()) {
284 font.setStyleHint(QFont::SansSerif);
285 font.setFamily(font_family);
286 } else if (font_family == guiApp->typewriterFontName()) {
287 font.setStyleHint(QFont::TypeWriter);
288 font.setFamily(font_family);
290 LYXERR0("FAILED to find the default font: '"
291 << foundry << "', '" << family << '\'');
295 QFontInfo info(font);
296 string default_font_name, dummyfoundry;
297 parseFontName(info.family(), default_font_name, dummyfoundry);
298 LYXERR0("Apparent font is " << default_font_name);
300 for (int i = 0; i < cb->count(); ++i) {
301 LYXERR0("Looking at " << cb->itemText(i));
302 if (compare_ascii_no_case(fromqstr(cb->itemText(i)),
303 default_font_name) == 0) {
304 cb->setCurrentIndex(i);
309 LYXERR0("FAILED to find the font: '"
310 << foundry << "', '" << family << '\'');
314 /////////////////////////////////////////////////////////////////////
318 /////////////////////////////////////////////////////////////////////
320 PrefOutput::PrefOutput(GuiPreferences * form)
321 : PrefModule(catOutput, N_("General[[settings]]"), form)
325 dviCB->setValidator(new NoNewLineValidator(dviCB));
326 pdfCB->setValidator(new NoNewLineValidator(pdfCB));
328 connect(plaintextLinelengthSB, SIGNAL(valueChanged(int)),
329 this, SIGNAL(changed()));
330 connect(overwriteCO, SIGNAL(activated(int)),
331 this, SIGNAL(changed()));
332 connect(dviCB, SIGNAL(editTextChanged(QString)),
333 this, SIGNAL(changed()));
334 connect(pdfCB, SIGNAL(editTextChanged(QString)),
335 this, SIGNAL(changed()));
336 connect(printerPaperTypeED, SIGNAL(textChanged(QString)),
337 this, SIGNAL(changed()));
338 connect(printerLandscapeED, SIGNAL(textChanged(QString)),
339 this, SIGNAL(changed()));
340 connect(printerPaperSizeED, SIGNAL(textChanged(QString)),
341 this, SIGNAL(changed()));
343 printerPaperTypeED->setValidator(new NoNewLineValidator(printerPaperTypeED));
344 printerLandscapeED->setValidator(new NoNewLineValidator(printerLandscapeED));
345 printerPaperSizeED->setValidator(new NoNewLineValidator(printerPaperSizeED));
348 dviCB->addItem("xdvi -sourceposition '$$n:\\ $$t' $$o");
349 dviCB->addItem("yap -1 -s \"$$n $$t\" $$o");
350 dviCB->addItem("okular --unique \"$$o#src:$$n $$f\"");
351 dviCB->addItem("synctex view -i $$n:0:$$t -o $$o -x \"evince -i %{page+1} $$o\"");
353 pdfCB->addItem("CMCDDE SUMATRA control [ForwardSearch(\\\"$$o\\\",\\\"$$t\\\",$$n,0,0,1)]");
354 pdfCB->addItem("SumatraPDF -reuse-instance \"$$o\" -forward-search \"$$t\" $$n");
355 pdfCB->addItem("synctex view -i $$n:0:$$t -o $$o -x \"xpdf -raise -remote $$t.tmp $$o %{page+1}\"");
356 pdfCB->addItem("okular --unique \"$$o#src:$$n $$f\"");
357 pdfCB->addItem("qpdfview --unique \"$$o#src:$$f:$$n:0\"");
358 pdfCB->addItem("synctex view -i $$n:0:$$t -o $$o -x \"evince -i %{page+1} $$o\"");
359 pdfCB->addItem("/Applications/Skim.app/Contents/SharedSupport/displayline $$n $$o $$t");
363 void PrefOutput::applyRC(LyXRC & rc) const
365 rc.plaintext_linelen = plaintextLinelengthSB->value();
366 rc.forward_search_dvi = fromqstr(dviCB->currentText());
367 rc.forward_search_pdf = fromqstr(pdfCB->currentText());
369 switch (overwriteCO->currentIndex()) {
371 rc.export_overwrite = NO_FILES;
374 rc.export_overwrite = MAIN_FILE;
377 rc.export_overwrite = ALL_FILES;
381 rc.print_paper_flag = fromqstr(printerPaperTypeED->text());
382 rc.print_landscape_flag = fromqstr(printerLandscapeED->text());
383 rc.print_paper_dimension_flag = fromqstr(printerPaperSizeED->text());
387 void PrefOutput::updateRC(LyXRC const & rc)
389 plaintextLinelengthSB->setValue(rc.plaintext_linelen);
390 dviCB->setEditText(toqstr(rc.forward_search_dvi));
391 pdfCB->setEditText(toqstr(rc.forward_search_pdf));
393 switch (rc.export_overwrite) {
395 overwriteCO->setCurrentIndex(0);
398 overwriteCO->setCurrentIndex(1);
401 overwriteCO->setCurrentIndex(2);
405 printerPaperTypeED->setText(toqstr(rc.print_paper_flag));
406 printerLandscapeED->setText(toqstr(rc.print_landscape_flag));
407 printerPaperSizeED->setText(toqstr(rc.print_paper_dimension_flag));
411 /////////////////////////////////////////////////////////////////////
415 /////////////////////////////////////////////////////////////////////
417 PrefInput::PrefInput(GuiPreferences * form)
418 : PrefModule(catEditing, N_("Keyboard/Mouse"), form)
422 connect(keymapCB, SIGNAL(clicked()),
423 this, SIGNAL(changed()));
424 connect(firstKeymapED, SIGNAL(textChanged(QString)),
425 this, SIGNAL(changed()));
426 connect(secondKeymapED, SIGNAL(textChanged(QString)),
427 this, SIGNAL(changed()));
428 connect(mouseWheelSpeedSB, SIGNAL(valueChanged(double)),
429 this, SIGNAL(changed()));
430 connect(scrollzoomEnableCB, SIGNAL(clicked()),
431 this, SIGNAL(changed()));
432 connect(scrollzoomValueCO, SIGNAL(activated(int)),
433 this, SIGNAL(changed()));
434 connect(dontswapCB, SIGNAL(toggled(bool)),
435 this, SIGNAL(changed()));
436 connect(mmPasteCB, SIGNAL(toggled(bool)),
437 this, SIGNAL(changed()));
439 // reveal checkbox for switching Ctrl and Meta on Mac:
442 #if QT_VERSION > 0x040600
446 dontswapCB->setVisible(swapcb);
450 void PrefInput::applyRC(LyXRC & rc) const
452 // FIXME: can derive CB from the two EDs
453 rc.use_kbmap = keymapCB->isChecked();
454 rc.primary_kbmap = internal_path(fromqstr(firstKeymapED->text()));
455 rc.secondary_kbmap = internal_path(fromqstr(secondKeymapED->text()));
456 rc.mouse_wheel_speed = mouseWheelSpeedSB->value();
457 if (scrollzoomEnableCB->isChecked()) {
458 switch (scrollzoomValueCO->currentIndex()) {
460 rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_CTRL;
463 rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_SHIFT;
466 rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_ALT;
470 rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_OFF;
472 rc.mac_dontswap_ctrl_meta = dontswapCB->isChecked();
473 rc.mouse_middlebutton_paste = mmPasteCB->isChecked();
477 void PrefInput::updateRC(LyXRC const & rc)
479 // FIXME: can derive CB from the two EDs
480 keymapCB->setChecked(rc.use_kbmap);
481 firstKeymapED->setText(toqstr(external_path(rc.primary_kbmap)));
482 secondKeymapED->setText(toqstr(external_path(rc.secondary_kbmap)));
483 mouseWheelSpeedSB->setValue(rc.mouse_wheel_speed);
484 switch (rc.scroll_wheel_zoom) {
485 case LyXRC::SCROLL_WHEEL_ZOOM_OFF:
486 scrollzoomEnableCB->setChecked(false);
488 case LyXRC::SCROLL_WHEEL_ZOOM_CTRL:
489 scrollzoomEnableCB->setChecked(true);
490 scrollzoomValueCO->setCurrentIndex(0);
492 case LyXRC::SCROLL_WHEEL_ZOOM_SHIFT:
493 scrollzoomEnableCB->setChecked(true);
494 scrollzoomValueCO->setCurrentIndex(1);
496 case LyXRC::SCROLL_WHEEL_ZOOM_ALT:
497 scrollzoomEnableCB->setChecked(true);
498 scrollzoomValueCO->setCurrentIndex(2);
501 dontswapCB->setChecked(rc.mac_dontswap_ctrl_meta);
502 mmPasteCB->setChecked(rc.mouse_middlebutton_paste);
506 QString PrefInput::testKeymap(QString const & keymap)
508 return form_->browsekbmap(internalPath(keymap));
512 void PrefInput::on_firstKeymapPB_clicked(bool)
514 QString const file = testKeymap(firstKeymapED->text());
516 firstKeymapED->setText(file);
520 void PrefInput::on_secondKeymapPB_clicked(bool)
522 QString const file = testKeymap(secondKeymapED->text());
524 secondKeymapED->setText(file);
528 void PrefInput::on_keymapCB_toggled(bool keymap)
530 firstKeymapLA->setEnabled(keymap);
531 secondKeymapLA->setEnabled(keymap);
532 firstKeymapED->setEnabled(keymap);
533 secondKeymapED->setEnabled(keymap);
534 firstKeymapPB->setEnabled(keymap);
535 secondKeymapPB->setEnabled(keymap);
539 void PrefInput::on_scrollzoomEnableCB_toggled(bool enabled)
541 scrollzoomValueCO->setEnabled(enabled);
545 /////////////////////////////////////////////////////////////////////
549 /////////////////////////////////////////////////////////////////////
551 PrefCompletion::PrefCompletion(GuiPreferences * form)
552 : PrefModule(catEditing, N_("Input Completion"), form)
556 connect(inlineDelaySB, SIGNAL(valueChanged(double)),
557 this, SIGNAL(changed()));
558 connect(inlineMathCB, SIGNAL(clicked()),
559 this, SIGNAL(changed()));
560 connect(inlineTextCB, SIGNAL(clicked()),
561 this, SIGNAL(changed()));
562 connect(inlineDotsCB, SIGNAL(clicked()),
563 this, SIGNAL(changed()));
564 connect(popupDelaySB, SIGNAL(valueChanged(double)),
565 this, SIGNAL(changed()));
566 connect(popupMathCB, SIGNAL(clicked()),
567 this, SIGNAL(changed()));
568 connect(autocorrectionCB, SIGNAL(clicked()),
569 this, SIGNAL(changed()));
570 connect(popupTextCB, SIGNAL(clicked()),
571 this, SIGNAL(changed()));
572 connect(popupAfterCompleteCB, SIGNAL(clicked()),
573 this, SIGNAL(changed()));
574 connect(cursorTextCB, SIGNAL(clicked()),
575 this, SIGNAL(changed()));
576 connect(minlengthSB, SIGNAL(valueChanged(int)),
577 this, SIGNAL(changed()));
581 void PrefCompletion::on_inlineTextCB_clicked()
587 void PrefCompletion::on_popupTextCB_clicked()
593 void PrefCompletion::enableCB()
595 cursorTextCB->setEnabled(
596 popupTextCB->isChecked() || inlineTextCB->isChecked());
600 void PrefCompletion::applyRC(LyXRC & rc) const
602 rc.completion_inline_delay = inlineDelaySB->value();
603 rc.completion_inline_math = inlineMathCB->isChecked();
604 rc.completion_inline_text = inlineTextCB->isChecked();
605 rc.completion_inline_dots = inlineDotsCB->isChecked() ? 13 : -1;
606 rc.completion_popup_delay = popupDelaySB->value();
607 rc.completion_popup_math = popupMathCB->isChecked();
608 rc.autocorrection_math = autocorrectionCB->isChecked();
609 rc.completion_popup_text = popupTextCB->isChecked();
610 rc.completion_cursor_text = cursorTextCB->isChecked();
611 rc.completion_popup_after_complete =
612 popupAfterCompleteCB->isChecked();
613 rc.completion_minlength = minlengthSB->value();
617 void PrefCompletion::updateRC(LyXRC const & rc)
619 inlineDelaySB->setValue(rc.completion_inline_delay);
620 inlineMathCB->setChecked(rc.completion_inline_math);
621 inlineTextCB->setChecked(rc.completion_inline_text);
622 inlineDotsCB->setChecked(rc.completion_inline_dots != -1);
623 popupDelaySB->setValue(rc.completion_popup_delay);
624 popupMathCB->setChecked(rc.completion_popup_math);
625 autocorrectionCB->setChecked(rc.autocorrection_math);
626 popupTextCB->setChecked(rc.completion_popup_text);
627 cursorTextCB->setChecked(rc.completion_cursor_text);
628 popupAfterCompleteCB->setChecked(rc.completion_popup_after_complete);
630 minlengthSB->setValue(rc.completion_minlength);
635 /////////////////////////////////////////////////////////////////////
639 /////////////////////////////////////////////////////////////////////
641 PrefLatex::PrefLatex(GuiPreferences * form)
642 : PrefModule(catOutput, N_("LaTeX"), form)
646 latexDviPaperED->setValidator(new NoNewLineValidator(latexDviPaperED));
647 latexBibtexED->setValidator(new NoNewLineValidator(latexBibtexED));
648 latexJBibtexED->setValidator(new NoNewLineValidator(latexJBibtexED));
649 latexIndexED->setValidator(new NoNewLineValidator(latexIndexED));
650 latexJIndexED->setValidator(new NoNewLineValidator(latexJIndexED));
651 latexNomenclED->setValidator(new NoNewLineValidator(latexNomenclED));
652 latexChecktexED->setValidator(new NoNewLineValidator(latexChecktexED));
654 connect(latexChecktexED, SIGNAL(textChanged(QString)),
655 this, SIGNAL(changed()));
656 connect(latexBibtexCO, SIGNAL(activated(int)),
657 this, SIGNAL(changed()));
658 connect(latexBibtexED, SIGNAL(textChanged(QString)),
659 this, SIGNAL(changed()));
660 connect(latexJBibtexCO, SIGNAL(activated(int)),
661 this, SIGNAL(changed()));
662 connect(latexJBibtexED, SIGNAL(textChanged(QString)),
663 this, SIGNAL(changed()));
664 connect(latexIndexCO, SIGNAL(activated(int)),
665 this, SIGNAL(changed()));
666 connect(latexIndexED, SIGNAL(textChanged(QString)),
667 this, SIGNAL(changed()));
668 connect(latexJIndexED, SIGNAL(textChanged(QString)),
669 this, SIGNAL(changed()));
670 connect(latexAutoresetCB, SIGNAL(clicked()),
671 this, SIGNAL(changed()));
672 connect(latexDviPaperED, SIGNAL(textChanged(QString)),
673 this, SIGNAL(changed()));
674 connect(latexNomenclED, SIGNAL(textChanged(QString)),
675 this, SIGNAL(changed()));
677 #if defined(__CYGWIN__) || defined(_WIN32)
678 pathCB->setVisible(true);
679 connect(pathCB, SIGNAL(clicked()),
680 this, SIGNAL(changed()));
682 pathCB->setVisible(false);
687 void PrefLatex::on_latexBibtexCO_activated(int n)
689 QString const bibtex = latexBibtexCO->itemData(n).toString();
690 if (bibtex.isEmpty()) {
691 latexBibtexED->clear();
692 latexBibtexOptionsLA->setText(qt_("C&ommand:"));
695 for (LyXRC::CommandSet::const_iterator it = bibtex_alternatives.begin();
696 it != bibtex_alternatives.end(); ++it) {
697 QString const bib = toqstr(*it);
698 int ind = bib.indexOf(" ");
699 QString sel_command = bib.left(ind);
700 QString sel_options = ind < 0 ? QString() : bib.mid(ind + 1);
701 if (bibtex == sel_command) {
703 latexBibtexED->clear();
705 latexBibtexED->setText(sel_options.trimmed());
708 latexBibtexOptionsLA->setText(qt_("&Options:"));
712 void PrefLatex::on_latexJBibtexCO_activated(int n)
714 QString const jbibtex = latexJBibtexCO->itemData(n).toString();
715 if (jbibtex.isEmpty()) {
716 latexJBibtexED->clear();
717 latexJBibtexOptionsLA->setText(qt_("Co&mmand:"));
720 for (LyXRC::CommandSet::const_iterator it = jbibtex_alternatives.begin();
721 it != jbibtex_alternatives.end(); ++it) {
722 QString const bib = toqstr(*it);
723 int ind = bib.indexOf(" ");
724 QString sel_command = bib.left(ind);
725 QString sel_options = ind < 0 ? QString() : bib.mid(ind + 1);
726 if (jbibtex == sel_command) {
728 latexJBibtexED->clear();
730 latexJBibtexED->setText(sel_options.trimmed());
733 latexJBibtexOptionsLA->setText(qt_("Opt&ions:"));
737 void PrefLatex::on_latexIndexCO_activated(int n)
739 QString const index = latexIndexCO->itemData(n).toString();
740 if (index.isEmpty()) {
741 latexIndexED->clear();
742 latexIndexOptionsLA->setText(qt_("Co&mmand:"));
745 for (LyXRC::CommandSet::const_iterator it = index_alternatives.begin();
746 it != index_alternatives.end(); ++it) {
747 QString const idx = toqstr(*it);
748 int ind = idx.indexOf(" ");
749 QString sel_command = idx.left(ind);
750 QString sel_options = ind < 0 ? QString() : idx.mid(ind + 1);
751 if (index == sel_command) {
753 latexIndexED->clear();
755 latexIndexED->setText(sel_options.trimmed());
758 latexIndexOptionsLA->setText(qt_("Op&tions:"));
762 void PrefLatex::applyRC(LyXRC & rc) const
764 // If bibtex is not empty, bibopt contains the options, otherwise
765 // it is a customized bibtex command with options.
766 QString const bibtex = latexBibtexCO->itemData(
767 latexBibtexCO->currentIndex()).toString();
768 QString const bibopt = latexBibtexED->text();
769 if (bibtex.isEmpty())
770 rc.bibtex_command = fromqstr(bibopt);
771 else if (bibopt.isEmpty())
772 rc.bibtex_command = fromqstr(bibtex);
774 rc.bibtex_command = fromqstr(bibtex) + " " + fromqstr(bibopt);
776 // If jbibtex is not empty, jbibopt contains the options, otherwise
777 // it is a customized bibtex command with options.
778 QString const jbibtex = latexJBibtexCO->itemData(
779 latexJBibtexCO->currentIndex()).toString();
780 QString const jbibopt = latexJBibtexED->text();
781 if (jbibtex.isEmpty())
782 rc.jbibtex_command = fromqstr(jbibopt);
783 else if (jbibopt.isEmpty())
784 rc.jbibtex_command = fromqstr(jbibtex);
786 rc.jbibtex_command = fromqstr(jbibtex) + " " + fromqstr(jbibopt);
788 // If index is not empty, idxopt contains the options, otherwise
789 // it is a customized index command with options.
790 QString const index = latexIndexCO->itemData(
791 latexIndexCO->currentIndex()).toString();
792 QString const idxopt = latexIndexED->text();
794 rc.index_command = fromqstr(idxopt);
795 else if (idxopt.isEmpty())
796 rc.index_command = fromqstr(index);
798 rc.index_command = fromqstr(index) + " " + fromqstr(idxopt);
800 rc.chktex_command = fromqstr(latexChecktexED->text());
801 rc.jindex_command = fromqstr(latexJIndexED->text());
802 rc.nomencl_command = fromqstr(latexNomenclED->text());
803 rc.auto_reset_options = latexAutoresetCB->isChecked();
804 rc.view_dvi_paper_option = fromqstr(latexDviPaperED->text());
805 #if defined(__CYGWIN__) || defined(_WIN32)
806 rc.windows_style_tex_paths = pathCB->isChecked();
811 void PrefLatex::updateRC(LyXRC const & rc)
813 latexBibtexCO->clear();
815 latexBibtexCO->addItem(qt_("Automatic"), "automatic");
816 latexBibtexCO->addItem(qt_("Custom"), QString());
817 for (LyXRC::CommandSet::const_iterator it = rc.bibtex_alternatives.begin();
818 it != rc.bibtex_alternatives.end(); ++it) {
819 QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
820 latexBibtexCO->addItem(command, command);
823 bibtex_alternatives = rc.bibtex_alternatives;
825 QString const bib = toqstr(rc.bibtex_command);
826 int ind = bib.indexOf(" ");
827 QString sel_command = bib.left(ind);
828 QString sel_options = ind < 0 ? QString() : bib.mid(ind + 1);
830 int pos = latexBibtexCO->findData(sel_command);
832 latexBibtexCO->setCurrentIndex(pos);
833 latexBibtexED->setText(sel_options.trimmed());
834 latexBibtexOptionsLA->setText(qt_("&Options:"));
836 latexBibtexED->setText(toqstr(rc.bibtex_command));
837 latexBibtexCO->setCurrentIndex(0);
838 latexBibtexOptionsLA->setText(qt_("C&ommand:"));
841 latexJBibtexCO->clear();
843 latexJBibtexCO->addItem(qt_("Automatic"), "automatic");
844 latexJBibtexCO->addItem(qt_("Custom"), QString());
845 for (LyXRC::CommandSet::const_iterator it = rc.jbibtex_alternatives.begin();
846 it != rc.jbibtex_alternatives.end(); ++it) {
847 QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
848 latexJBibtexCO->addItem(command, command);
851 jbibtex_alternatives = rc.jbibtex_alternatives;
853 QString const jbib = toqstr(rc.jbibtex_command);
854 ind = jbib.indexOf(" ");
855 sel_command = jbib.left(ind);
856 sel_options = ind < 0 ? QString() : jbib.mid(ind + 1);
858 pos = latexJBibtexCO->findData(sel_command);
860 latexJBibtexCO->setCurrentIndex(pos);
861 latexJBibtexED->setText(sel_options.trimmed());
862 latexJBibtexOptionsLA->setText(qt_("Opt&ions:"));
864 latexJBibtexED->setText(toqstr(rc.bibtex_command));
865 latexJBibtexCO->setCurrentIndex(0);
866 latexJBibtexOptionsLA->setText(qt_("Co&mmand:"));
869 latexIndexCO->clear();
871 latexIndexCO->addItem(qt_("Custom"), QString());
872 for (LyXRC::CommandSet::const_iterator it = rc.index_alternatives.begin();
873 it != rc.index_alternatives.end(); ++it) {
874 QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
875 latexIndexCO->addItem(command, command);
878 index_alternatives = rc.index_alternatives;
880 QString const idx = toqstr(rc.index_command);
881 ind = idx.indexOf(" ");
882 sel_command = idx.left(ind);
883 sel_options = ind < 0 ? QString() : idx.mid(ind + 1);
885 pos = latexIndexCO->findData(sel_command);
887 latexIndexCO->setCurrentIndex(pos);
888 latexIndexED->setText(sel_options.trimmed());
889 latexIndexOptionsLA->setText(qt_("Op&tions:"));
891 latexIndexED->setText(toqstr(rc.index_command));
892 latexIndexCO->setCurrentIndex(0);
893 latexIndexOptionsLA->setText(qt_("Co&mmand:"));
896 latexChecktexED->setText(toqstr(rc.chktex_command));
897 latexJIndexED->setText(toqstr(rc.jindex_command));
898 latexNomenclED->setText(toqstr(rc.nomencl_command));
899 latexAutoresetCB->setChecked(rc.auto_reset_options);
900 latexDviPaperED->setText(toqstr(rc.view_dvi_paper_option));
901 #if defined(__CYGWIN__) || defined(_WIN32)
902 pathCB->setChecked(rc.windows_style_tex_paths);
907 /////////////////////////////////////////////////////////////////////
911 /////////////////////////////////////////////////////////////////////
913 PrefScreenFonts::PrefScreenFonts(GuiPreferences * form)
914 : PrefModule(catLookAndFeel, N_("Screen Fonts"), form)
918 #if QT_VERSION < 0x050e00
919 connect(screenRomanCO, SIGNAL(activated(QString)),
920 this, SLOT(selectRoman(QString)));
921 connect(screenSansCO, SIGNAL(activated(QString)),
922 this, SLOT(selectSans(QString)));
923 connect(screenTypewriterCO, SIGNAL(activated(QString)),
924 this, SLOT(selectTypewriter(QString)));
926 connect(screenRomanCO, SIGNAL(textActivated(QString)),
927 this, SLOT(selectRoman(QString)));
928 connect(screenSansCO, SIGNAL(textActivated(QString)),
929 this, SLOT(selectSans(QString)));
930 connect(screenTypewriterCO, SIGNAL(textActivated(QString)),
931 this, SLOT(selectTypewriter(QString)));
934 QFontDatabase fontdb;
935 QStringList families(fontdb.families());
936 for (auto const & family : families) {
937 screenRomanCO->addItem(family);
938 screenSansCO->addItem(family);
939 screenTypewriterCO->addItem(family);
941 #if QT_VERSION < 0x050e00
942 connect(screenRomanCO, SIGNAL(activated(QString)),
943 this, SIGNAL(changed()));
944 connect(screenSansCO, SIGNAL(activated(QString)),
945 this, SIGNAL(changed()));
946 connect(screenTypewriterCO, SIGNAL(activated(QString)),
947 this, SIGNAL(changed()));
949 connect(screenRomanCO, SIGNAL(textActivated(QString)),
950 this, SIGNAL(changed()));
951 connect(screenSansCO, SIGNAL(textActivated(QString)),
952 this, SIGNAL(changed()));
953 connect(screenTypewriterCO, SIGNAL(textActivated(QString)),
954 this, SIGNAL(changed()));
956 connect(screenZoomSB, SIGNAL(valueChanged(int)),
957 this, SIGNAL(changed()));
958 connect(screenTinyED, SIGNAL(textChanged(QString)),
959 this, SIGNAL(changed()));
960 connect(screenSmallestED, SIGNAL(textChanged(QString)),
961 this, SIGNAL(changed()));
962 connect(screenSmallerED, SIGNAL(textChanged(QString)),
963 this, SIGNAL(changed()));
964 connect(screenSmallED, SIGNAL(textChanged(QString)),
965 this, SIGNAL(changed()));
966 connect(screenNormalED, SIGNAL(textChanged(QString)),
967 this, SIGNAL(changed()));
968 connect(screenLargeED, SIGNAL(textChanged(QString)),
969 this, SIGNAL(changed()));
970 connect(screenLargerED, SIGNAL(textChanged(QString)),
971 this, SIGNAL(changed()));
972 connect(screenLargestED, SIGNAL(textChanged(QString)),
973 this, SIGNAL(changed()));
974 connect(screenHugeED, SIGNAL(textChanged(QString)),
975 this, SIGNAL(changed()));
976 connect(screenHugerED, SIGNAL(textChanged(QString)),
977 this, SIGNAL(changed()));
979 screenTinyED->setValidator(new QDoubleValidator(screenTinyED));
980 screenSmallestED->setValidator(new QDoubleValidator(screenSmallestED));
981 screenSmallerED->setValidator(new QDoubleValidator(screenSmallerED));
982 screenSmallED->setValidator(new QDoubleValidator(screenSmallED));
983 screenNormalED->setValidator(new QDoubleValidator(screenNormalED));
984 screenLargeED->setValidator(new QDoubleValidator(screenLargeED));
985 screenLargerED->setValidator(new QDoubleValidator(screenLargerED));
986 screenLargestED->setValidator(new QDoubleValidator(screenLargestED));
987 screenHugeED->setValidator(new QDoubleValidator(screenHugeED));
988 screenHugerED->setValidator(new QDoubleValidator(screenHugerED));
992 void PrefScreenFonts::applyRC(LyXRC & rc) const
994 LyXRC const oldrc = rc;
996 parseFontName(screenRomanCO->currentText(),
997 rc.roman_font_name, rc.roman_font_foundry);
998 parseFontName(screenSansCO->currentText(),
999 rc.sans_font_name, rc.sans_font_foundry);
1000 parseFontName(screenTypewriterCO->currentText(),
1001 rc.typewriter_font_name, rc.typewriter_font_foundry);
1003 rc.defaultZoom = screenZoomSB->value();
1004 rc.font_sizes[TINY_SIZE] = widgetToDoubleStr(screenTinyED);
1005 rc.font_sizes[SCRIPT_SIZE] = widgetToDoubleStr(screenSmallestED);
1006 rc.font_sizes[FOOTNOTE_SIZE] = widgetToDoubleStr(screenSmallerED);
1007 rc.font_sizes[SMALL_SIZE] = widgetToDoubleStr(screenSmallED);
1008 rc.font_sizes[NORMAL_SIZE] = widgetToDoubleStr(screenNormalED);
1009 rc.font_sizes[LARGE_SIZE] = widgetToDoubleStr(screenLargeED);
1010 rc.font_sizes[LARGER_SIZE] = widgetToDoubleStr(screenLargerED);
1011 rc.font_sizes[LARGEST_SIZE] = widgetToDoubleStr(screenLargestED);
1012 rc.font_sizes[HUGE_SIZE] = widgetToDoubleStr(screenHugeED);
1013 rc.font_sizes[HUGER_SIZE] = widgetToDoubleStr(screenHugerED);
1017 void PrefScreenFonts::updateRC(LyXRC const & rc)
1019 setComboxFont(screenRomanCO, rc.roman_font_name,
1020 rc.roman_font_foundry);
1021 setComboxFont(screenSansCO, rc.sans_font_name,
1022 rc.sans_font_foundry);
1023 setComboxFont(screenTypewriterCO, rc.typewriter_font_name,
1024 rc.typewriter_font_foundry);
1026 selectRoman(screenRomanCO->currentText());
1027 selectSans(screenSansCO->currentText());
1028 selectTypewriter(screenTypewriterCO->currentText());
1030 screenZoomSB->setValue(rc.defaultZoom);
1031 updateScreenFontSizes(rc);
1035 void PrefScreenFonts::updateScreenFontSizes(LyXRC const & rc)
1037 doubleToWidget(screenTinyED, rc.font_sizes[TINY_SIZE]);
1038 doubleToWidget(screenSmallestED, rc.font_sizes[SCRIPT_SIZE]);
1039 doubleToWidget(screenSmallerED, rc.font_sizes[FOOTNOTE_SIZE]);
1040 doubleToWidget(screenSmallED, rc.font_sizes[SMALL_SIZE]);
1041 doubleToWidget(screenNormalED, rc.font_sizes[NORMAL_SIZE]);
1042 doubleToWidget(screenLargeED, rc.font_sizes[LARGE_SIZE]);
1043 doubleToWidget(screenLargerED, rc.font_sizes[LARGER_SIZE]);
1044 doubleToWidget(screenLargestED, rc.font_sizes[LARGEST_SIZE]);
1045 doubleToWidget(screenHugeED, rc.font_sizes[HUGE_SIZE]);
1046 doubleToWidget(screenHugerED, rc.font_sizes[HUGER_SIZE]);
1050 void PrefScreenFonts::selectRoman(const QString & name)
1052 screenRomanFE->set(QFont(name), name);
1056 void PrefScreenFonts::selectSans(const QString & name)
1058 screenSansFE->set(QFont(name), name);
1062 void PrefScreenFonts::selectTypewriter(const QString & name)
1064 screenTypewriterFE->set(QFont(name), name);
1068 /////////////////////////////////////////////////////////////////////
1072 /////////////////////////////////////////////////////////////////////
1075 PrefColors::PrefColors(GuiPreferences * form)
1076 : PrefModule(catLookAndFeel, N_("Colors"), form)
1080 // FIXME: all of this initialization should be put into the controller.
1081 // See http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg113301.html
1082 // for some discussion of why that is not trivial.
1083 QPixmap icon(32, 32);
1084 for (int i = 0; i < Color_ignore; ++i) {
1085 ColorCode lc = static_cast<ColorCode>(i);
1086 if (lc == Color_none
1087 || lc == Color_black
1088 || lc == Color_white
1090 || lc == Color_brown
1092 || lc == Color_darkgray
1094 || lc == Color_green
1095 || lc == Color_lightgray
1097 || lc == Color_magenta
1098 || lc == Color_olive
1099 || lc == Color_orange
1101 || lc == Color_purple
1104 || lc == Color_violet
1105 || lc == Color_yellow
1106 || lc == Color_inherit
1107 || lc == Color_ignore)
1109 lcolors_.push_back(lc);
1111 sort(lcolors_.begin(), lcolors_.end(), ColorSorter);
1112 vector<ColorCode>::const_iterator cit = lcolors_.begin();
1113 vector<ColorCode>::const_iterator const end = lcolors_.end();
1114 for (; cit != end; ++cit) {
1115 (void) new QListWidgetItem(QIcon(icon),
1116 toqstr(lcolor.getGUIName(*cit)), lyxObjectsLW);
1118 curcolors_.resize(lcolors_.size());
1119 newcolors_.resize(lcolors_.size());
1120 // End initialization
1122 connect(colorChangePB, SIGNAL(clicked()),
1123 this, SLOT(changeColor()));
1124 connect(colorResetPB, SIGNAL(clicked()),
1125 this, SLOT(resetColor()));
1126 connect(colorResetAllPB, SIGNAL(clicked()),
1127 this, SLOT(resetAllColor()));
1128 connect(lyxObjectsLW, SIGNAL(itemSelectionChanged()),
1129 this, SLOT(changeLyxObjectsSelection()));
1130 connect(lyxObjectsLW, SIGNAL(itemActivated(QListWidgetItem*)),
1131 this, SLOT(changeColor()));
1132 connect(syscolorsCB, SIGNAL(toggled(bool)),
1133 this, SIGNAL(changed()));
1134 connect(syscolorsCB, SIGNAL(toggled(bool)),
1135 this, SLOT(changeSysColor()));
1139 void PrefColors::applyRC(LyXRC & rc) const
1143 for (unsigned int i = 0; i < lcolors_.size(); ++i)
1144 if (curcolors_[i] != newcolors_[i])
1145 form_->setColor(lcolors_[i], newcolors_[i]);
1146 rc.use_system_colors = syscolorsCB->isChecked();
1148 if (oldrc.use_system_colors != rc.use_system_colors)
1149 guiApp->colorCache().clear();
1153 void PrefColors::updateRC(LyXRC const & rc)
1155 for (size_type i = 0; i < lcolors_.size(); ++i) {
1156 QColor color = guiApp->colorCache().get(lcolors_[i], false);
1157 QPixmap coloritem(32, 32);
1158 coloritem.fill(color);
1159 lyxObjectsLW->item(int(i))->setIcon(QIcon(coloritem));
1160 newcolors_[i] = curcolors_[i] = color.name();
1162 syscolorsCB->setChecked(rc.use_system_colors);
1163 changeLyxObjectsSelection();
1165 setDisabledResets();
1169 void PrefColors::changeColor()
1171 int const row = lyxObjectsLW->currentRow();
1177 QString const color = newcolors_[size_t(row)];
1178 QColor const c = QColorDialog::getColor(QColor(color), qApp->focusWidget());
1180 if (setColor(row, c, color)) {
1181 setDisabledResets();
1188 void PrefColors::resetColor()
1190 int const row = lyxObjectsLW->currentRow();
1196 QString const color = newcolors_[size_t(row)];
1197 QColor const c = getDefaultColorByRow(row);
1199 if (setColor(row, c, color)) {
1200 setDisabledResets();
1207 void PrefColors::resetAllColor()
1209 bool isChanged = false;
1211 colorResetAllPB->setDisabled(true);
1213 for (int irow = 0, count = lyxObjectsLW->count(); irow < count; ++irow) {
1214 QString const color = newcolors_[size_t(irow)];
1215 QColor const c = getDefaultColorByRow(irow);
1217 if (setColor(irow, c, color))
1222 setDisabledResets();
1229 bool PrefColors::setColor(int const row, QColor const & new_color,
1230 QString const & old_color)
1232 if (new_color.isValid() && new_color.name() != old_color) {
1233 newcolors_[size_t(row)] = new_color.name();
1234 QPixmap coloritem(32, 32);
1235 coloritem.fill(new_color);
1236 lyxObjectsLW->item(row)->setIcon(QIcon(coloritem));
1243 void PrefColors::setDisabledResets()
1245 int const row = lyxObjectsLW->currentRow();
1246 // set disable reset buttons ...
1248 colorResetPB->setDisabled(isDefaultColor(row, newcolors_[size_t(row)]));
1250 colorResetAllPB->setDisabled(true);
1252 // ... in between process qt events to give quicker visual feedback to the user ...
1253 guiApp->processEvents();
1255 // ... set disable Reset All button
1256 for (int irow = 0, count = lyxObjectsLW->count(); irow < count; ++irow) {
1257 if (!isDefaultColor(irow, newcolors_[size_t(irow)])) {
1258 colorResetAllPB->setDisabled(false);
1259 // the break condition might hide performance issues
1260 // if a non-default color is at the top of the list
1267 bool PrefColors::isDefaultColor(int const row, QString const & color)
1269 return color == getDefaultColorByRow(row).name();
1273 QColor PrefColors::getDefaultColorByRow(int const row)
1275 ColorSet const defaultcolor;
1276 return defaultcolor.getX11HexName(lcolors_[size_t(row)],
1277 guiApp->colorCache().isDarkMode()).c_str();
1281 void PrefColors::changeSysColor()
1283 for (int row = 0 ; row < lyxObjectsLW->count() ; ++row) {
1284 // skip colors that are taken from system palette
1285 bool const disable = syscolorsCB->isChecked()
1286 && guiApp->colorCache().isSystem(lcolors_[size_t(row)]);
1288 QListWidgetItem * const item = lyxObjectsLW->item(row);
1289 Qt::ItemFlags const flags = item->flags();
1292 item->setFlags(flags & ~Qt::ItemIsEnabled);
1294 item->setFlags(flags | Qt::ItemIsEnabled);
1299 void PrefColors::changeLyxObjectsSelection()
1301 int currentRow = lyxObjectsLW->currentRow();
1302 colorChangePB->setDisabled(currentRow < 0);
1305 colorResetPB->setDisabled(true);
1307 colorResetPB->setDisabled(
1308 isDefaultColor(currentRow, newcolors_[size_t(currentRow)]));
1312 /////////////////////////////////////////////////////////////////////
1316 /////////////////////////////////////////////////////////////////////
1318 PrefDisplay::PrefDisplay(GuiPreferences * form)
1319 : PrefModule(catLookAndFeel, N_("Display"), form)
1322 connect(displayGraphicsCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1323 connect(instantPreviewCO, SIGNAL(activated(int)), this, SIGNAL(changed()));
1324 connect(previewSizeSB, SIGNAL(valueChanged(double)), this, SIGNAL(changed()));
1325 connect(paragraphMarkerCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1326 connect(ctAdditionsUnderlinedCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1330 void PrefDisplay::on_instantPreviewCO_currentIndexChanged(int index)
1332 previewSizeSB->setEnabled(index != 0);
1336 void PrefDisplay::applyRC(LyXRC & rc) const
1338 switch (instantPreviewCO->currentIndex()) {
1340 rc.preview = LyXRC::PREVIEW_OFF;
1343 rc.preview = LyXRC::PREVIEW_NO_MATH;
1346 rc.preview = LyXRC::PREVIEW_ON;
1350 rc.display_graphics = displayGraphicsCB->isChecked();
1351 rc.preview_scale_factor = previewSizeSB->value();
1352 rc.paragraph_markers = paragraphMarkerCB->isChecked();
1353 rc.ct_additions_underlined = ctAdditionsUnderlinedCB->isChecked();
1355 // FIXME!! The graphics cache no longer has a changeDisplay method.
1357 if (old_value != rc.display_graphics) {
1358 graphics::GCache & gc = graphics::GCache::get();
1365 void PrefDisplay::updateRC(LyXRC const & rc)
1367 switch (rc.preview) {
1368 case LyXRC::PREVIEW_OFF:
1369 instantPreviewCO->setCurrentIndex(0);
1371 case LyXRC::PREVIEW_NO_MATH :
1372 instantPreviewCO->setCurrentIndex(1);
1374 case LyXRC::PREVIEW_ON :
1375 instantPreviewCO->setCurrentIndex(2);
1379 displayGraphicsCB->setChecked(rc.display_graphics);
1380 previewSizeSB->setValue(rc.preview_scale_factor);
1381 paragraphMarkerCB->setChecked(rc.paragraph_markers);
1382 ctAdditionsUnderlinedCB->setChecked(rc.ct_additions_underlined);
1383 previewSizeSB->setEnabled(
1385 && rc.preview != LyXRC::PREVIEW_OFF);
1389 /////////////////////////////////////////////////////////////////////
1393 /////////////////////////////////////////////////////////////////////
1395 PrefPaths::PrefPaths(GuiPreferences * form)
1396 : PrefModule(QString(), N_("Paths"), form)
1400 connect(workingDirPB, SIGNAL(clicked()), this, SLOT(selectWorkingdir()));
1401 connect(workingDirED, SIGNAL(textChanged(QString)),
1402 this, SIGNAL(changed()));
1404 connect(templateDirPB, SIGNAL(clicked()), this, SLOT(selectTemplatedir()));
1405 connect(templateDirED, SIGNAL(textChanged(QString)),
1406 this, SIGNAL(changed()));
1408 connect(exampleDirPB, SIGNAL(clicked()), this, SLOT(selectExampledir()));
1409 connect(exampleDirED, SIGNAL(textChanged(QString)),
1410 this, SIGNAL(changed()));
1412 connect(backupDirPB, SIGNAL(clicked()), this, SLOT(selectBackupdir()));
1413 connect(backupDirED, SIGNAL(textChanged(QString)),
1414 this, SIGNAL(changed()));
1416 connect(lyxserverDirPB, SIGNAL(clicked()), this, SLOT(selectLyxPipe()));
1417 connect(lyxserverDirED, SIGNAL(textChanged(QString)),
1418 this, SIGNAL(changed()));
1420 connect(thesaurusDirPB, SIGNAL(clicked()), this, SLOT(selectThesaurusdir()));
1421 connect(thesaurusDirED, SIGNAL(textChanged(QString)),
1422 this, SIGNAL(changed()));
1424 connect(tempDirPB, SIGNAL(clicked()), this, SLOT(selectTempdir()));
1425 connect(tempDirED, SIGNAL(textChanged(QString)),
1426 this, SIGNAL(changed()));
1428 #if defined(USE_HUNSPELL)
1429 connect(hunspellDirPB, SIGNAL(clicked()), this, SLOT(selectHunspelldir()));
1430 connect(hunspellDirED, SIGNAL(textChanged(QString)),
1431 this, SIGNAL(changed()));
1433 hunspellDirPB->setEnabled(false);
1434 hunspellDirED->setEnabled(false);
1437 connect(pathPrefixED, SIGNAL(textChanged(QString)),
1438 this, SIGNAL(changed()));
1440 connect(texinputsPrefixED, SIGNAL(textChanged(QString)),
1441 this, SIGNAL(changed()));
1443 pathPrefixED->setValidator(new NoNewLineValidator(pathPrefixED));
1444 texinputsPrefixED->setValidator(new NoNewLineValidator(texinputsPrefixED));
1448 void PrefPaths::applyRC(LyXRC & rc) const
1450 rc.document_path = internal_path(fromqstr(workingDirED->text()));
1451 rc.example_path = internal_path(fromqstr(exampleDirED->text()));
1452 rc.template_path = internal_path(fromqstr(templateDirED->text()));
1453 rc.backupdir_path = internal_path(fromqstr(backupDirED->text()));
1454 rc.tempdir_path = internal_path(fromqstr(tempDirED->text()));
1455 rc.thesaurusdir_path = internal_path(fromqstr(thesaurusDirED->text()));
1456 rc.hunspelldir_path = internal_path(fromqstr(hunspellDirED->text()));
1457 rc.path_prefix = internal_path_list(fromqstr(pathPrefixED->text()));
1458 rc.texinputs_prefix = internal_path_list(fromqstr(texinputsPrefixED->text()));
1459 // FIXME: should be a checkbox only
1460 rc.lyxpipes = internal_path(fromqstr(lyxserverDirED->text()));
1464 void PrefPaths::updateRC(LyXRC const & rc)
1466 workingDirED->setText(toqstr(external_path(rc.document_path)));
1467 exampleDirED->setText(toqstr(external_path(rc.example_path)));
1468 templateDirED->setText(toqstr(external_path(rc.template_path)));
1469 backupDirED->setText(toqstr(external_path(rc.backupdir_path)));
1470 tempDirED->setText(toqstr(external_path(rc.tempdir_path)));
1471 thesaurusDirED->setText(toqstr(external_path(rc.thesaurusdir_path)));
1472 hunspellDirED->setText(toqstr(external_path(rc.hunspelldir_path)));
1473 pathPrefixED->setText(toqstr(external_path_list(rc.path_prefix)));
1474 texinputsPrefixED->setText(toqstr(external_path_list(rc.texinputs_prefix)));
1475 // FIXME: should be a checkbox only
1476 lyxserverDirED->setText(toqstr(external_path(rc.lyxpipes)));
1480 void PrefPaths::selectExampledir()
1482 QString file = browseDir(internalPath(exampleDirED->text()),
1483 qt_("Select directory for example files"));
1484 if (!file.isEmpty())
1485 exampleDirED->setText(file);
1489 void PrefPaths::selectTemplatedir()
1491 QString file = browseDir(internalPath(templateDirED->text()),
1492 qt_("Select a document templates directory"));
1493 if (!file.isEmpty())
1494 templateDirED->setText(file);
1498 void PrefPaths::selectTempdir()
1500 QString file = browseDir(internalPath(tempDirED->text()),
1501 qt_("Select a temporary directory"));
1502 if (!file.isEmpty())
1503 tempDirED->setText(file);
1507 void PrefPaths::selectBackupdir()
1509 QString file = browseDir(internalPath(backupDirED->text()),
1510 qt_("Select a backups directory"));
1511 if (!file.isEmpty())
1512 backupDirED->setText(file);
1516 void PrefPaths::selectWorkingdir()
1518 QString file = browseDir(internalPath(workingDirED->text()),
1519 qt_("Select a document directory"));
1520 if (!file.isEmpty())
1521 workingDirED->setText(file);
1525 void PrefPaths::selectThesaurusdir()
1527 QString file = browseDir(internalPath(thesaurusDirED->text()),
1528 qt_("Set the path to the thesaurus dictionaries"));
1529 if (!file.isEmpty())
1530 thesaurusDirED->setText(file);
1534 void PrefPaths::selectHunspelldir()
1536 QString file = browseDir(internalPath(hunspellDirED->text()),
1537 qt_("Set the path to the Hunspell dictionaries"));
1538 if (!file.isEmpty())
1539 hunspellDirED->setText(file);
1543 void PrefPaths::selectLyxPipe()
1545 QString file = form_->browse(internalPath(lyxserverDirED->text()),
1546 qt_("Give a filename for the LyX server pipe"));
1547 if (!file.isEmpty())
1548 lyxserverDirED->setText(file);
1552 /////////////////////////////////////////////////////////////////////
1556 /////////////////////////////////////////////////////////////////////
1558 PrefSpellchecker::PrefSpellchecker(GuiPreferences * form)
1559 : PrefModule(catLanguage, N_("Spellchecker"), form)
1563 // FIXME: this check should test the target platform (darwin)
1564 #if defined(USE_MACOSX_PACKAGING)
1565 spellcheckerCB->addItem(qt_("Native"), QString("native"));
1566 #define CONNECT_APPLESPELL
1568 #undef CONNECT_APPLESPELL
1570 #if defined(USE_ASPELL)
1571 spellcheckerCB->addItem(qt_("Aspell"), QString("aspell"));
1573 #if defined(USE_ENCHANT)
1574 spellcheckerCB->addItem(qt_("Enchant"), QString("enchant"));
1576 #if defined(USE_HUNSPELL)
1577 spellcheckerCB->addItem(qt_("Hunspell"), QString("hunspell"));
1580 #if defined(CONNECT_APPLESPELL) || defined(USE_ASPELL) || defined(USE_ENCHANT) || defined(USE_HUNSPELL)
1581 connect(spellcheckerCB, SIGNAL(currentIndexChanged(int)),
1582 this, SIGNAL(changed()));
1583 connect(altLanguageED, SIGNAL(textChanged(QString)),
1584 this, SIGNAL(changed()));
1585 connect(escapeCharactersED, SIGNAL(textChanged(QString)),
1586 this, SIGNAL(changed()));
1587 connect(compoundWordCB, SIGNAL(clicked()),
1588 this, SIGNAL(changed()));
1589 connect(spellcheckContinuouslyCB, SIGNAL(clicked()),
1590 this, SIGNAL(changed()));
1591 connect(spellcheckNotesCB, SIGNAL(clicked()),
1592 this, SIGNAL(changed()));
1594 altLanguageED->setValidator(new NoNewLineValidator(altLanguageED));
1595 escapeCharactersED->setValidator(new NoNewLineValidator(escapeCharactersED));
1597 spellcheckerCB->setEnabled(false);
1598 altLanguageED->setEnabled(false);
1599 escapeCharactersED->setEnabled(false);
1600 compoundWordCB->setEnabled(false);
1601 spellcheckContinuouslyCB->setEnabled(false);
1602 spellcheckNotesCB->setEnabled(false);
1607 void PrefSpellchecker::applyRC(LyXRC & rc) const
1609 string const speller = fromqstr(spellcheckerCB->
1610 itemData(spellcheckerCB->currentIndex()).toString());
1611 if (!speller.empty())
1612 rc.spellchecker = speller;
1613 rc.spellchecker_alt_lang = fromqstr(altLanguageED->text());
1614 rc.spellchecker_esc_chars = fromqstr(escapeCharactersED->text());
1615 rc.spellchecker_accept_compound = compoundWordCB->isChecked();
1616 rc.spellcheck_continuously = spellcheckContinuouslyCB->isChecked();
1617 rc.spellcheck_notes = spellcheckNotesCB->isChecked();
1621 void PrefSpellchecker::updateRC(LyXRC const & rc)
1623 spellcheckerCB->setCurrentIndex(
1624 spellcheckerCB->findData(toqstr(rc.spellchecker)));
1625 altLanguageED->setText(toqstr(rc.spellchecker_alt_lang));
1626 escapeCharactersED->setText(toqstr(rc.spellchecker_esc_chars));
1627 compoundWordCB->setChecked(rc.spellchecker_accept_compound);
1628 spellcheckContinuouslyCB->setChecked(rc.spellcheck_continuously);
1629 spellcheckNotesCB->setChecked(rc.spellcheck_notes);
1633 void PrefSpellchecker::on_spellcheckerCB_currentIndexChanged(int index)
1635 QString spellchecker = spellcheckerCB->itemData(index).toString();
1637 compoundWordCB->setEnabled(spellchecker == QString("aspell"));
1642 /////////////////////////////////////////////////////////////////////
1646 /////////////////////////////////////////////////////////////////////
1649 PrefConverters::PrefConverters(GuiPreferences * form)
1650 : PrefModule(catFiles, N_("Converters"), form)
1654 connect(converterNewPB, SIGNAL(clicked()),
1655 this, SLOT(updateConverter()));
1656 connect(converterRemovePB, SIGNAL(clicked()),
1657 this, SLOT(removeConverter()));
1658 connect(converterModifyPB, SIGNAL(clicked()),
1659 this, SLOT(updateConverter()));
1660 connect(convertersLW, SIGNAL(currentRowChanged(int)),
1661 this, SLOT(switchConverter()));
1662 #if QT_VERSION < 0x050e00
1663 connect(converterFromCO, SIGNAL(activated(QString)),
1664 this, SLOT(changeConverter()));
1665 connect(converterToCO, SIGNAL(activated(QString)),
1666 this, SLOT(changeConverter()));
1668 connect(converterFromCO, SIGNAL(textActivated(QString)),
1669 this, SLOT(changeConverter()));
1670 connect(converterToCO, SIGNAL(textActivated(QString)),
1671 this, SLOT(changeConverter()));
1673 connect(converterED, SIGNAL(textEdited(QString)),
1674 this, SLOT(changeConverter()));
1675 connect(converterFlagED, SIGNAL(textEdited(QString)),
1676 this, SLOT(changeConverter()));
1677 connect(converterNewPB, SIGNAL(clicked()),
1678 this, SIGNAL(changed()));
1679 connect(converterRemovePB, SIGNAL(clicked()),
1680 this, SIGNAL(changed()));
1681 connect(converterModifyPB, SIGNAL(clicked()),
1682 this, SIGNAL(changed()));
1683 connect(maxAgeLE, SIGNAL(textEdited(QString)),
1684 this, SIGNAL(changed()));
1685 connect(needauthForbiddenCB, SIGNAL(toggled(bool)),
1686 this, SIGNAL(changed()));
1688 converterED->setValidator(new NoNewLineValidator(converterED));
1689 converterFlagED->setValidator(new NoNewLineValidator(converterFlagED));
1690 maxAgeLE->setValidator(new QDoubleValidator(0, HUGE_VAL, 6, maxAgeLE));
1691 //converterDefGB->setFocusProxy(convertersLW);
1695 void PrefConverters::applyRC(LyXRC & rc) const
1697 rc.use_converter_cache = cacheCB->isChecked();
1698 rc.use_converter_needauth_forbidden = needauthForbiddenCB->isChecked();
1699 rc.use_converter_needauth = needauthCB->isChecked();
1700 rc.converter_cache_maxage = int(widgetToDouble(maxAgeLE) * 86400.0);
1704 static void setCheckboxBlockSignals(QCheckBox *cb, bool checked) {
1705 cb->blockSignals(true);
1706 cb->setChecked(checked);
1707 cb->blockSignals(false);
1711 void PrefConverters::updateRC(LyXRC const & rc)
1713 cacheCB->setChecked(rc.use_converter_cache);
1714 needauthForbiddenCB->setChecked(rc.use_converter_needauth_forbidden);
1715 setCheckboxBlockSignals(needauthCB, rc.use_converter_needauth);
1717 doubleToWidget(maxAgeLE, (double(rc.converter_cache_maxage) / 86400.0), 'g', 6);
1722 void PrefConverters::updateGui()
1724 QString const pattern("%1 -> %2");
1725 form_->formats().sort();
1726 form_->converters().update(form_->formats());
1727 // save current selection
1730 .arg(converterFromCO->currentText())
1731 .arg(converterToCO->currentText());
1733 converterFromCO->clear();
1734 converterToCO->clear();
1736 for (Format const & f : form_->formats()) {
1737 QString const name = toqstr(translateIfPossible(f.prettyname()));
1738 converterFromCO->addItem(name);
1739 converterToCO->addItem(name);
1742 // currentRowChanged(int) is also triggered when updating the listwidget
1743 // block signals to avoid unnecessary calls to switchConverter()
1744 convertersLW->blockSignals(true);
1745 convertersLW->clear();
1747 for (Converter const & c : form_->converters()) {
1748 QString const name =
1750 .arg(toqstr(translateIfPossible(c.From()->prettyname())))
1751 .arg(toqstr(translateIfPossible(c.To()->prettyname())));
1752 int type = form_->converters().getNumber(c.From()->name(),
1754 new QListWidgetItem(name, convertersLW, type);
1756 convertersLW->sortItems(Qt::AscendingOrder);
1757 convertersLW->blockSignals(false);
1759 // restore selection
1760 if (current != pattern.arg(QString()).arg(QString())) {
1761 QList<QListWidgetItem *> const item =
1762 convertersLW->findItems(current, Qt::MatchExactly);
1763 if (!item.isEmpty())
1764 convertersLW->setCurrentItem(item.at(0));
1767 // select first element if restoring failed
1768 if (convertersLW->currentRow() == -1)
1769 convertersLW->setCurrentRow(0);
1775 void PrefConverters::switchConverter()
1777 int const cnr = convertersLW->currentItem()->type();
1778 Converter const & c(form_->converters().get(cnr));
1779 converterFromCO->setCurrentIndex(form_->formats().getNumber(c.from()));
1780 converterToCO->setCurrentIndex(form_->formats().getNumber(c.to()));
1781 converterED->setText(toqstr(c.command()));
1782 converterFlagED->setText(toqstr(c.flags()));
1788 void PrefConverters::changeConverter()
1794 void PrefConverters::updateButtons()
1796 if (form_->formats().empty())
1798 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1799 Format const & to = form_->formats().get(converterToCO->currentIndex());
1800 int const sel = form_->converters().getNumber(from.name(), to.name());
1801 bool const known = sel >= 0;
1802 bool const valid = !(converterED->text().isEmpty()
1803 || from.name() == to.name());
1808 if (convertersLW->count() > 0) {
1809 int const cnr = convertersLW->currentItem()->type();
1810 Converter const & c = form_->converters().get(cnr);
1811 old_command = c.command();
1812 old_flag = c.flags();
1815 string const new_command = fromqstr(converterED->text());
1816 string const new_flag = fromqstr(converterFlagED->text());
1818 bool modified = (old_command != new_command || old_flag != new_flag);
1820 converterModifyPB->setEnabled(valid && known && modified);
1821 converterNewPB->setEnabled(valid && !known);
1822 converterRemovePB->setEnabled(known);
1824 maxAgeLE->setEnabled(cacheCB->isChecked());
1825 maxAgeLA->setEnabled(cacheCB->isChecked());
1830 // specify unique from/to or it doesn't appear. This is really bad UI
1831 // this is why we can use the same function for both new and modify
1832 void PrefConverters::updateConverter()
1834 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1835 Format const & to = form_->formats().get(converterToCO->currentIndex());
1836 string const flags = fromqstr(converterFlagED->text());
1837 string const command = fromqstr(converterED->text());
1839 Converter const * old =
1840 form_->converters().getConverter(from.name(), to.name());
1841 form_->converters().add(from.name(), to.name(), command, flags);
1844 form_->converters().updateLast(form_->formats());
1848 // Remove all files created by this converter from the cache, since
1849 // the modified converter might create different files.
1850 ConverterCache::get().remove_all(from.name(), to.name());
1854 void PrefConverters::removeConverter()
1856 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1857 Format const & to = form_->formats().get(converterToCO->currentIndex());
1858 form_->converters().erase(from.name(), to.name());
1862 // Remove all files created by this converter from the cache, since
1863 // a possible new converter might create different files.
1864 ConverterCache::get().remove_all(from.name(), to.name());
1868 void PrefConverters::on_cacheCB_stateChanged(int state)
1870 maxAgeLE->setEnabled(state == Qt::Checked);
1871 maxAgeLA->setEnabled(state == Qt::Checked);
1876 void PrefConverters::on_needauthForbiddenCB_toggled(bool checked)
1878 needauthCB->setEnabled(!checked);
1882 void PrefConverters::on_needauthCB_toggled(bool checked)
1889 int ret = frontend::Alert::prompt(
1890 _("SECURITY WARNING!"), _("Unchecking this option has the effect that potentially harmful converters would be run without asking your permission first. This is UNSAFE and NOT recommended, unless you know what you are doing. Are you sure you would like to proceed ? The recommended and safe answer is NO!"),
1891 0, 0, _("&No"), _("&Yes"));
1895 setCheckboxBlockSignals(needauthCB, true);
1899 /////////////////////////////////////////////////////////////////////
1903 /////////////////////////////////////////////////////////////////////
1905 class FormatValidator : public QValidator
1908 FormatValidator(QWidget *, Formats const & f);
1909 void fixup(QString & input) const override;
1910 QValidator::State validate(QString & input, int & pos) const override;
1912 virtual QString toString(Format const & format) const = 0;
1914 Formats const & formats_;
1918 FormatValidator::FormatValidator(QWidget * parent, Formats const & f)
1919 : QValidator(parent), formats_(f)
1924 void FormatValidator::fixup(QString & input) const
1926 Formats::const_iterator cit = formats_.begin();
1927 Formats::const_iterator end = formats_.end();
1928 for (; cit != end; ++cit) {
1929 QString const name = toString(*cit);
1930 if (distance(formats_.begin(), cit) == nr()) {
1938 QValidator::State FormatValidator::validate(QString & input, int & /*pos*/) const
1940 Formats::const_iterator cit = formats_.begin();
1941 Formats::const_iterator end = formats_.end();
1942 bool unknown = true;
1943 for (; unknown && cit != end; ++cit) {
1944 QString const name = toString(*cit);
1945 if (distance(formats_.begin(), cit) != nr())
1946 unknown = name != input;
1949 if (unknown && !input.isEmpty())
1950 return QValidator::Acceptable;
1952 return QValidator::Intermediate;
1956 int FormatValidator::nr() const
1958 QComboBox * p = qobject_cast<QComboBox *>(parent());
1959 return p->itemData(p->currentIndex()).toInt();
1963 /////////////////////////////////////////////////////////////////////
1965 // FormatNameValidator
1967 /////////////////////////////////////////////////////////////////////
1969 class FormatNameValidator : public FormatValidator
1972 FormatNameValidator(QWidget * parent, Formats const & f)
1973 : FormatValidator(parent, f)
1976 QString toString(Format const & format) const override
1978 return toqstr(format.name());
1983 /////////////////////////////////////////////////////////////////////
1985 // FormatPrettynameValidator
1987 /////////////////////////////////////////////////////////////////////
1989 class FormatPrettynameValidator : public FormatValidator
1992 FormatPrettynameValidator(QWidget * parent, Formats const & f)
1993 : FormatValidator(parent, f)
1996 QString toString(Format const & format) const override
1998 return toqstr(translateIfPossible(format.prettyname()));
2003 /////////////////////////////////////////////////////////////////////
2007 /////////////////////////////////////////////////////////////////////
2009 PrefFileformats::PrefFileformats(GuiPreferences * form)
2010 : PrefModule(catFiles, N_("File Formats"), form)
2014 formatED->setValidator(new FormatNameValidator(formatsCB, form_->formats()));
2015 formatsCB->setValidator(new FormatPrettynameValidator(formatsCB, form_->formats()));
2016 extensionsED->setValidator(new NoNewLineValidator(extensionsED));
2017 shortcutED->setValidator(new NoNewLineValidator(shortcutED));
2018 editorED->setValidator(new NoNewLineValidator(editorED));
2019 viewerED->setValidator(new NoNewLineValidator(viewerED));
2020 copierED->setValidator(new NoNewLineValidator(copierED));
2022 connect(documentCB, SIGNAL(clicked()),
2023 this, SLOT(setFlags()));
2024 connect(vectorCB, SIGNAL(clicked()),
2025 this, SLOT(setFlags()));
2026 connect(exportMenuCB, SIGNAL(clicked()),
2027 this, SLOT(setFlags()));
2028 connect(formatsCB->lineEdit(), SIGNAL(editingFinished()),
2029 this, SLOT(updatePrettyname()));
2030 connect(formatsCB->lineEdit(), SIGNAL(textEdited(QString)),
2031 this, SIGNAL(changed()));
2032 #if QT_VERSION < 0x050e00
2033 connect(defaultFormatCB, SIGNAL(activated(QString)),
2034 this, SIGNAL(changed()));
2035 connect(defaultOTFFormatCB, SIGNAL(activated(QString)),
2036 this, SIGNAL(changed()));
2037 connect(defaultPlatexFormatCB, SIGNAL(activated(QString)),
2038 this, SIGNAL(changed()));
2040 connect(defaultFormatCB, SIGNAL(textActivated(QString)),
2041 this, SIGNAL(changed()));
2042 connect(defaultOTFFormatCB, SIGNAL(textActivated(QString)),
2043 this, SIGNAL(changed()));
2044 connect(defaultPlatexFormatCB, SIGNAL(textActivated(QString)),
2045 this, SIGNAL(changed()));
2047 connect(viewerCO, SIGNAL(activated(int)),
2048 this, SIGNAL(changed()));
2049 connect(editorCO, SIGNAL(activated(int)),
2050 this, SIGNAL(changed()));
2056 string const l10n_shortcut(docstring const & prettyname, string const & shortcut)
2058 if (shortcut.empty())
2061 string l10n_format =
2062 to_utf8(_(to_utf8(prettyname) + '|' + shortcut));
2063 return split(l10n_format, '|');
2069 void PrefFileformats::applyRC(LyXRC & rc) const
2071 QString const default_format = defaultFormatCB->itemData(
2072 defaultFormatCB->currentIndex()).toString();
2073 rc.default_view_format = fromqstr(default_format);
2074 QString const default_otf_format = defaultOTFFormatCB->itemData(
2075 defaultOTFFormatCB->currentIndex()).toString();
2076 rc.default_otf_view_format = fromqstr(default_otf_format);
2077 QString const default_platex_format = defaultPlatexFormatCB->itemData(
2078 defaultPlatexFormatCB->currentIndex()).toString();
2079 rc.default_platex_view_format = fromqstr(default_platex_format);
2083 void PrefFileformats::updateRC(LyXRC const & rc)
2085 viewer_alternatives = rc.viewer_alternatives;
2086 editor_alternatives = rc.editor_alternatives;
2087 bool const init = defaultFormatCB->currentText().isEmpty();
2091 defaultFormatCB->findData(toqstr(rc.default_view_format));
2092 defaultFormatCB->setCurrentIndex(pos);
2093 pos = defaultOTFFormatCB->findData(toqstr(rc.default_otf_view_format));
2094 defaultOTFFormatCB->setCurrentIndex(pos);
2095 defaultOTFFormatCB->setCurrentIndex(pos);
2096 pos = defaultPlatexFormatCB->findData(toqstr(rc.default_platex_view_format));
2097 defaultPlatexFormatCB->setCurrentIndex(pos);
2098 defaultPlatexFormatCB->setCurrentIndex(pos);
2103 void PrefFileformats::updateView()
2105 QString const current = formatsCB->currentText();
2106 QString const current_def = defaultFormatCB->currentText();
2107 QString const current_def_otf = defaultOTFFormatCB->currentText();
2108 QString const current_def_platex = defaultPlatexFormatCB->currentText();
2110 // update comboboxes with formats
2111 formatsCB->blockSignals(true);
2112 defaultFormatCB->blockSignals(true);
2113 defaultOTFFormatCB->blockSignals(true);
2114 defaultPlatexFormatCB->blockSignals(true);
2116 defaultFormatCB->clear();
2117 defaultOTFFormatCB->clear();
2118 defaultPlatexFormatCB->clear();
2119 form_->formats().sort();
2120 for (Format const & f : form_->formats()) {
2121 QString const prettyname = toqstr(translateIfPossible(f.prettyname()));
2122 formatsCB->addItem(prettyname,
2123 QVariant(form_->formats().getNumber(f.name())));
2124 if (f.viewer().empty())
2126 if (form_->converters().isReachable("xhtml", f.name())
2127 || form_->converters().isReachable("dviluatex", f.name())
2128 || form_->converters().isReachable("luatex", f.name())
2129 || form_->converters().isReachable("xetex", f.name())) {
2130 defaultFormatCB->addItem(prettyname,
2131 QVariant(toqstr(f.name())));
2132 defaultOTFFormatCB->addItem(prettyname,
2133 QVariant(toqstr(f.name())));
2135 if (form_->converters().isReachable("latex", f.name())
2136 || form_->converters().isReachable("pdflatex", f.name()))
2137 defaultFormatCB->addItem(prettyname,
2138 QVariant(toqstr(f.name())));
2139 if (form_->converters().isReachable("platex", f.name()))
2140 defaultPlatexFormatCB->addItem(prettyname,
2141 QVariant(toqstr(f.name())));
2145 // restore selections
2146 int item = formatsCB->findText(current, Qt::MatchExactly);
2147 formatsCB->setCurrentIndex(item < 0 ? 0 : item);
2148 on_formatsCB_currentIndexChanged(item < 0 ? 0 : item);
2149 item = defaultFormatCB->findText(current_def, Qt::MatchExactly);
2150 defaultFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2151 item = defaultOTFFormatCB->findText(current_def_otf, Qt::MatchExactly);
2152 defaultOTFFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2153 item = defaultPlatexFormatCB->findText(current_def_platex, Qt::MatchExactly);
2154 defaultPlatexFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2155 formatsCB->blockSignals(false);
2156 defaultFormatCB->blockSignals(false);
2157 defaultOTFFormatCB->blockSignals(false);
2158 defaultPlatexFormatCB->blockSignals(false);
2162 void PrefFileformats::on_formatsCB_currentIndexChanged(int i)
2164 if (form_->formats().empty())
2166 int const nr = formatsCB->itemData(i).toInt();
2167 Format const f = form_->formats().get(nr);
2169 formatED->setText(toqstr(f.name()));
2170 copierED->setText(toqstr(form_->movers().command(f.name())));
2171 extensionsED->setText(toqstr(f.extensions()));
2172 mimeED->setText(toqstr(f.mime()));
2173 shortcutED->setText(
2174 toqstr(l10n_shortcut(f.prettyname(), f.shortcut())));
2175 documentCB->setChecked((f.documentFormat()));
2176 vectorCB->setChecked((f.vectorFormat()));
2177 exportMenuCB->setChecked((f.inExportMenu()));
2178 exportMenuCB->setEnabled((f.documentFormat()));
2184 void PrefFileformats::setFlags()
2186 int flags = Format::none;
2187 if (documentCB->isChecked())
2188 flags |= Format::document;
2189 if (vectorCB->isChecked())
2190 flags |= Format::vector;
2191 if (exportMenuCB->isChecked())
2192 flags |= Format::export_menu;
2193 currentFormat().setFlags(flags);
2194 exportMenuCB->setEnabled(documentCB->isChecked());
2199 void PrefFileformats::on_copierED_textEdited(const QString & s)
2201 string const fmt = fromqstr(formatED->text());
2202 form_->movers().set(fmt, fromqstr(s));
2207 void PrefFileformats::on_extensionsED_textEdited(const QString & s)
2209 currentFormat().setExtensions(fromqstr(s));
2214 void PrefFileformats::on_viewerED_textEdited(const QString & s)
2216 currentFormat().setViewer(fromqstr(s));
2221 void PrefFileformats::on_editorED_textEdited(const QString & s)
2223 currentFormat().setEditor(fromqstr(s));
2228 void PrefFileformats::on_mimeED_textEdited(const QString & s)
2230 currentFormat().setMime(fromqstr(s));
2235 void PrefFileformats::on_shortcutED_textEdited(const QString & s)
2237 string const new_shortcut = fromqstr(s);
2238 if (new_shortcut == l10n_shortcut(currentFormat().prettyname(),
2239 currentFormat().shortcut()))
2241 currentFormat().setShortcut(new_shortcut);
2246 void PrefFileformats::on_formatED_editingFinished()
2248 string const newname = fromqstr(formatED->displayText());
2249 string const oldname = currentFormat().name();
2250 if (newname == oldname)
2252 if (form_->converters().formatIsUsed(oldname)) {
2253 Alert::error(_("Format in use"),
2254 _("You cannot change a format's short name "
2255 "if the format is used by a converter. "
2256 "Please remove the converter first."));
2261 currentFormat().setName(newname);
2266 void PrefFileformats::on_formatED_textChanged(const QString &)
2268 QString t = formatED->text();
2270 bool valid = formatED->validator()->validate(t, p) == QValidator::Acceptable;
2271 setValid(formatLA, valid);
2275 void PrefFileformats::on_formatsCB_editTextChanged(const QString &)
2277 QString t = formatsCB->currentText();
2279 bool valid = formatsCB->validator()->validate(t, p) == QValidator::Acceptable;
2280 setValid(formatsLA, valid);
2284 void PrefFileformats::updatePrettyname()
2286 QString const newname = formatsCB->currentText();
2287 if (newname == toqstr(translateIfPossible(currentFormat().prettyname())))
2290 currentFormat().setPrettyname(qstring_to_ucs4(newname));
2298 void updateComboBox(LyXRC::Alternatives const & alts,
2299 string const & fmt, QComboBox * combo)
2301 LyXRC::Alternatives::const_iterator it =
2303 if (it != alts.end()) {
2304 LyXRC::CommandSet const & cmds = it->second;
2305 LyXRC::CommandSet::const_iterator sit =
2307 LyXRC::CommandSet::const_iterator const sen =
2309 for (; sit != sen; ++sit) {
2310 QString const qcmd = toqstr(*sit);
2311 combo->addItem(qcmd, qcmd);
2318 void PrefFileformats::updateViewers()
2320 Format const f = currentFormat();
2321 viewerCO->blockSignals(true);
2323 viewerCO->addItem(qt_("None"), QString());
2324 updateComboBox(viewer_alternatives, f.name(), viewerCO);
2325 viewerCO->addItem(qt_("Custom"), QString("custom viewer"));
2326 viewerCO->blockSignals(false);
2328 int pos = viewerCO->findData(toqstr(f.viewer()));
2331 viewerED->setEnabled(false);
2332 viewerCO->setCurrentIndex(pos);
2334 viewerED->setEnabled(true);
2335 viewerED->setText(toqstr(f.viewer()));
2336 viewerCO->setCurrentIndex(viewerCO->findData(toqstr("custom viewer")));
2341 void PrefFileformats::updateEditors()
2343 Format const f = currentFormat();
2344 editorCO->blockSignals(true);
2346 editorCO->addItem(qt_("None"), QString());
2347 updateComboBox(editor_alternatives, f.name(), editorCO);
2348 editorCO->addItem(qt_("Custom"), QString("custom editor"));
2349 editorCO->blockSignals(false);
2351 int pos = editorCO->findData(toqstr(f.editor()));
2354 editorED->setEnabled(false);
2355 editorCO->setCurrentIndex(pos);
2357 editorED->setEnabled(true);
2358 editorED->setText(toqstr(f.editor()));
2359 editorCO->setCurrentIndex(editorCO->findData(toqstr("custom editor")));
2364 void PrefFileformats::on_viewerCO_currentIndexChanged(int i)
2366 bool const custom = viewerCO->itemData(i).toString() == "custom viewer";
2367 viewerED->setEnabled(custom);
2369 currentFormat().setViewer(fromqstr(viewerCO->itemData(i).toString()));
2373 void PrefFileformats::on_editorCO_currentIndexChanged(int i)
2375 bool const custom = editorCO->itemData(i).toString() == "custom editor";
2376 editorED->setEnabled(custom);
2378 currentFormat().setEditor(fromqstr(editorCO->itemData(i).toString()));
2382 Format & PrefFileformats::currentFormat()
2384 int const i = formatsCB->currentIndex();
2385 int const nr = formatsCB->itemData(i).toInt();
2386 return form_->formats().get(nr);
2390 void PrefFileformats::on_formatNewPB_clicked()
2392 form_->formats().add("", "", docstring(), "", "", "", "", Format::none);
2394 formatsCB->setCurrentIndex(0);
2395 formatsCB->setFocus(Qt::OtherFocusReason);
2399 void PrefFileformats::on_formatRemovePB_clicked()
2401 int const i = formatsCB->currentIndex();
2402 int const nr = formatsCB->itemData(i).toInt();
2403 string const current_text = form_->formats().get(nr).name();
2404 if (form_->converters().formatIsUsed(current_text)) {
2405 Alert::error(_("Format in use"),
2406 _("Cannot remove a Format used by a Converter. "
2407 "Remove the converter first."));
2411 form_->formats().erase(current_text);
2414 on_formatsCB_editTextChanged(formatsCB->currentText());
2419 /////////////////////////////////////////////////////////////////////
2423 /////////////////////////////////////////////////////////////////////
2425 PrefLanguage::PrefLanguage(GuiPreferences * form)
2426 : PrefModule(catLanguage, N_("Language"), form)
2430 connect(visualCursorRB, SIGNAL(clicked()),
2431 this, SIGNAL(changed()));
2432 connect(logicalCursorRB, SIGNAL(clicked()),
2433 this, SIGNAL(changed()));
2434 connect(markForeignCB, SIGNAL(clicked()),
2435 this, SIGNAL(changed()));
2436 connect(respectOSkbdCB, SIGNAL(clicked()),
2437 this, SIGNAL(changed()));
2438 connect(explicitDocLangBeginCB, SIGNAL(clicked()),
2439 this, SIGNAL(changed()));
2440 connect(explicitDocLangEndCB, SIGNAL(clicked()),
2441 this, SIGNAL(changed()));
2442 connect(languagePackageCO, SIGNAL(activated(int)),
2443 this, SIGNAL(changed()));
2444 connect(languagePackageED, SIGNAL(textChanged(QString)),
2445 this, SIGNAL(changed()));
2446 connect(globalCB, SIGNAL(clicked()),
2447 this, SIGNAL(changed()));
2448 connect(startCommandED, SIGNAL(textChanged(QString)),
2449 this, SIGNAL(changed()));
2450 connect(endCommandED, SIGNAL(textChanged(QString)),
2451 this, SIGNAL(changed()));
2452 connect(uiLanguageCO, SIGNAL(activated(int)),
2453 this, SIGNAL(changed()));
2454 connect(defaultDecimalSepED, SIGNAL(textChanged(QString)),
2455 this, SIGNAL(changed()));
2456 connect(defaultDecimalSepCO, SIGNAL(activated(int)),
2457 this, SIGNAL(changed()));
2458 connect(defaultLengthUnitCO, SIGNAL(activated(int)),
2459 this, SIGNAL(changed()));
2461 languagePackageED->setValidator(new NoNewLineValidator(languagePackageED));
2462 startCommandED->setValidator(new NoNewLineValidator(startCommandED));
2463 endCommandED->setValidator(new NoNewLineValidator(endCommandED));
2465 #if QT_VERSION < 0x060000
2466 defaultDecimalSepED->setValidator(new QRegExpValidator(QRegExp("\\S"), this));
2468 defaultDecimalSepED->setValidator(new QRegularExpressionValidator(QRegularExpression("\\S"), this));
2470 defaultDecimalSepED->setMaxLength(1);
2472 defaultLengthUnitCO->addItem(lyx::qt_(unit_name_gui[Length::CM]), Length::CM);
2473 defaultLengthUnitCO->addItem(lyx::qt_(unit_name_gui[Length::IN]), Length::IN);
2475 QAbstractItemModel * language_model = guiApp->languageModel();
2476 language_model->sort(0);
2477 uiLanguageCO->blockSignals(true);
2478 uiLanguageCO->clear();
2479 uiLanguageCO->addItem(qt_("Default"), toqstr("auto"));
2480 for (int i = 0; i != language_model->rowCount(); ++i) {
2481 QModelIndex index = language_model->index(i, 0);
2482 // Filter the list based on the available translation and add
2483 // each language code only once
2484 string const name = fromqstr(index.data(Qt::UserRole).toString());
2485 Language const * lang = languages.getLanguage(name);
2488 // never remove the currently selected language
2489 if (name != form->rc().gui_language
2490 && name != lyxrc.gui_language
2491 && (!Messages::available(lang->code())
2492 || !lang->hasGuiSupport()))
2494 uiLanguageCO->addItem(index.data(Qt::DisplayRole).toString(),
2495 index.data(Qt::UserRole).toString());
2497 uiLanguageCO->blockSignals(false);
2499 // FIXME: restore this when it works (see discussion in #6450).
2500 respectOSkbdCB->hide();
2504 void PrefLanguage::on_uiLanguageCO_currentIndexChanged(int)
2506 QMessageBox::information(this, qt_("LyX needs to be restarted!"),
2507 qt_("The change of user interface language will be fully "
2508 "effective only after a restart."));
2512 void PrefLanguage::on_languagePackageCO_currentIndexChanged(int i)
2515 languagePackageED->setText(save_langpack_);
2516 else if (!languagePackageED->text().isEmpty()) {
2517 save_langpack_ = languagePackageED->text();
2518 languagePackageED->clear();
2520 languagePackageED->setEnabled(i == 2);
2524 void PrefLanguage::on_defaultDecimalSepCO_currentIndexChanged(int i)
2526 defaultDecimalSepED->setEnabled(i == 1);
2530 void PrefLanguage::applyRC(LyXRC & rc) const
2532 rc.visual_cursor = visualCursorRB->isChecked();
2533 rc.mark_foreign_language = markForeignCB->isChecked();
2534 rc.respect_os_kbd_language = respectOSkbdCB->isChecked();
2535 rc.language_auto_begin = !explicitDocLangBeginCB->isChecked();
2536 rc.language_auto_end = !explicitDocLangEndCB->isChecked();
2537 int const p = languagePackageCO->currentIndex();
2539 rc.language_package_selection = LyXRC::LP_AUTO;
2541 rc.language_package_selection = LyXRC::LP_BABEL;
2543 rc.language_package_selection = LyXRC::LP_CUSTOM;
2545 rc.language_package_selection = LyXRC::LP_NONE;
2546 rc.language_custom_package = fromqstr(languagePackageED->text());
2547 rc.language_global_options = globalCB->isChecked();
2548 rc.language_command_begin = fromqstr(startCommandED->text());
2549 rc.language_command_end = fromqstr(endCommandED->text());
2550 rc.gui_language = fromqstr(
2551 uiLanguageCO->itemData(uiLanguageCO->currentIndex()).toString());
2552 if (defaultDecimalSepCO->currentIndex() == 0)
2553 rc.default_decimal_sep = "locale";
2555 rc.default_decimal_sep = fromqstr(defaultDecimalSepED->text());
2556 rc.default_length_unit = (Length::UNIT) defaultLengthUnitCO->itemData(defaultLengthUnitCO->currentIndex()).toInt();
2560 void PrefLanguage::updateRC(LyXRC const & rc)
2562 if (rc.visual_cursor)
2563 visualCursorRB->setChecked(true);
2565 logicalCursorRB->setChecked(true);
2566 markForeignCB->setChecked(rc.mark_foreign_language);
2567 respectOSkbdCB->setChecked(rc.respect_os_kbd_language);
2568 explicitDocLangBeginCB->setChecked(!rc.language_auto_begin);
2569 explicitDocLangEndCB->setChecked(!rc.language_auto_end);
2570 languagePackageCO->setCurrentIndex(rc.language_package_selection);
2571 if (languagePackageCO->currentIndex() == 2) {
2572 languagePackageED->setText(toqstr(rc.language_custom_package));
2573 languagePackageED->setEnabled(true);
2575 languagePackageED->clear();
2576 save_langpack_ = toqstr(rc.language_custom_package);
2577 languagePackageED->setEnabled(false);
2579 defaultDecimalSepED->setEnabled(defaultDecimalSepCO->currentIndex() == 1);
2580 globalCB->setChecked(rc.language_global_options);
2581 startCommandED->setText(toqstr(rc.language_command_begin));
2582 endCommandED->setText(toqstr(rc.language_command_end));
2583 if (rc.default_decimal_sep == "locale") {
2584 defaultDecimalSepCO->setCurrentIndex(0);
2585 defaultDecimalSepED->clear();
2587 defaultDecimalSepCO->setCurrentIndex(1);
2588 defaultDecimalSepED->setText(toqstr(rc.default_decimal_sep));
2590 int pos = defaultLengthUnitCO->findData(int(rc.default_length_unit));
2591 defaultLengthUnitCO->setCurrentIndex(pos);
2593 pos = uiLanguageCO->findData(toqstr(rc.gui_language));
2594 uiLanguageCO->blockSignals(true);
2595 uiLanguageCO->setCurrentIndex(pos);
2596 uiLanguageCO->blockSignals(false);
2600 /////////////////////////////////////////////////////////////////////
2602 // PrefUserInterface
2604 /////////////////////////////////////////////////////////////////////
2606 PrefUserInterface::PrefUserInterface(GuiPreferences * form)
2607 : PrefModule(catLookAndFeel, N_("User Interface"), form)
2611 connect(uiFilePB, SIGNAL(clicked()),
2612 this, SLOT(selectUi()));
2613 connect(uiFileED, SIGNAL(textChanged(QString)),
2614 this, SIGNAL(changed()));
2615 connect(iconSetCO, SIGNAL(activated(int)),
2616 this, SIGNAL(changed()));
2617 connect(useSystemThemeIconsCB, SIGNAL(clicked()),
2618 this, SIGNAL(changed()));
2619 connect(lastfilesSB, SIGNAL(valueChanged(int)),
2620 this, SIGNAL(changed()));
2621 connect(tooltipCB, SIGNAL(toggled(bool)),
2622 this, SIGNAL(changed()));
2623 lastfilesSB->setMaximum(maxlastfiles);
2625 iconSetCO->addItem(qt_("Default"), QString());
2626 iconSetCO->addItem(qt_("Classic"), "classic");
2627 iconSetCO->addItem(qt_("Oxygen"), "oxygen");
2629 #if QT_VERSION >= 0x040600
2630 if (guiApp->platformName() != "qt4x11"
2631 && guiApp->platformName() != "xcb"
2632 && !guiApp->platformName().contains("wayland"))
2634 useSystemThemeIconsCB->hide();
2638 void PrefUserInterface::applyRC(LyXRC & rc) const
2640 rc.icon_set = fromqstr(iconSetCO->itemData(
2641 iconSetCO->currentIndex()).toString());
2643 rc.ui_file = internal_path(fromqstr(uiFileED->text()));
2644 rc.use_system_theme_icons = useSystemThemeIconsCB->isChecked();
2645 rc.num_lastfiles = lastfilesSB->value();
2646 rc.use_tooltip = tooltipCB->isChecked();
2650 void PrefUserInterface::updateRC(LyXRC const & rc)
2652 int iconset = iconSetCO->findData(toqstr(rc.icon_set));
2655 iconSetCO->setCurrentIndex(iconset);
2656 useSystemThemeIconsCB->setChecked(rc.use_system_theme_icons);
2657 uiFileED->setText(toqstr(external_path(rc.ui_file)));
2658 lastfilesSB->setValue(rc.num_lastfiles);
2659 tooltipCB->setChecked(rc.use_tooltip);
2663 void PrefUserInterface::selectUi()
2665 QString file = form_->browseUI(internalPath(uiFileED->text()));
2666 if (!file.isEmpty())
2667 uiFileED->setText(file);
2671 /////////////////////////////////////////////////////////////////////
2673 // PrefDocumentHandling
2675 /////////////////////////////////////////////////////////////////////
2677 PrefDocHandling::PrefDocHandling(GuiPreferences * form)
2678 : PrefModule(catLookAndFeel, N_("Document Handling"), form)
2682 connect(autoSaveCB, SIGNAL(toggled(bool)),
2683 autoSaveSB, SLOT(setEnabled(bool)));
2684 connect(autoSaveCB, SIGNAL(toggled(bool)),
2685 TextLabel1, SLOT(setEnabled(bool)));
2686 connect(openDocumentsInTabsCB, SIGNAL(clicked()),
2687 this, SIGNAL(changed()));
2688 connect(singleInstanceCB, SIGNAL(clicked()),
2689 this, SIGNAL(changed()));
2690 connect(singleCloseTabButtonCB, SIGNAL(clicked()),
2691 this, SIGNAL(changed()));
2692 connect(closeLastViewCO, SIGNAL(activated(int)),
2693 this, SIGNAL(changed()));
2694 connect(restoreCursorCB, SIGNAL(clicked()),
2695 this, SIGNAL(changed()));
2696 connect(loadSessionCB, SIGNAL(clicked()),
2697 this, SIGNAL(changed()));
2698 connect(allowGeometrySessionCB, SIGNAL(clicked()),
2699 this, SIGNAL(changed()));
2700 connect(autoSaveSB, SIGNAL(valueChanged(int)),
2701 this, SIGNAL(changed()));
2702 connect(autoSaveCB, SIGNAL(clicked()),
2703 this, SIGNAL(changed()));
2704 connect(backupCB, SIGNAL(clicked()),
2705 this, SIGNAL(changed()));
2706 connect(saveCompressedCB, SIGNAL(clicked()),
2707 this, SIGNAL(changed()));
2708 connect(saveOriginCB, SIGNAL(clicked()),
2709 this, SIGNAL(changed()));
2713 void PrefDocHandling::applyRC(LyXRC & rc) const
2715 rc.use_lastfilepos = restoreCursorCB->isChecked();
2716 rc.load_session = loadSessionCB->isChecked();
2717 rc.allow_geometry_session = allowGeometrySessionCB->isChecked();
2718 rc.autosave = autoSaveCB->isChecked() ? autoSaveSB->value() * 60 : 0;
2719 rc.make_backup = backupCB->isChecked();
2720 rc.save_compressed = saveCompressedCB->isChecked();
2721 rc.save_origin = saveOriginCB->isChecked();
2722 rc.open_buffers_in_tabs = openDocumentsInTabsCB->isChecked();
2723 rc.single_instance = singleInstanceCB->isChecked();
2724 rc.single_close_tab_button = singleCloseTabButtonCB->isChecked();
2726 switch (closeLastViewCO->currentIndex()) {
2728 rc.close_buffer_with_last_view = "yes";
2731 rc.close_buffer_with_last_view = "no";
2734 rc.close_buffer_with_last_view = "ask";
2742 void PrefDocHandling::updateRC(LyXRC const & rc)
2744 restoreCursorCB->setChecked(rc.use_lastfilepos);
2745 loadSessionCB->setChecked(rc.load_session);
2746 allowGeometrySessionCB->setChecked(rc.allow_geometry_session);
2747 // convert to minutes
2748 bool autosave = rc.autosave > 0;
2749 int mins = rc.autosave / 60;
2752 autoSaveSB->setValue(mins);
2753 autoSaveCB->setChecked(autosave);
2754 autoSaveSB->setEnabled(autosave);
2755 backupCB->setChecked(rc.make_backup);
2756 saveCompressedCB->setChecked(rc.save_compressed);
2757 saveOriginCB->setChecked(rc.save_origin);
2758 openDocumentsInTabsCB->setChecked(rc.open_buffers_in_tabs);
2759 singleInstanceCB->setChecked(rc.single_instance && !rc.lyxpipes.empty());
2760 singleInstanceCB->setEnabled(!rc.lyxpipes.empty());
2761 singleCloseTabButtonCB->setChecked(rc.single_close_tab_button);
2762 if (rc.close_buffer_with_last_view == "yes")
2763 closeLastViewCO->setCurrentIndex(0);
2764 else if (rc.close_buffer_with_last_view == "no")
2765 closeLastViewCO->setCurrentIndex(1);
2766 else if (rc.close_buffer_with_last_view == "ask")
2767 closeLastViewCO->setCurrentIndex(2);
2771 void PrefDocHandling::on_clearSessionPB_clicked()
2773 guiApp->clearSession();
2778 /////////////////////////////////////////////////////////////////////
2782 /////////////////////////////////////////////////////////////////////
2784 PrefEdit::PrefEdit(GuiPreferences * form)
2785 : PrefModule(catEditing, N_("Control"), form)
2789 connect(cursorFollowsCB, SIGNAL(clicked()),
2790 this, SIGNAL(changed()));
2791 connect(scrollBelowCB, SIGNAL(clicked()),
2792 this, SIGNAL(changed()));
2793 connect(macLikeCursorMovementCB, SIGNAL(clicked()),
2794 this, SIGNAL(changed()));
2795 connect(copyCTMarkupCB, SIGNAL(clicked()),
2796 this, SIGNAL(changed()));
2797 connect(sortEnvironmentsCB, SIGNAL(clicked()),
2798 this, SIGNAL(changed()));
2799 connect(groupEnvironmentsCB, SIGNAL(clicked()),
2800 this, SIGNAL(changed()));
2801 connect(macroEditStyleCO, SIGNAL(activated(int)),
2802 this, SIGNAL(changed()));
2803 connect(cursorWidthSB, SIGNAL(valueChanged(int)),
2804 this, SIGNAL(changed()));
2805 connect(citationSearchLE, SIGNAL(textChanged(QString)),
2806 this, SIGNAL(changed()));
2807 connect(fullscreenWidthSB, SIGNAL(valueChanged(int)),
2808 this, SIGNAL(changed()));
2809 connect(toggleTabbarCB, SIGNAL(toggled(bool)),
2810 this, SIGNAL(changed()));
2811 connect(toggleMenubarCB, SIGNAL(toggled(bool)),
2812 this, SIGNAL(changed()));
2813 connect(toggleScrollbarCB, SIGNAL(toggled(bool)),
2814 this, SIGNAL(changed()));
2815 connect(toggleStatusbarCB, SIGNAL(toggled(bool)),
2816 this, SIGNAL(changed()));
2817 connect(toggleToolbarsCB, SIGNAL(toggled(bool)),
2818 this, SIGNAL(changed()));
2822 void PrefEdit::on_fullscreenLimitCB_toggled(bool const state)
2824 fullscreenWidthSB->setEnabled(state);
2825 fullscreenWidthLA->setEnabled(state);
2830 void PrefEdit::on_citationSearchCB_toggled(bool const state)
2832 citationSearchLE->setEnabled(state);
2833 citationSearchLA->setEnabled(state);
2838 void PrefEdit::applyRC(LyXRC & rc) const
2840 rc.cursor_follows_scrollbar = cursorFollowsCB->isChecked();
2841 rc.scroll_below_document = scrollBelowCB->isChecked();
2842 rc.mac_like_cursor_movement = macLikeCursorMovementCB->isChecked();
2843 rc.ct_markup_copied = copyCTMarkupCB->isChecked();
2844 rc.sort_layouts = sortEnvironmentsCB->isChecked();
2845 rc.group_layouts = groupEnvironmentsCB->isChecked();
2846 switch (macroEditStyleCO->currentIndex()) {
2847 case 0: rc.macro_edit_style = LyXRC::MACRO_EDIT_INLINE_BOX; break;
2848 case 1: rc.macro_edit_style = LyXRC::MACRO_EDIT_INLINE; break;
2849 case 2: rc.macro_edit_style = LyXRC::MACRO_EDIT_LIST; break;
2851 rc.cursor_width = cursorWidthSB->value();
2852 rc.citation_search = citationSearchCB->isChecked();
2853 rc.citation_search_pattern = fromqstr(citationSearchLE->text());
2854 rc.full_screen_toolbars = toggleToolbarsCB->isChecked();
2855 rc.full_screen_scrollbar = toggleScrollbarCB->isChecked();
2856 rc.full_screen_statusbar = toggleStatusbarCB->isChecked();
2857 rc.full_screen_tabbar = toggleTabbarCB->isChecked();
2858 rc.full_screen_menubar = toggleMenubarCB->isChecked();
2859 rc.full_screen_width = fullscreenWidthSB->value();
2860 rc.full_screen_limit = fullscreenLimitCB->isChecked();
2864 void PrefEdit::updateRC(LyXRC const & rc)
2866 cursorFollowsCB->setChecked(rc.cursor_follows_scrollbar);
2867 scrollBelowCB->setChecked(rc.scroll_below_document);
2868 macLikeCursorMovementCB->setChecked(rc.mac_like_cursor_movement);
2869 copyCTMarkupCB->setChecked(rc.ct_markup_copied);
2870 sortEnvironmentsCB->setChecked(rc.sort_layouts);
2871 groupEnvironmentsCB->setChecked(rc.group_layouts);
2872 macroEditStyleCO->setCurrentIndex(rc.macro_edit_style);
2873 cursorWidthSB->setValue(rc.cursor_width);
2874 citationSearchCB->setChecked(rc.citation_search);
2875 citationSearchLE->setText(toqstr(rc.citation_search_pattern));
2876 citationSearchLE->setEnabled(rc.citation_search);
2877 citationSearchLA->setEnabled(rc.citation_search);
2878 toggleScrollbarCB->setChecked(rc.full_screen_scrollbar);
2879 toggleStatusbarCB->setChecked(rc.full_screen_statusbar);
2880 toggleToolbarsCB->setChecked(rc.full_screen_toolbars);
2881 toggleTabbarCB->setChecked(rc.full_screen_tabbar);
2882 toggleMenubarCB->setChecked(rc.full_screen_menubar);
2883 fullscreenWidthSB->setValue(rc.full_screen_width);
2884 fullscreenLimitCB->setChecked(rc.full_screen_limit);
2885 fullscreenWidthSB->setEnabled(rc.full_screen_limit);
2886 fullscreenWidthLA->setEnabled(rc.full_screen_limit);
2890 /////////////////////////////////////////////////////////////////////
2894 /////////////////////////////////////////////////////////////////////
2897 GuiShortcutDialog::GuiShortcutDialog(QWidget * parent) : QDialog(parent)
2899 Ui::shortcutUi::setupUi(this);
2900 QDialog::setModal(true);
2901 lfunLE->setValidator(new NoNewLineValidator(lfunLE));
2905 PrefShortcuts::PrefShortcuts(GuiPreferences * form)
2906 : PrefModule(catEditing, N_("Shortcuts"), form),
2907 editItem_(nullptr), mathItem_(nullptr), bufferItem_(nullptr), layoutItem_(nullptr),
2908 systemItem_(nullptr)
2912 shortcutsTW->setColumnCount(2);
2913 shortcutsTW->headerItem()->setText(0, qt_("Function"));
2914 shortcutsTW->headerItem()->setText(1, qt_("Shortcut"));
2915 shortcutsTW->setSortingEnabled(true);
2916 // Multi-selection can be annoying.
2917 // shortcutsTW->setSelectionMode(QAbstractItemView::MultiSelection);
2919 connect(bindFilePB, SIGNAL(clicked()),
2920 this, SLOT(selectBind()));
2921 connect(bindFileED, SIGNAL(textChanged(QString)),
2922 this, SIGNAL(changed()));
2924 shortcut_ = new GuiShortcutDialog(this);
2925 shortcut_bc_.setPolicy(ButtonPolicy::OkCancelPolicy);
2926 shortcut_bc_.setOK(shortcut_->buttonBox->button(QDialogButtonBox::Ok));
2927 shortcut_bc_.setCancel(shortcut_->buttonBox->button(QDialogButtonBox::Cancel));
2929 connect(shortcut_->buttonBox, SIGNAL(accepted()),
2930 this, SIGNAL(changed()));
2931 connect(shortcut_->buttonBox, SIGNAL(rejected()),
2932 shortcut_, SLOT(reject()));
2933 connect(shortcut_->clearPB, SIGNAL(clicked()),
2934 this, SLOT(shortcutClearPressed()));
2935 connect(shortcut_->removePB, SIGNAL(clicked()),
2936 this, SLOT(shortcutRemovePressed()));
2937 connect(shortcut_->buttonBox, SIGNAL(accepted()),
2938 this, SLOT(shortcutOkPressed()));
2939 connect(shortcut_->buttonBox, SIGNAL(rejected()),
2940 this, SLOT(shortcutCancelPressed()));
2944 void PrefShortcuts::applyRC(LyXRC & rc) const
2946 rc.bind_file = internal_path(fromqstr(bindFileED->text()));
2947 // write user_bind and user_unbind to .lyx/bind/user.bind
2948 FileName bind_dir(addPath(package().user_support().absFileName(), "bind"));
2949 if (!bind_dir.exists() && !bind_dir.createDirectory(0777)) {
2950 lyxerr << "LyX could not create the user bind directory '"
2951 << bind_dir << "'. All user-defined key bindings will be lost." << endl;
2954 if (!bind_dir.isDirWritable()) {
2955 lyxerr << "LyX could not write to the user bind directory '"
2956 << bind_dir << "'. All user-defined key bindings will be lost." << endl;
2959 FileName user_bind_file(bind_dir.absFileName() + "/user.bind");
2960 user_unbind_.write(user_bind_file.toFilesystemEncoding(), false, true);
2961 user_bind_.write(user_bind_file.toFilesystemEncoding(), true, false);
2962 // immediately apply the keybindings. Why this is not done before?
2963 // The good thing is that the menus are updated automatically.
2964 theTopLevelKeymap().clear();
2965 theTopLevelKeymap().read("site");
2966 theTopLevelKeymap().read(rc.bind_file, nullptr, KeyMap::Fallback);
2967 theTopLevelKeymap().read("user", nullptr, KeyMap::MissingOK);
2971 void PrefShortcuts::updateRC(LyXRC const & rc)
2973 bindFileED->setText(toqstr(external_path(rc.bind_file)));
2975 system_bind_.clear();
2977 user_unbind_.clear();
2978 system_bind_.read("site");
2979 system_bind_.read(rc.bind_file);
2980 // \unbind in user.bind is added to user_unbind_
2981 user_bind_.read("user", &user_unbind_, KeyMap::MissingOK);
2982 updateShortcutsTW();
2986 void PrefShortcuts::updateShortcutsTW()
2988 shortcutsTW->clear();
2990 editItem_ = new QTreeWidgetItem(shortcutsTW);
2991 editItem_->setText(0, qt_("Cursor, Mouse and Editing Functions"));
2992 editItem_->setFlags(editItem_->flags() & ~Qt::ItemIsSelectable);
2994 mathItem_ = new QTreeWidgetItem(shortcutsTW);
2995 mathItem_->setText(0, qt_("Mathematical Symbols"));
2996 mathItem_->setFlags(mathItem_->flags() & ~Qt::ItemIsSelectable);
2998 bufferItem_ = new QTreeWidgetItem(shortcutsTW);
2999 bufferItem_->setText(0, qt_("Document and Window"));
3000 bufferItem_->setFlags(bufferItem_->flags() & ~Qt::ItemIsSelectable);
3002 layoutItem_ = new QTreeWidgetItem(shortcutsTW);
3003 layoutItem_->setText(0, qt_("Font, Layouts and Textclasses"));
3004 layoutItem_->setFlags(layoutItem_->flags() & ~Qt::ItemIsSelectable);
3006 systemItem_ = new QTreeWidgetItem(shortcutsTW);
3007 systemItem_->setText(0, qt_("System and Miscellaneous"));
3008 systemItem_->setFlags(systemItem_->flags() & ~Qt::ItemIsSelectable);
3010 // listBindings(unbound=true) lists all bound and unbound lfuns
3011 // Items in this list is tagged by its source.
3012 KeyMap::BindingList bindinglist = system_bind_.listBindings(true,
3014 KeyMap::BindingList user_bindinglist = user_bind_.listBindings(false,
3016 KeyMap::BindingList user_unbindinglist = user_unbind_.listBindings(false,
3017 KeyMap::UserUnbind);
3018 bindinglist.insert(bindinglist.end(), user_bindinglist.begin(),
3019 user_bindinglist.end());
3020 bindinglist.insert(bindinglist.end(), user_unbindinglist.begin(),
3021 user_unbindinglist.end());
3023 KeyMap::BindingList::const_iterator it = bindinglist.begin();
3024 KeyMap::BindingList::const_iterator it_end = bindinglist.end();
3025 for (; it != it_end; ++it)
3026 insertShortcutItem(it->request, it->sequence, it->tag);
3028 shortcutsTW->sortItems(0, Qt::AscendingOrder);
3029 on_shortcutsTW_itemSelectionChanged();
3030 on_searchLE_textEdited();
3031 shortcutsTW->resizeColumnToContents(0);
3036 KeyMap::ItemType PrefShortcuts::itemType(QTreeWidgetItem & item)
3038 return static_cast<KeyMap::ItemType>(item.data(0, Qt::UserRole).toInt());
3043 bool PrefShortcuts::isAlwaysHidden(QTreeWidgetItem & item)
3045 // Hide rebound system settings that are empty
3046 return itemType(item) == KeyMap::UserUnbind && item.text(1).isEmpty();
3050 void PrefShortcuts::setItemType(QTreeWidgetItem * item, KeyMap::ItemType tag)
3052 item->setData(0, Qt::UserRole, QVariant(tag));
3056 case KeyMap::System:
3058 case KeyMap::UserBind:
3061 case KeyMap::UserUnbind:
3062 font.setStrikeOut(true);
3064 // this item is not displayed now.
3065 case KeyMap::UserExtraUnbind:
3066 font.setStrikeOut(true);
3069 item->setHidden(isAlwaysHidden(*item));
3070 item->setFont(1, font);
3074 QTreeWidgetItem * PrefShortcuts::insertShortcutItem(FuncRequest const & lfun,
3075 KeySequence const & seq, KeyMap::ItemType tag)
3077 FuncCode const action = lfun.action();
3078 string const action_name = lyxaction.getActionName(action);
3079 QString const lfun_name = toqstr(from_utf8(action_name)
3080 + ' ' + lfun.argument());
3081 QString const shortcut = toqstr(seq.print(KeySequence::ForGui));
3083 QTreeWidgetItem * newItem = nullptr;
3084 // for unbind items, try to find an existing item in the system bind list
3085 if (tag == KeyMap::UserUnbind) {
3086 QList<QTreeWidgetItem*> const items = shortcutsTW->findItems(lfun_name,
3087 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 0);
3088 for (auto const & item : items) {
3089 if (item->text(1) == shortcut) {
3094 // if not found, this unbind item is KeyMap::UserExtraUnbind
3095 // Such an item is not displayed to avoid confusion (what is
3096 // unmatched removed?).
3102 switch(lyxaction.getActionType(action)) {
3103 case LyXAction::Hidden:
3105 case LyXAction::Edit:
3106 newItem = new QTreeWidgetItem(editItem_);
3108 case LyXAction::Math:
3109 newItem = new QTreeWidgetItem(mathItem_);
3111 case LyXAction::Buffer:
3112 newItem = new QTreeWidgetItem(bufferItem_);
3114 case LyXAction::Layout:
3115 newItem = new QTreeWidgetItem(layoutItem_);
3117 case LyXAction::System:
3118 newItem = new QTreeWidgetItem(systemItem_);
3121 // this should not happen
3122 newItem = new QTreeWidgetItem(shortcutsTW);
3126 newItem->setText(0, lfun_name);
3127 newItem->setText(1, shortcut);
3128 // record BindFile representation to recover KeySequence when needed.
3129 newItem->setData(1, Qt::UserRole, toqstr(seq.print(KeySequence::BindFile)));
3130 setItemType(newItem, tag);
3135 void PrefShortcuts::on_shortcutsTW_itemSelectionChanged()
3137 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
3138 removePB->setEnabled(!items.isEmpty() && !items[0]->text(1).isEmpty());
3139 modifyPB->setEnabled(!items.isEmpty());
3140 if (items.isEmpty())
3143 if (itemType(*items[0]) == KeyMap::UserUnbind)
3144 removePB->setText(qt_("Res&tore"));
3146 removePB->setText(qt_("Remo&ve"));
3150 void PrefShortcuts::on_shortcutsTW_itemDoubleClicked()
3156 void PrefShortcuts::modifyShortcut()
3158 QTreeWidgetItem * item = shortcutsTW->currentItem();
3159 if (item->flags() & Qt::ItemIsSelectable) {
3160 shortcut_->lfunLE->setText(item->text(0));
3161 save_lfun_ = item->text(0).trimmed();
3162 shortcut_->shortcutWG->setText(item->text(1));
3164 seq.parse(fromqstr(item->data(1, Qt::UserRole).toString()));
3165 shortcut_->shortcutWG->setKeySequence(seq);
3166 shortcut_->shortcutWG->setFocus();
3172 void PrefShortcuts::unhideEmpty(QString const & lfun, bool select)
3174 // list of items that match lfun
3175 QList<QTreeWidgetItem*> items = shortcutsTW->findItems(lfun,
3176 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 0);
3177 for (auto const & item : items) {
3178 if (isAlwaysHidden(*item)) {
3179 setItemType(item, KeyMap::System);
3181 shortcutsTW->setCurrentItem(item);
3188 void PrefShortcuts::removeShortcut()
3190 // it seems that only one item can be selected, but I am
3191 // removing all selected items anyway.
3192 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
3193 for (auto & item : items) {
3194 string shortcut = fromqstr(item->data(1, Qt::UserRole).toString());
3195 string lfun = fromqstr(item->text(0));
3196 FuncRequest const func = lyxaction.lookupFunc(lfun);
3198 switch (itemType(*item)) {
3199 case KeyMap::System: {
3200 // for system bind, we do not touch the item
3201 // but add an user unbind item
3202 user_unbind_.bind(shortcut, func);
3203 setItemType(item, KeyMap::UserUnbind);
3204 removePB->setText(qt_("Res&tore"));
3207 case KeyMap::UserBind: {
3208 // for user_bind, we remove this bind
3209 QTreeWidgetItem * parent = item->parent();
3210 int itemIdx = parent->indexOfChild(item);
3211 parent->takeChild(itemIdx);
3213 shortcutsTW->scrollToItem(parent->child(itemIdx - 1));
3215 shortcutsTW->scrollToItem(parent);
3216 user_bind_.unbind(shortcut, func);
3217 // If this user binding hid an empty system binding, unhide the
3218 // latter and select it.
3219 unhideEmpty(item->text(0), true);
3222 case KeyMap::UserUnbind: {
3223 // for user_unbind, we remove the unbind, and the item
3224 // become KeyMap::System again.
3226 seq.parse(shortcut);
3227 // Ask the user to replace current binding
3228 if (!validateNewShortcut(func, seq, QString()))
3230 user_unbind_.unbind(shortcut, func);
3231 setItemType(item, KeyMap::System);
3232 removePB->setText(qt_("Remo&ve"));
3235 case KeyMap::UserExtraUnbind: {
3236 // for user unbind that is not in system bind file,
3237 // remove this unbind file
3238 QTreeWidgetItem * parent = item->parent();
3239 parent->takeChild(parent->indexOfChild(item));
3240 user_unbind_.unbind(shortcut, func);
3247 void PrefShortcuts::deactivateShortcuts(QList<QTreeWidgetItem*> const & items)
3249 for (auto item : items) {
3250 string shortcut = fromqstr(item->data(1, Qt::UserRole).toString());
3251 string lfun = fromqstr(item->text(0));
3252 FuncRequest const func = lyxaction.lookupFunc(lfun);
3254 switch (itemType(*item)) {
3255 case KeyMap::System:
3256 // for system bind, we do not touch the item
3257 // but add an user unbind item
3258 user_unbind_.bind(shortcut, func);
3259 setItemType(item, KeyMap::UserUnbind);
3262 case KeyMap::UserBind: {
3263 // for user_bind, we remove this bind
3264 QTreeWidgetItem * parent = item->parent();
3265 int itemIdx = parent->indexOfChild(item);
3266 parent->takeChild(itemIdx);
3267 user_bind_.unbind(shortcut, func);
3268 unhideEmpty(item->text(0), false);
3278 void PrefShortcuts::selectBind()
3280 QString file = form_->browsebind(internalPath(bindFileED->text()));
3281 if (!file.isEmpty()) {
3282 bindFileED->setText(file);
3283 system_bind_ = KeyMap();
3284 system_bind_.read(fromqstr(file));
3285 updateShortcutsTW();
3290 void PrefShortcuts::on_modifyPB_pressed()
3296 void PrefShortcuts::on_newPB_pressed()
3298 shortcut_->lfunLE->clear();
3299 shortcut_->shortcutWG->reset();
3300 save_lfun_ = QString();
3305 void PrefShortcuts::on_removePB_pressed()
3312 void PrefShortcuts::on_searchLE_textEdited()
3314 if (searchLE->text().isEmpty()) {
3315 // show all hidden items
3316 QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Hidden);
3318 (*it)->setHidden(isAlwaysHidden(**it));
3319 // close all categories
3320 for (int i = 0; i < shortcutsTW->topLevelItemCount(); ++i)
3321 shortcutsTW->collapseItem(shortcutsTW->topLevelItem(i));
3324 // search both columns
3325 QList<QTreeWidgetItem *> matched = shortcutsTW->findItems(searchLE->text(),
3326 Qt::MatchFlags(Qt::MatchContains | Qt::MatchRecursive), 0);
3327 matched += shortcutsTW->findItems(searchLE->text(),
3328 Qt::MatchFlags(Qt::MatchContains | Qt::MatchRecursive), 1);
3330 // hide everyone (to avoid searching in matched QList repeatedly
3331 QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Selectable);
3333 (*it++)->setHidden(true);
3334 // show matched items
3335 for (auto & item : matched)
3336 if (!isAlwaysHidden(*item)) {
3337 item->setHidden(false);
3339 item->parent()->setExpanded(true);
3344 docstring makeCmdString(FuncRequest const & f)
3346 docstring actionStr = from_ascii(lyxaction.getActionName(f.action()));
3347 if (!f.argument().empty())
3348 actionStr += " " + f.argument();
3353 FuncRequest PrefShortcuts::currentBinding(KeySequence const & k)
3355 FuncRequest res = user_bind_.getBinding(k);
3356 if (res.action() != LFUN_UNKNOWN_ACTION)
3358 res = system_bind_.getBinding(k);
3359 // Check if it is unbound. Note: user_unbind_ can only unbind one
3360 // FuncRequest per key sequence.
3361 if (user_unbind_.getBinding(k) == res)
3362 return FuncRequest::unknown;
3367 bool PrefShortcuts::validateNewShortcut(FuncRequest const & func,
3368 KeySequence const & k,
3369 QString const & lfun_to_modify)
3371 if (func.action() == LFUN_UNKNOWN_ACTION) {
3372 Alert::error(_("Failed to create shortcut"),
3373 _("Unknown or invalid LyX function"));
3377 // It is not currently possible to bind Hidden lfuns such as self-insert. In
3378 // the future, to remove this limitation, see GuiPrefs::insertShortcutItem
3379 // and how it is used in GuiPrefs::shortcutOkPressed.
3380 if (lyxaction.getActionType(func.action()) == LyXAction::Hidden) {
3381 Alert::error(_("Failed to create shortcut"),
3382 _("This LyX function is hidden and cannot be bound."));
3386 if (k.length() == 0) {
3387 Alert::error(_("Failed to create shortcut"),
3388 _("Invalid or empty key sequence"));
3392 FuncRequest oldBinding = currentBinding(k);
3393 if (oldBinding == func)
3394 // nothing to change
3397 // make sure this key isn't already bound---and, if so, prompt user
3398 // (exclude the lfun the user already wants to modify)
3399 docstring const action_string = makeCmdString(oldBinding);
3400 if (oldBinding.action() != LFUN_UNKNOWN_ACTION
3401 && lfun_to_modify != toqstr(action_string)) {
3402 docstring const new_action_string = makeCmdString(func);
3403 docstring const text = bformat(_("Shortcut `%1$s' is already bound to "
3405 "Are you sure you want to unbind the "
3406 "current shortcut and bind it to %3$s?"),
3407 k.print(KeySequence::ForGui), action_string,
3409 int ret = Alert::prompt(_("Redefine shortcut?"),
3410 text, 0, 1, _("&Redefine"), _("&Cancel"));
3413 QString const sequence_text = toqstr(k.print(KeySequence::ForGui));
3414 QList<QTreeWidgetItem*> items = shortcutsTW->findItems(sequence_text,
3415 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 1);
3416 deactivateShortcuts(items);
3422 void PrefShortcuts::shortcutOkPressed()
3424 QString const new_lfun = shortcut_->lfunLE->text();
3425 FuncRequest const func = lyxaction.lookupFunc(fromqstr(new_lfun));
3426 KeySequence k = shortcut_->shortcutWG->getKeySequence();
3428 // save_lfun_ contains the text of the lfun to modify, if the user clicked
3429 // "modify", or is empty if they clicked "new" (which I do not really like)
3430 if (!validateNewShortcut(func, k, save_lfun_))
3433 if (!save_lfun_.isEmpty()) {
3434 // real modification of the lfun's shortcut,
3435 // so remove the previous one
3436 QList<QTreeWidgetItem*> to_modify = shortcutsTW->selectedItems();
3437 deactivateShortcuts(to_modify);
3440 shortcut_->accept();
3442 QTreeWidgetItem * item = insertShortcutItem(func, k, KeyMap::UserBind);
3444 user_bind_.bind(&k, func);
3445 shortcutsTW->sortItems(0, Qt::AscendingOrder);
3446 item->parent()->setExpanded(true);
3447 shortcutsTW->setCurrentItem(item);
3448 shortcutsTW->scrollToItem(item);
3450 Alert::error(_("Failed to create shortcut"),
3451 _("Can not insert shortcut to the list"));
3457 void PrefShortcuts::shortcutCancelPressed()
3459 shortcut_->shortcutWG->reset();
3463 void PrefShortcuts::shortcutClearPressed()
3465 shortcut_->shortcutWG->reset();
3469 void PrefShortcuts::shortcutRemovePressed()
3471 shortcut_->shortcutWG->removeFromSequence();
3475 /////////////////////////////////////////////////////////////////////
3479 /////////////////////////////////////////////////////////////////////
3481 PrefIdentity::PrefIdentity(GuiPreferences * form)
3482 : PrefModule(QString(), N_("Identity"), form)
3486 connect(nameED, SIGNAL(textChanged(QString)),
3487 this, SIGNAL(changed()));
3488 connect(emailED, SIGNAL(textChanged(QString)),
3489 this, SIGNAL(changed()));
3490 connect(initialsED, SIGNAL(textChanged(QString)),
3491 this, SIGNAL(changed()));
3493 nameED->setValidator(new NoNewLineValidator(nameED));
3494 emailED->setValidator(new NoNewLineValidator(emailED));
3495 initialsED->setValidator(new NoNewLineValidator(initialsED));
3499 void PrefIdentity::applyRC(LyXRC & rc) const
3501 rc.user_name = fromqstr(nameED->text());
3502 rc.user_email = fromqstr(emailED->text());
3503 rc.user_initials = fromqstr(initialsED->text());
3507 void PrefIdentity::updateRC(LyXRC const & rc)
3509 nameED->setText(toqstr(rc.user_name));
3510 emailED->setText(toqstr(rc.user_email));
3511 initialsED->setText(toqstr(rc.user_initials));
3516 /////////////////////////////////////////////////////////////////////
3520 /////////////////////////////////////////////////////////////////////
3522 GuiPreferences::GuiPreferences(GuiView & lv)
3523 : GuiDialog(lv, "prefs", qt_("Preferences"))
3527 QDialog::setModal(false);
3529 connect(buttonBox, SIGNAL(clicked(QAbstractButton *)),
3530 this, SLOT(slotButtonBox(QAbstractButton *)));
3532 addModule(new PrefUserInterface(this));
3533 addModule(new PrefDocHandling(this));
3534 addModule(new PrefEdit(this));
3535 addModule(new PrefShortcuts(this));
3536 PrefScreenFonts * screenfonts = new PrefScreenFonts(this);
3537 connect(this, SIGNAL(prefsApplied(LyXRC const &)),
3538 screenfonts, SLOT(updateScreenFontSizes(LyXRC const &)));
3539 addModule(screenfonts);
3540 addModule(new PrefColors(this));
3541 addModule(new PrefDisplay(this));
3542 addModule(new PrefInput(this));
3543 addModule(new PrefCompletion(this));
3545 addModule(new PrefPaths(this));
3547 addModule(new PrefIdentity(this));
3549 addModule(new PrefLanguage(this));
3550 addModule(new PrefSpellchecker(this));
3552 PrefOutput * output = new PrefOutput(this);
3554 addModule(new PrefLatex(this));
3556 PrefConverters * converters = new PrefConverters(this);
3557 PrefFileformats * formats = new PrefFileformats(this);
3558 connect(formats, SIGNAL(formatsChanged()),
3559 converters, SLOT(updateGui()));
3560 addModule(converters);
3563 prefsPS->setCurrentPanel("User Interface");
3564 // FIXME: hack to work around resizing bug in Qt >= 4.2
3565 // bug verified with Qt 4.2.{0-3} (JSpitzm)
3566 #if QT_VERSION >= 0x040200
3567 prefsPS->updateGeometry();
3570 bc().setPolicy(ButtonPolicy::PreferencesPolicy);
3571 bc().setOK(buttonBox->button(QDialogButtonBox::Ok));
3572 bc().setApply(buttonBox->button(QDialogButtonBox::Apply));
3573 bc().setCancel(buttonBox->button(QDialogButtonBox::Cancel));
3574 bc().setRestore(buttonBox->button(QDialogButtonBox::Reset));
3576 guilyxfiles_ = new GuiLyXFiles(lv);
3577 connect(guilyxfiles_, SIGNAL(fileSelected(QString)),
3578 this, SLOT(slotFileSelected(QString)));
3582 void GuiPreferences::addModule(PrefModule * module)
3584 LASSERT(module, return);
3585 if (module->category().isEmpty())
3586 prefsPS->addPanel(module, module->title());
3588 prefsPS->addPanel(module, module->title(), module->category());
3589 connect(module, SIGNAL(changed()), this, SLOT(change_adaptor()));
3590 modules_.push_back(module);
3594 void GuiPreferences::change_adaptor()
3600 void GuiPreferences::applyRC(LyXRC & rc) const
3602 size_t end = modules_.size();
3603 for (size_t i = 0; i != end; ++i)
3604 modules_[i]->applyRC(rc);
3608 void GuiPreferences::updateRC(LyXRC const & rc)
3610 size_t const end = modules_.size();
3611 for (size_t i = 0; i != end; ++i)
3612 modules_[i]->updateRC(rc);
3616 void GuiPreferences::applyView()
3622 bool GuiPreferences::initialiseParams(string const &)
3625 formats_ = theFormats();
3626 converters_ = theConverters();
3627 converters_.update(formats_);
3628 movers_ = theMovers();
3632 // Make sure that the bc is in the INITIAL state
3633 if (bc().policy().buttonStatus(ButtonPolicy::RESTORE))
3640 void GuiPreferences::dispatchParams()
3643 rc_.write(ss, true);
3644 dispatch(FuncRequest(LFUN_LYXRC_APPLY, ss.str()));
3645 // issue prefsApplied signal. This will update the
3646 // localized screen font sizes.
3648 // FIXME: these need lfuns
3650 Author const & author =
3651 Author(from_utf8(rc_.user_name), from_utf8(rc_.user_email),
3652 from_utf8(rc_.user_initials));
3653 theBufferList().recordCurrentAuthor(author);
3655 theFormats() = formats_;
3657 theConverters() = converters_;
3658 theConverters().update(formats_);
3659 theConverters().buildGraph();
3660 theBufferList().invalidateConverterCache();
3662 theMovers() = movers_;
3664 for (string const & color : colors_)
3665 dispatch(FuncRequest(LFUN_SET_COLOR, color));
3669 if (!tempSaveCB->isChecked())
3670 dispatch(FuncRequest(LFUN_PREFERENCES_SAVE));
3674 void GuiPreferences::setColor(ColorCode col, QString const & hex)
3676 colors_.push_back(lcolor.getLyXName(col) + ' ' + fromqstr(hex));
3680 void GuiPreferences::slotFileSelected(QString const file)
3686 QString GuiPreferences::browseLibFile(QString const & dir,
3687 QString const & name, QString const & ext)
3691 guilyxfiles_->passParams(fromqstr(dir));
3692 guilyxfiles_->selectItem(name);
3693 guilyxfiles_->exec();
3695 QString const result = uifile_;
3697 // remove the extension if it is the default one
3698 QString noextresult;
3699 if (getExtension(result) == ext)
3700 noextresult = removeExtension(result);
3702 noextresult = result;
3704 // remove the directory, if it is the default one
3705 QString const file = onlyFileName(noextresult);
3706 if (toqstr(libFileSearch(dir, file, ext).absFileName()) == result)
3713 QString GuiPreferences::browsebind(QString const & file)
3715 return browseLibFile("bind", file, "bind");
3719 QString GuiPreferences::browseUI(QString const & file)
3721 return browseLibFile("ui", file, "ui");
3725 QString GuiPreferences::browsekbmap(QString const & file)
3727 return browseLibFile("kbd", file, "kmap");
3731 QString GuiPreferences::browse(QString const & file,
3732 QString const & title) const
3734 return browseFile(file, title, QStringList(), true);
3738 } // namespace frontend
3741 #include "moc_GuiPrefs.cpp"