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 #if QT_VERSION >= 0x060000
935 const QStringList families(QFontDatabase::families());
937 QFontDatabase fontdb;
938 const QStringList families(fontdb.families());
940 for (auto const & family : families) {
941 screenRomanCO->addItem(family);
942 screenSansCO->addItem(family);
943 screenTypewriterCO->addItem(family);
945 #if QT_VERSION < 0x050e00
946 connect(screenRomanCO, SIGNAL(activated(QString)),
947 this, SIGNAL(changed()));
948 connect(screenSansCO, SIGNAL(activated(QString)),
949 this, SIGNAL(changed()));
950 connect(screenTypewriterCO, SIGNAL(activated(QString)),
951 this, SIGNAL(changed()));
953 connect(screenRomanCO, SIGNAL(textActivated(QString)),
954 this, SIGNAL(changed()));
955 connect(screenSansCO, SIGNAL(textActivated(QString)),
956 this, SIGNAL(changed()));
957 connect(screenTypewriterCO, SIGNAL(textActivated(QString)),
958 this, SIGNAL(changed()));
960 connect(screenZoomSB, SIGNAL(valueChanged(int)),
961 this, SIGNAL(changed()));
962 connect(screenTinyED, SIGNAL(textChanged(QString)),
963 this, SIGNAL(changed()));
964 connect(screenSmallestED, SIGNAL(textChanged(QString)),
965 this, SIGNAL(changed()));
966 connect(screenSmallerED, SIGNAL(textChanged(QString)),
967 this, SIGNAL(changed()));
968 connect(screenSmallED, SIGNAL(textChanged(QString)),
969 this, SIGNAL(changed()));
970 connect(screenNormalED, SIGNAL(textChanged(QString)),
971 this, SIGNAL(changed()));
972 connect(screenLargeED, SIGNAL(textChanged(QString)),
973 this, SIGNAL(changed()));
974 connect(screenLargerED, SIGNAL(textChanged(QString)),
975 this, SIGNAL(changed()));
976 connect(screenLargestED, SIGNAL(textChanged(QString)),
977 this, SIGNAL(changed()));
978 connect(screenHugeED, SIGNAL(textChanged(QString)),
979 this, SIGNAL(changed()));
980 connect(screenHugerED, SIGNAL(textChanged(QString)),
981 this, SIGNAL(changed()));
983 screenTinyED->setValidator(new QDoubleValidator(screenTinyED));
984 screenSmallestED->setValidator(new QDoubleValidator(screenSmallestED));
985 screenSmallerED->setValidator(new QDoubleValidator(screenSmallerED));
986 screenSmallED->setValidator(new QDoubleValidator(screenSmallED));
987 screenNormalED->setValidator(new QDoubleValidator(screenNormalED));
988 screenLargeED->setValidator(new QDoubleValidator(screenLargeED));
989 screenLargerED->setValidator(new QDoubleValidator(screenLargerED));
990 screenLargestED->setValidator(new QDoubleValidator(screenLargestED));
991 screenHugeED->setValidator(new QDoubleValidator(screenHugeED));
992 screenHugerED->setValidator(new QDoubleValidator(screenHugerED));
996 void PrefScreenFonts::applyRC(LyXRC & rc) const
998 LyXRC const oldrc = rc;
1000 parseFontName(screenRomanCO->currentText(),
1001 rc.roman_font_name, rc.roman_font_foundry);
1002 parseFontName(screenSansCO->currentText(),
1003 rc.sans_font_name, rc.sans_font_foundry);
1004 parseFontName(screenTypewriterCO->currentText(),
1005 rc.typewriter_font_name, rc.typewriter_font_foundry);
1007 rc.defaultZoom = screenZoomSB->value();
1008 rc.font_sizes[TINY_SIZE] = widgetToDoubleStr(screenTinyED);
1009 rc.font_sizes[SCRIPT_SIZE] = widgetToDoubleStr(screenSmallestED);
1010 rc.font_sizes[FOOTNOTE_SIZE] = widgetToDoubleStr(screenSmallerED);
1011 rc.font_sizes[SMALL_SIZE] = widgetToDoubleStr(screenSmallED);
1012 rc.font_sizes[NORMAL_SIZE] = widgetToDoubleStr(screenNormalED);
1013 rc.font_sizes[LARGE_SIZE] = widgetToDoubleStr(screenLargeED);
1014 rc.font_sizes[LARGER_SIZE] = widgetToDoubleStr(screenLargerED);
1015 rc.font_sizes[LARGEST_SIZE] = widgetToDoubleStr(screenLargestED);
1016 rc.font_sizes[HUGE_SIZE] = widgetToDoubleStr(screenHugeED);
1017 rc.font_sizes[HUGER_SIZE] = widgetToDoubleStr(screenHugerED);
1021 void PrefScreenFonts::updateRC(LyXRC const & rc)
1023 setComboxFont(screenRomanCO, rc.roman_font_name,
1024 rc.roman_font_foundry);
1025 setComboxFont(screenSansCO, rc.sans_font_name,
1026 rc.sans_font_foundry);
1027 setComboxFont(screenTypewriterCO, rc.typewriter_font_name,
1028 rc.typewriter_font_foundry);
1030 selectRoman(screenRomanCO->currentText());
1031 selectSans(screenSansCO->currentText());
1032 selectTypewriter(screenTypewriterCO->currentText());
1034 screenZoomSB->setValue(rc.defaultZoom);
1035 updateScreenFontSizes(rc);
1039 void PrefScreenFonts::updateScreenFontSizes(LyXRC const & rc)
1041 doubleToWidget(screenTinyED, rc.font_sizes[TINY_SIZE]);
1042 doubleToWidget(screenSmallestED, rc.font_sizes[SCRIPT_SIZE]);
1043 doubleToWidget(screenSmallerED, rc.font_sizes[FOOTNOTE_SIZE]);
1044 doubleToWidget(screenSmallED, rc.font_sizes[SMALL_SIZE]);
1045 doubleToWidget(screenNormalED, rc.font_sizes[NORMAL_SIZE]);
1046 doubleToWidget(screenLargeED, rc.font_sizes[LARGE_SIZE]);
1047 doubleToWidget(screenLargerED, rc.font_sizes[LARGER_SIZE]);
1048 doubleToWidget(screenLargestED, rc.font_sizes[LARGEST_SIZE]);
1049 doubleToWidget(screenHugeED, rc.font_sizes[HUGE_SIZE]);
1050 doubleToWidget(screenHugerED, rc.font_sizes[HUGER_SIZE]);
1054 void PrefScreenFonts::selectRoman(const QString & name)
1056 screenRomanFE->set(QFont(name), name);
1060 void PrefScreenFonts::selectSans(const QString & name)
1062 screenSansFE->set(QFont(name), name);
1066 void PrefScreenFonts::selectTypewriter(const QString & name)
1068 screenTypewriterFE->set(QFont(name), name);
1072 /////////////////////////////////////////////////////////////////////
1076 /////////////////////////////////////////////////////////////////////
1079 PrefColors::PrefColors(GuiPreferences * form)
1080 : PrefModule(catLookAndFeel, N_("Colors"), form)
1084 // FIXME: all of this initialization should be put into the controller.
1085 // See http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg113301.html
1086 // for some discussion of why that is not trivial.
1087 QPixmap icon(32, 32);
1088 for (int i = 0; i < Color_ignore; ++i) {
1089 ColorCode lc = static_cast<ColorCode>(i);
1090 if (lc == Color_none
1091 || lc == Color_black
1092 || lc == Color_white
1094 || lc == Color_brown
1096 || lc == Color_darkgray
1098 || lc == Color_green
1099 || lc == Color_lightgray
1101 || lc == Color_magenta
1102 || lc == Color_olive
1103 || lc == Color_orange
1105 || lc == Color_purple
1108 || lc == Color_violet
1109 || lc == Color_yellow
1110 || lc == Color_inherit
1111 || lc == Color_ignore)
1113 lcolors_.push_back(lc);
1115 sort(lcolors_.begin(), lcolors_.end(), ColorSorter);
1116 vector<ColorCode>::const_iterator cit = lcolors_.begin();
1117 vector<ColorCode>::const_iterator const end = lcolors_.end();
1118 for (; cit != end; ++cit) {
1119 (void) new QListWidgetItem(QIcon(icon),
1120 toqstr(lcolor.getGUIName(*cit)), lyxObjectsLW);
1122 curcolors_.resize(lcolors_.size());
1123 newcolors_.resize(lcolors_.size());
1124 // End initialization
1126 connect(colorChangePB, SIGNAL(clicked()),
1127 this, SLOT(changeColor()));
1128 connect(colorResetPB, SIGNAL(clicked()),
1129 this, SLOT(resetColor()));
1130 connect(colorResetAllPB, SIGNAL(clicked()),
1131 this, SLOT(resetAllColor()));
1132 connect(lyxObjectsLW, SIGNAL(itemSelectionChanged()),
1133 this, SLOT(changeLyxObjectsSelection()));
1134 connect(lyxObjectsLW, SIGNAL(itemActivated(QListWidgetItem*)),
1135 this, SLOT(changeColor()));
1136 connect(syscolorsCB, SIGNAL(toggled(bool)),
1137 this, SIGNAL(changed()));
1138 connect(syscolorsCB, SIGNAL(toggled(bool)),
1139 this, SLOT(changeSysColor()));
1143 void PrefColors::applyRC(LyXRC & rc) const
1147 for (unsigned int i = 0; i < lcolors_.size(); ++i)
1148 if (curcolors_[i] != newcolors_[i])
1149 form_->setColor(lcolors_[i], newcolors_[i]);
1150 rc.use_system_colors = syscolorsCB->isChecked();
1152 if (oldrc.use_system_colors != rc.use_system_colors)
1153 guiApp->colorCache().clear();
1157 void PrefColors::updateRC(LyXRC const & rc)
1159 for (size_type i = 0; i < lcolors_.size(); ++i) {
1160 QColor color = guiApp->colorCache().get(lcolors_[i], false);
1161 QPixmap coloritem(32, 32);
1162 coloritem.fill(color);
1163 lyxObjectsLW->item(int(i))->setIcon(QIcon(coloritem));
1164 newcolors_[i] = curcolors_[i] = color.name();
1166 syscolorsCB->setChecked(rc.use_system_colors);
1167 changeLyxObjectsSelection();
1169 setDisabledResets();
1173 void PrefColors::changeColor()
1175 int const row = lyxObjectsLW->currentRow();
1181 QString const color = newcolors_[size_t(row)];
1182 QColor const c = QColorDialog::getColor(QColor(color), qApp->focusWidget());
1184 if (setColor(row, c, color)) {
1185 setDisabledResets();
1192 void PrefColors::resetColor()
1194 int const row = lyxObjectsLW->currentRow();
1200 QString const color = newcolors_[size_t(row)];
1201 QColor const c = getDefaultColorByRow(row);
1203 if (setColor(row, c, color)) {
1204 setDisabledResets();
1211 void PrefColors::resetAllColor()
1213 bool isChanged = false;
1215 colorResetAllPB->setDisabled(true);
1217 for (int irow = 0, count = lyxObjectsLW->count(); irow < count; ++irow) {
1218 QString const color = newcolors_[size_t(irow)];
1219 QColor const c = getDefaultColorByRow(irow);
1221 if (setColor(irow, c, color))
1226 setDisabledResets();
1233 bool PrefColors::setColor(int const row, QColor const & new_color,
1234 QString const & old_color)
1236 if (new_color.isValid() && new_color.name() != old_color) {
1237 newcolors_[size_t(row)] = new_color.name();
1238 QPixmap coloritem(32, 32);
1239 coloritem.fill(new_color);
1240 lyxObjectsLW->item(row)->setIcon(QIcon(coloritem));
1247 void PrefColors::setDisabledResets()
1249 int const row = lyxObjectsLW->currentRow();
1250 // set disable reset buttons ...
1252 colorResetPB->setDisabled(isDefaultColor(row, newcolors_[size_t(row)]));
1254 colorResetAllPB->setDisabled(true);
1256 // ... in between process qt events to give quicker visual feedback to the user ...
1257 guiApp->processEvents();
1259 // ... set disable Reset All button
1260 for (int irow = 0, count = lyxObjectsLW->count(); irow < count; ++irow) {
1261 if (!isDefaultColor(irow, newcolors_[size_t(irow)])) {
1262 colorResetAllPB->setDisabled(false);
1263 // the break condition might hide performance issues
1264 // if a non-default color is at the top of the list
1271 bool PrefColors::isDefaultColor(int const row, QString const & color)
1273 return color == getDefaultColorByRow(row).name();
1277 QColor PrefColors::getDefaultColorByRow(int const row)
1279 ColorSet const defaultcolor;
1280 return defaultcolor.getX11HexName(lcolors_[size_t(row)],
1281 guiApp->colorCache().isDarkMode()).c_str();
1285 void PrefColors::changeSysColor()
1287 for (int row = 0 ; row < lyxObjectsLW->count() ; ++row) {
1288 // skip colors that are taken from system palette
1289 bool const disable = syscolorsCB->isChecked()
1290 && guiApp->colorCache().isSystem(lcolors_[size_t(row)]);
1292 QListWidgetItem * const item = lyxObjectsLW->item(row);
1293 Qt::ItemFlags const flags = item->flags();
1296 item->setFlags(flags & ~Qt::ItemIsEnabled);
1298 item->setFlags(flags | Qt::ItemIsEnabled);
1303 void PrefColors::changeLyxObjectsSelection()
1305 int currentRow = lyxObjectsLW->currentRow();
1306 colorChangePB->setDisabled(currentRow < 0);
1309 colorResetPB->setDisabled(true);
1311 colorResetPB->setDisabled(
1312 isDefaultColor(currentRow, newcolors_[size_t(currentRow)]));
1316 /////////////////////////////////////////////////////////////////////
1320 /////////////////////////////////////////////////////////////////////
1322 PrefDisplay::PrefDisplay(GuiPreferences * form)
1323 : PrefModule(catLookAndFeel, N_("Display"), form)
1326 connect(displayGraphicsCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1327 connect(instantPreviewCO, SIGNAL(activated(int)), this, SIGNAL(changed()));
1328 connect(previewSizeSB, SIGNAL(valueChanged(double)), this, SIGNAL(changed()));
1329 connect(paragraphMarkerCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1330 connect(ctAdditionsUnderlinedCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1334 void PrefDisplay::on_instantPreviewCO_currentIndexChanged(int index)
1336 previewSizeSB->setEnabled(index != 0);
1340 void PrefDisplay::applyRC(LyXRC & rc) const
1342 switch (instantPreviewCO->currentIndex()) {
1344 rc.preview = LyXRC::PREVIEW_OFF;
1347 rc.preview = LyXRC::PREVIEW_NO_MATH;
1350 rc.preview = LyXRC::PREVIEW_ON;
1354 rc.display_graphics = displayGraphicsCB->isChecked();
1355 rc.preview_scale_factor = previewSizeSB->value();
1356 rc.paragraph_markers = paragraphMarkerCB->isChecked();
1357 rc.ct_additions_underlined = ctAdditionsUnderlinedCB->isChecked();
1359 // FIXME!! The graphics cache no longer has a changeDisplay method.
1361 if (old_value != rc.display_graphics) {
1362 graphics::GCache & gc = graphics::GCache::get();
1369 void PrefDisplay::updateRC(LyXRC const & rc)
1371 switch (rc.preview) {
1372 case LyXRC::PREVIEW_OFF:
1373 instantPreviewCO->setCurrentIndex(0);
1375 case LyXRC::PREVIEW_NO_MATH :
1376 instantPreviewCO->setCurrentIndex(1);
1378 case LyXRC::PREVIEW_ON :
1379 instantPreviewCO->setCurrentIndex(2);
1383 displayGraphicsCB->setChecked(rc.display_graphics);
1384 previewSizeSB->setValue(rc.preview_scale_factor);
1385 paragraphMarkerCB->setChecked(rc.paragraph_markers);
1386 ctAdditionsUnderlinedCB->setChecked(rc.ct_additions_underlined);
1387 previewSizeSB->setEnabled(
1389 && rc.preview != LyXRC::PREVIEW_OFF);
1393 /////////////////////////////////////////////////////////////////////
1397 /////////////////////////////////////////////////////////////////////
1399 PrefPaths::PrefPaths(GuiPreferences * form)
1400 : PrefModule(QString(), N_("Paths"), form)
1404 connect(workingDirPB, SIGNAL(clicked()), this, SLOT(selectWorkingdir()));
1405 connect(workingDirED, SIGNAL(textChanged(QString)),
1406 this, SIGNAL(changed()));
1408 connect(templateDirPB, SIGNAL(clicked()), this, SLOT(selectTemplatedir()));
1409 connect(templateDirED, SIGNAL(textChanged(QString)),
1410 this, SIGNAL(changed()));
1412 connect(exampleDirPB, SIGNAL(clicked()), this, SLOT(selectExampledir()));
1413 connect(exampleDirED, SIGNAL(textChanged(QString)),
1414 this, SIGNAL(changed()));
1416 connect(backupDirPB, SIGNAL(clicked()), this, SLOT(selectBackupdir()));
1417 connect(backupDirED, SIGNAL(textChanged(QString)),
1418 this, SIGNAL(changed()));
1420 connect(lyxserverDirPB, SIGNAL(clicked()), this, SLOT(selectLyxPipe()));
1421 connect(lyxserverDirED, SIGNAL(textChanged(QString)),
1422 this, SIGNAL(changed()));
1424 connect(thesaurusDirPB, SIGNAL(clicked()), this, SLOT(selectThesaurusdir()));
1425 connect(thesaurusDirED, SIGNAL(textChanged(QString)),
1426 this, SIGNAL(changed()));
1428 connect(tempDirPB, SIGNAL(clicked()), this, SLOT(selectTempdir()));
1429 connect(tempDirED, SIGNAL(textChanged(QString)),
1430 this, SIGNAL(changed()));
1432 #if defined(USE_HUNSPELL)
1433 connect(hunspellDirPB, SIGNAL(clicked()), this, SLOT(selectHunspelldir()));
1434 connect(hunspellDirED, SIGNAL(textChanged(QString)),
1435 this, SIGNAL(changed()));
1437 hunspellDirPB->setEnabled(false);
1438 hunspellDirED->setEnabled(false);
1441 connect(pathPrefixED, SIGNAL(textChanged(QString)),
1442 this, SIGNAL(changed()));
1444 connect(texinputsPrefixED, SIGNAL(textChanged(QString)),
1445 this, SIGNAL(changed()));
1447 pathPrefixED->setValidator(new NoNewLineValidator(pathPrefixED));
1448 texinputsPrefixED->setValidator(new NoNewLineValidator(texinputsPrefixED));
1452 void PrefPaths::applyRC(LyXRC & rc) const
1454 rc.document_path = internal_path(fromqstr(workingDirED->text()));
1455 rc.example_path = internal_path(fromqstr(exampleDirED->text()));
1456 rc.template_path = internal_path(fromqstr(templateDirED->text()));
1457 rc.backupdir_path = internal_path(fromqstr(backupDirED->text()));
1458 rc.tempdir_path = internal_path(fromqstr(tempDirED->text()));
1459 rc.thesaurusdir_path = internal_path(fromqstr(thesaurusDirED->text()));
1460 rc.hunspelldir_path = internal_path(fromqstr(hunspellDirED->text()));
1461 rc.path_prefix = internal_path_list(fromqstr(pathPrefixED->text()));
1462 rc.texinputs_prefix = internal_path_list(fromqstr(texinputsPrefixED->text()));
1463 // FIXME: should be a checkbox only
1464 rc.lyxpipes = internal_path(fromqstr(lyxserverDirED->text()));
1468 void PrefPaths::updateRC(LyXRC const & rc)
1470 workingDirED->setText(toqstr(external_path(rc.document_path)));
1471 exampleDirED->setText(toqstr(external_path(rc.example_path)));
1472 templateDirED->setText(toqstr(external_path(rc.template_path)));
1473 backupDirED->setText(toqstr(external_path(rc.backupdir_path)));
1474 tempDirED->setText(toqstr(external_path(rc.tempdir_path)));
1475 thesaurusDirED->setText(toqstr(external_path(rc.thesaurusdir_path)));
1476 hunspellDirED->setText(toqstr(external_path(rc.hunspelldir_path)));
1477 pathPrefixED->setText(toqstr(external_path_list(rc.path_prefix)));
1478 texinputsPrefixED->setText(toqstr(external_path_list(rc.texinputs_prefix)));
1479 // FIXME: should be a checkbox only
1480 lyxserverDirED->setText(toqstr(external_path(rc.lyxpipes)));
1484 void PrefPaths::selectExampledir()
1486 QString file = browseDir(internalPath(exampleDirED->text()),
1487 qt_("Select directory for example files"));
1488 if (!file.isEmpty())
1489 exampleDirED->setText(file);
1493 void PrefPaths::selectTemplatedir()
1495 QString file = browseDir(internalPath(templateDirED->text()),
1496 qt_("Select a document templates directory"));
1497 if (!file.isEmpty())
1498 templateDirED->setText(file);
1502 void PrefPaths::selectTempdir()
1504 QString file = browseDir(internalPath(tempDirED->text()),
1505 qt_("Select a temporary directory"));
1506 if (!file.isEmpty())
1507 tempDirED->setText(file);
1511 void PrefPaths::selectBackupdir()
1513 QString file = browseDir(internalPath(backupDirED->text()),
1514 qt_("Select a backups directory"));
1515 if (!file.isEmpty())
1516 backupDirED->setText(file);
1520 void PrefPaths::selectWorkingdir()
1522 QString file = browseDir(internalPath(workingDirED->text()),
1523 qt_("Select a document directory"));
1524 if (!file.isEmpty())
1525 workingDirED->setText(file);
1529 void PrefPaths::selectThesaurusdir()
1531 QString file = browseDir(internalPath(thesaurusDirED->text()),
1532 qt_("Set the path to the thesaurus dictionaries"));
1533 if (!file.isEmpty())
1534 thesaurusDirED->setText(file);
1538 void PrefPaths::selectHunspelldir()
1540 QString file = browseDir(internalPath(hunspellDirED->text()),
1541 qt_("Set the path to the Hunspell dictionaries"));
1542 if (!file.isEmpty())
1543 hunspellDirED->setText(file);
1547 void PrefPaths::selectLyxPipe()
1549 QString file = form_->browse(internalPath(lyxserverDirED->text()),
1550 qt_("Give a filename for the LyX server pipe"));
1551 if (!file.isEmpty())
1552 lyxserverDirED->setText(file);
1556 /////////////////////////////////////////////////////////////////////
1560 /////////////////////////////////////////////////////////////////////
1562 PrefSpellchecker::PrefSpellchecker(GuiPreferences * form)
1563 : PrefModule(catLanguage, N_("Spellchecker"), form)
1567 // FIXME: this check should test the target platform (darwin)
1568 #if defined(USE_MACOSX_PACKAGING)
1569 spellcheckerCB->addItem(qt_("Native"), QString("native"));
1570 #define CONNECT_APPLESPELL
1572 #undef CONNECT_APPLESPELL
1574 #if defined(USE_ASPELL)
1575 spellcheckerCB->addItem(qt_("Aspell"), QString("aspell"));
1577 #if defined(USE_ENCHANT)
1578 spellcheckerCB->addItem(qt_("Enchant"), QString("enchant"));
1580 #if defined(USE_HUNSPELL)
1581 spellcheckerCB->addItem(qt_("Hunspell"), QString("hunspell"));
1584 #if defined(CONNECT_APPLESPELL) || defined(USE_ASPELL) || defined(USE_ENCHANT) || defined(USE_HUNSPELL)
1585 connect(spellcheckerCB, SIGNAL(currentIndexChanged(int)),
1586 this, SIGNAL(changed()));
1587 connect(altLanguageED, SIGNAL(textChanged(QString)),
1588 this, SIGNAL(changed()));
1589 connect(escapeCharactersED, SIGNAL(textChanged(QString)),
1590 this, SIGNAL(changed()));
1591 connect(compoundWordCB, SIGNAL(clicked()),
1592 this, SIGNAL(changed()));
1593 connect(spellcheckContinuouslyCB, SIGNAL(clicked()),
1594 this, SIGNAL(changed()));
1595 connect(spellcheckNotesCB, SIGNAL(clicked()),
1596 this, SIGNAL(changed()));
1598 altLanguageED->setValidator(new NoNewLineValidator(altLanguageED));
1599 escapeCharactersED->setValidator(new NoNewLineValidator(escapeCharactersED));
1601 spellcheckerCB->setEnabled(false);
1602 altLanguageED->setEnabled(false);
1603 escapeCharactersED->setEnabled(false);
1604 compoundWordCB->setEnabled(false);
1605 spellcheckContinuouslyCB->setEnabled(false);
1606 spellcheckNotesCB->setEnabled(false);
1611 void PrefSpellchecker::applyRC(LyXRC & rc) const
1613 string const speller = fromqstr(spellcheckerCB->
1614 itemData(spellcheckerCB->currentIndex()).toString());
1615 if (!speller.empty())
1616 rc.spellchecker = speller;
1617 rc.spellchecker_alt_lang = fromqstr(altLanguageED->text());
1618 rc.spellchecker_esc_chars = fromqstr(escapeCharactersED->text());
1619 rc.spellchecker_accept_compound = compoundWordCB->isChecked();
1620 rc.spellcheck_continuously = spellcheckContinuouslyCB->isChecked();
1621 rc.spellcheck_notes = spellcheckNotesCB->isChecked();
1625 void PrefSpellchecker::updateRC(LyXRC const & rc)
1627 spellcheckerCB->setCurrentIndex(
1628 spellcheckerCB->findData(toqstr(rc.spellchecker)));
1629 altLanguageED->setText(toqstr(rc.spellchecker_alt_lang));
1630 escapeCharactersED->setText(toqstr(rc.spellchecker_esc_chars));
1631 compoundWordCB->setChecked(rc.spellchecker_accept_compound);
1632 spellcheckContinuouslyCB->setChecked(rc.spellcheck_continuously);
1633 spellcheckNotesCB->setChecked(rc.spellcheck_notes);
1637 void PrefSpellchecker::on_spellcheckerCB_currentIndexChanged(int index)
1639 QString spellchecker = spellcheckerCB->itemData(index).toString();
1641 compoundWordCB->setEnabled(spellchecker == QString("aspell"));
1646 /////////////////////////////////////////////////////////////////////
1650 /////////////////////////////////////////////////////////////////////
1653 PrefConverters::PrefConverters(GuiPreferences * form)
1654 : PrefModule(catFiles, N_("Converters"), form)
1658 connect(converterNewPB, SIGNAL(clicked()),
1659 this, SLOT(updateConverter()));
1660 connect(converterRemovePB, SIGNAL(clicked()),
1661 this, SLOT(removeConverter()));
1662 connect(converterModifyPB, SIGNAL(clicked()),
1663 this, SLOT(updateConverter()));
1664 connect(convertersLW, SIGNAL(currentRowChanged(int)),
1665 this, SLOT(switchConverter()));
1666 #if QT_VERSION < 0x050e00
1667 connect(converterFromCO, SIGNAL(activated(QString)),
1668 this, SLOT(changeConverter()));
1669 connect(converterToCO, SIGNAL(activated(QString)),
1670 this, SLOT(changeConverter()));
1672 connect(converterFromCO, SIGNAL(textActivated(QString)),
1673 this, SLOT(changeConverter()));
1674 connect(converterToCO, SIGNAL(textActivated(QString)),
1675 this, SLOT(changeConverter()));
1677 connect(converterED, SIGNAL(textEdited(QString)),
1678 this, SLOT(changeConverter()));
1679 connect(converterFlagED, SIGNAL(textEdited(QString)),
1680 this, SLOT(changeConverter()));
1681 connect(converterNewPB, SIGNAL(clicked()),
1682 this, SIGNAL(changed()));
1683 connect(converterRemovePB, SIGNAL(clicked()),
1684 this, SIGNAL(changed()));
1685 connect(converterModifyPB, SIGNAL(clicked()),
1686 this, SIGNAL(changed()));
1687 connect(maxAgeLE, SIGNAL(textEdited(QString)),
1688 this, SIGNAL(changed()));
1689 connect(needauthForbiddenCB, SIGNAL(toggled(bool)),
1690 this, SIGNAL(changed()));
1692 converterED->setValidator(new NoNewLineValidator(converterED));
1693 converterFlagED->setValidator(new NoNewLineValidator(converterFlagED));
1694 maxAgeLE->setValidator(new QDoubleValidator(0, HUGE_VAL, 6, maxAgeLE));
1695 //converterDefGB->setFocusProxy(convertersLW);
1699 void PrefConverters::applyRC(LyXRC & rc) const
1701 rc.use_converter_cache = cacheCB->isChecked();
1702 rc.use_converter_needauth_forbidden = needauthForbiddenCB->isChecked();
1703 rc.use_converter_needauth = needauthCB->isChecked();
1704 rc.converter_cache_maxage = int(widgetToDouble(maxAgeLE) * 86400.0);
1708 static void setCheckboxBlockSignals(QCheckBox *cb, bool checked) {
1709 cb->blockSignals(true);
1710 cb->setChecked(checked);
1711 cb->blockSignals(false);
1715 void PrefConverters::updateRC(LyXRC const & rc)
1717 cacheCB->setChecked(rc.use_converter_cache);
1718 needauthForbiddenCB->setChecked(rc.use_converter_needauth_forbidden);
1719 setCheckboxBlockSignals(needauthCB, rc.use_converter_needauth);
1721 doubleToWidget(maxAgeLE, (double(rc.converter_cache_maxage) / 86400.0), 'g', 6);
1726 void PrefConverters::updateGui()
1728 QString const pattern("%1 -> %2");
1729 form_->formats().sort();
1730 form_->converters().update(form_->formats());
1731 // save current selection
1734 .arg(converterFromCO->currentText())
1735 .arg(converterToCO->currentText());
1737 converterFromCO->clear();
1738 converterToCO->clear();
1740 for (Format const & f : form_->formats()) {
1741 QString const name = toqstr(translateIfPossible(f.prettyname()));
1742 converterFromCO->addItem(name);
1743 converterToCO->addItem(name);
1746 // currentRowChanged(int) is also triggered when updating the listwidget
1747 // block signals to avoid unnecessary calls to switchConverter()
1748 convertersLW->blockSignals(true);
1749 convertersLW->clear();
1751 for (Converter const & c : form_->converters()) {
1752 QString const name =
1754 .arg(toqstr(translateIfPossible(c.From()->prettyname())))
1755 .arg(toqstr(translateIfPossible(c.To()->prettyname())));
1756 int type = form_->converters().getNumber(c.From()->name(),
1758 new QListWidgetItem(name, convertersLW, type);
1760 convertersLW->sortItems(Qt::AscendingOrder);
1761 convertersLW->blockSignals(false);
1763 // restore selection
1764 if (current != pattern.arg(QString()).arg(QString())) {
1765 QList<QListWidgetItem *> const item =
1766 convertersLW->findItems(current, Qt::MatchExactly);
1767 if (!item.isEmpty())
1768 convertersLW->setCurrentItem(item.at(0));
1771 // select first element if restoring failed
1772 if (convertersLW->currentRow() == -1)
1773 convertersLW->setCurrentRow(0);
1779 void PrefConverters::switchConverter()
1781 int const cnr = convertersLW->currentItem()->type();
1782 Converter const & c(form_->converters().get(cnr));
1783 converterFromCO->setCurrentIndex(form_->formats().getNumber(c.from()));
1784 converterToCO->setCurrentIndex(form_->formats().getNumber(c.to()));
1785 converterED->setText(toqstr(c.command()));
1786 converterFlagED->setText(toqstr(c.flags()));
1792 void PrefConverters::changeConverter()
1798 void PrefConverters::updateButtons()
1800 if (form_->formats().empty())
1802 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1803 Format const & to = form_->formats().get(converterToCO->currentIndex());
1804 int const sel = form_->converters().getNumber(from.name(), to.name());
1805 bool const known = sel >= 0;
1806 bool const valid = !(converterED->text().isEmpty()
1807 || from.name() == to.name());
1812 if (convertersLW->count() > 0) {
1813 int const cnr = convertersLW->currentItem()->type();
1814 Converter const & c = form_->converters().get(cnr);
1815 old_command = c.command();
1816 old_flag = c.flags();
1819 string const new_command = fromqstr(converterED->text());
1820 string const new_flag = fromqstr(converterFlagED->text());
1822 bool modified = (old_command != new_command || old_flag != new_flag);
1824 converterModifyPB->setEnabled(valid && known && modified);
1825 converterNewPB->setEnabled(valid && !known);
1826 converterRemovePB->setEnabled(known);
1828 maxAgeLE->setEnabled(cacheCB->isChecked());
1829 maxAgeLA->setEnabled(cacheCB->isChecked());
1834 // specify unique from/to or it doesn't appear. This is really bad UI
1835 // this is why we can use the same function for both new and modify
1836 void PrefConverters::updateConverter()
1838 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1839 Format const & to = form_->formats().get(converterToCO->currentIndex());
1840 string const flags = fromqstr(converterFlagED->text());
1841 string const command = fromqstr(converterED->text());
1843 Converter const * old =
1844 form_->converters().getConverter(from.name(), to.name());
1845 form_->converters().add(from.name(), to.name(), command, flags);
1848 form_->converters().updateLast(form_->formats());
1852 // Remove all files created by this converter from the cache, since
1853 // the modified converter might create different files.
1854 ConverterCache::get().remove_all(from.name(), to.name());
1858 void PrefConverters::removeConverter()
1860 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1861 Format const & to = form_->formats().get(converterToCO->currentIndex());
1862 form_->converters().erase(from.name(), to.name());
1866 // Remove all files created by this converter from the cache, since
1867 // a possible new converter might create different files.
1868 ConverterCache::get().remove_all(from.name(), to.name());
1872 void PrefConverters::on_cacheCB_stateChanged(int state)
1874 maxAgeLE->setEnabled(state == Qt::Checked);
1875 maxAgeLA->setEnabled(state == Qt::Checked);
1880 void PrefConverters::on_needauthForbiddenCB_toggled(bool checked)
1882 needauthCB->setEnabled(!checked);
1886 void PrefConverters::on_needauthCB_toggled(bool checked)
1893 int ret = frontend::Alert::prompt(
1894 _("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!"),
1895 0, 0, _("&No"), _("&Yes"));
1899 setCheckboxBlockSignals(needauthCB, true);
1903 /////////////////////////////////////////////////////////////////////
1907 /////////////////////////////////////////////////////////////////////
1909 class FormatValidator : public QValidator
1912 FormatValidator(QWidget *, Formats const & f);
1913 void fixup(QString & input) const override;
1914 QValidator::State validate(QString & input, int & pos) const override;
1916 virtual QString toString(Format const & format) const = 0;
1918 Formats const & formats_;
1922 FormatValidator::FormatValidator(QWidget * parent, Formats const & f)
1923 : QValidator(parent), formats_(f)
1928 void FormatValidator::fixup(QString & input) const
1930 Formats::const_iterator cit = formats_.begin();
1931 Formats::const_iterator end = formats_.end();
1932 for (; cit != end; ++cit) {
1933 QString const name = toString(*cit);
1934 if (distance(formats_.begin(), cit) == nr()) {
1942 QValidator::State FormatValidator::validate(QString & input, int & /*pos*/) const
1944 Formats::const_iterator cit = formats_.begin();
1945 Formats::const_iterator end = formats_.end();
1946 bool unknown = true;
1947 for (; unknown && cit != end; ++cit) {
1948 QString const name = toString(*cit);
1949 if (distance(formats_.begin(), cit) != nr())
1950 unknown = name != input;
1953 if (unknown && !input.isEmpty())
1954 return QValidator::Acceptable;
1956 return QValidator::Intermediate;
1960 int FormatValidator::nr() const
1962 QComboBox * p = qobject_cast<QComboBox *>(parent());
1963 return p->itemData(p->currentIndex()).toInt();
1967 /////////////////////////////////////////////////////////////////////
1969 // FormatNameValidator
1971 /////////////////////////////////////////////////////////////////////
1973 class FormatNameValidator : public FormatValidator
1976 FormatNameValidator(QWidget * parent, Formats const & f)
1977 : FormatValidator(parent, f)
1980 QString toString(Format const & format) const override
1982 return toqstr(format.name());
1987 /////////////////////////////////////////////////////////////////////
1989 // FormatPrettynameValidator
1991 /////////////////////////////////////////////////////////////////////
1993 class FormatPrettynameValidator : public FormatValidator
1996 FormatPrettynameValidator(QWidget * parent, Formats const & f)
1997 : FormatValidator(parent, f)
2000 QString toString(Format const & format) const override
2002 return toqstr(translateIfPossible(format.prettyname()));
2007 /////////////////////////////////////////////////////////////////////
2011 /////////////////////////////////////////////////////////////////////
2013 PrefFileformats::PrefFileformats(GuiPreferences * form)
2014 : PrefModule(catFiles, N_("File Formats"), form)
2018 formatED->setValidator(new FormatNameValidator(formatsCB, form_->formats()));
2019 formatsCB->setValidator(new FormatPrettynameValidator(formatsCB, form_->formats()));
2020 extensionsED->setValidator(new NoNewLineValidator(extensionsED));
2021 shortcutED->setValidator(new NoNewLineValidator(shortcutED));
2022 editorED->setValidator(new NoNewLineValidator(editorED));
2023 viewerED->setValidator(new NoNewLineValidator(viewerED));
2024 copierED->setValidator(new NoNewLineValidator(copierED));
2026 connect(documentCB, SIGNAL(clicked()),
2027 this, SLOT(setFlags()));
2028 connect(vectorCB, SIGNAL(clicked()),
2029 this, SLOT(setFlags()));
2030 connect(exportMenuCB, SIGNAL(clicked()),
2031 this, SLOT(setFlags()));
2032 connect(formatsCB->lineEdit(), SIGNAL(editingFinished()),
2033 this, SLOT(updatePrettyname()));
2034 connect(formatsCB->lineEdit(), SIGNAL(textEdited(QString)),
2035 this, SIGNAL(changed()));
2036 #if QT_VERSION < 0x050e00
2037 connect(defaultFormatCB, SIGNAL(activated(QString)),
2038 this, SIGNAL(changed()));
2039 connect(defaultOTFFormatCB, SIGNAL(activated(QString)),
2040 this, SIGNAL(changed()));
2041 connect(defaultPlatexFormatCB, SIGNAL(activated(QString)),
2042 this, SIGNAL(changed()));
2044 connect(defaultFormatCB, SIGNAL(textActivated(QString)),
2045 this, SIGNAL(changed()));
2046 connect(defaultOTFFormatCB, SIGNAL(textActivated(QString)),
2047 this, SIGNAL(changed()));
2048 connect(defaultPlatexFormatCB, SIGNAL(textActivated(QString)),
2049 this, SIGNAL(changed()));
2051 connect(viewerCO, SIGNAL(activated(int)),
2052 this, SIGNAL(changed()));
2053 connect(editorCO, SIGNAL(activated(int)),
2054 this, SIGNAL(changed()));
2060 string const l10n_shortcut(docstring const & prettyname, string const & shortcut)
2062 if (shortcut.empty())
2065 string l10n_format =
2066 to_utf8(_(to_utf8(prettyname) + '|' + shortcut));
2067 return split(l10n_format, '|');
2073 void PrefFileformats::applyRC(LyXRC & rc) const
2075 QString const default_format = defaultFormatCB->itemData(
2076 defaultFormatCB->currentIndex()).toString();
2077 rc.default_view_format = fromqstr(default_format);
2078 QString const default_otf_format = defaultOTFFormatCB->itemData(
2079 defaultOTFFormatCB->currentIndex()).toString();
2080 rc.default_otf_view_format = fromqstr(default_otf_format);
2081 QString const default_platex_format = defaultPlatexFormatCB->itemData(
2082 defaultPlatexFormatCB->currentIndex()).toString();
2083 rc.default_platex_view_format = fromqstr(default_platex_format);
2087 void PrefFileformats::updateRC(LyXRC const & rc)
2089 viewer_alternatives = rc.viewer_alternatives;
2090 editor_alternatives = rc.editor_alternatives;
2091 bool const init = defaultFormatCB->currentText().isEmpty();
2095 defaultFormatCB->findData(toqstr(rc.default_view_format));
2096 defaultFormatCB->setCurrentIndex(pos);
2097 pos = defaultOTFFormatCB->findData(toqstr(rc.default_otf_view_format));
2098 defaultOTFFormatCB->setCurrentIndex(pos);
2099 defaultOTFFormatCB->setCurrentIndex(pos);
2100 pos = defaultPlatexFormatCB->findData(toqstr(rc.default_platex_view_format));
2101 defaultPlatexFormatCB->setCurrentIndex(pos);
2102 defaultPlatexFormatCB->setCurrentIndex(pos);
2107 void PrefFileformats::updateView()
2109 QString const current = formatsCB->currentText();
2110 QString const current_def = defaultFormatCB->currentText();
2111 QString const current_def_otf = defaultOTFFormatCB->currentText();
2112 QString const current_def_platex = defaultPlatexFormatCB->currentText();
2114 // update comboboxes with formats
2115 formatsCB->blockSignals(true);
2116 defaultFormatCB->blockSignals(true);
2117 defaultOTFFormatCB->blockSignals(true);
2118 defaultPlatexFormatCB->blockSignals(true);
2120 defaultFormatCB->clear();
2121 defaultOTFFormatCB->clear();
2122 defaultPlatexFormatCB->clear();
2123 form_->formats().sort();
2124 for (Format const & f : form_->formats()) {
2125 QString const prettyname = toqstr(translateIfPossible(f.prettyname()));
2126 formatsCB->addItem(prettyname,
2127 QVariant(form_->formats().getNumber(f.name())));
2128 if (f.viewer().empty())
2130 if (form_->converters().isReachable("xhtml", f.name())
2131 || form_->converters().isReachable("dviluatex", f.name())
2132 || form_->converters().isReachable("luatex", f.name())
2133 || form_->converters().isReachable("xetex", f.name())) {
2134 defaultFormatCB->addItem(prettyname,
2135 QVariant(toqstr(f.name())));
2136 defaultOTFFormatCB->addItem(prettyname,
2137 QVariant(toqstr(f.name())));
2139 if (form_->converters().isReachable("latex", f.name())
2140 || form_->converters().isReachable("pdflatex", f.name()))
2141 defaultFormatCB->addItem(prettyname,
2142 QVariant(toqstr(f.name())));
2143 if (form_->converters().isReachable("platex", f.name()))
2144 defaultPlatexFormatCB->addItem(prettyname,
2145 QVariant(toqstr(f.name())));
2149 // restore selections
2150 int item = formatsCB->findText(current, Qt::MatchExactly);
2151 formatsCB->setCurrentIndex(item < 0 ? 0 : item);
2152 on_formatsCB_currentIndexChanged(item < 0 ? 0 : item);
2153 item = defaultFormatCB->findText(current_def, Qt::MatchExactly);
2154 defaultFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2155 item = defaultOTFFormatCB->findText(current_def_otf, Qt::MatchExactly);
2156 defaultOTFFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2157 item = defaultPlatexFormatCB->findText(current_def_platex, Qt::MatchExactly);
2158 defaultPlatexFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2159 formatsCB->blockSignals(false);
2160 defaultFormatCB->blockSignals(false);
2161 defaultOTFFormatCB->blockSignals(false);
2162 defaultPlatexFormatCB->blockSignals(false);
2166 void PrefFileformats::on_formatsCB_currentIndexChanged(int i)
2168 if (form_->formats().empty())
2170 int const nr = formatsCB->itemData(i).toInt();
2171 Format const f = form_->formats().get(nr);
2173 formatED->setText(toqstr(f.name()));
2174 copierED->setText(toqstr(form_->movers().command(f.name())));
2175 extensionsED->setText(toqstr(f.extensions()));
2176 mimeED->setText(toqstr(f.mime()));
2177 shortcutED->setText(
2178 toqstr(l10n_shortcut(f.prettyname(), f.shortcut())));
2179 documentCB->setChecked((f.documentFormat()));
2180 vectorCB->setChecked((f.vectorFormat()));
2181 exportMenuCB->setChecked((f.inExportMenu()));
2182 exportMenuCB->setEnabled((f.documentFormat()));
2188 void PrefFileformats::setFlags()
2190 int flags = Format::none;
2191 if (documentCB->isChecked())
2192 flags |= Format::document;
2193 if (vectorCB->isChecked())
2194 flags |= Format::vector;
2195 if (exportMenuCB->isChecked())
2196 flags |= Format::export_menu;
2197 currentFormat().setFlags(flags);
2198 exportMenuCB->setEnabled(documentCB->isChecked());
2203 void PrefFileformats::on_copierED_textEdited(const QString & s)
2205 string const fmt = fromqstr(formatED->text());
2206 form_->movers().set(fmt, fromqstr(s));
2211 void PrefFileformats::on_extensionsED_textEdited(const QString & s)
2213 currentFormat().setExtensions(fromqstr(s));
2218 void PrefFileformats::on_viewerED_textEdited(const QString & s)
2220 currentFormat().setViewer(fromqstr(s));
2225 void PrefFileformats::on_editorED_textEdited(const QString & s)
2227 currentFormat().setEditor(fromqstr(s));
2232 void PrefFileformats::on_mimeED_textEdited(const QString & s)
2234 currentFormat().setMime(fromqstr(s));
2239 void PrefFileformats::on_shortcutED_textEdited(const QString & s)
2241 string const new_shortcut = fromqstr(s);
2242 if (new_shortcut == l10n_shortcut(currentFormat().prettyname(),
2243 currentFormat().shortcut()))
2245 currentFormat().setShortcut(new_shortcut);
2250 void PrefFileformats::on_formatED_editingFinished()
2252 string const newname = fromqstr(formatED->displayText());
2253 string const oldname = currentFormat().name();
2254 if (newname == oldname)
2256 if (form_->converters().formatIsUsed(oldname)) {
2257 Alert::error(_("Format in use"),
2258 _("You cannot change a format's short name "
2259 "if the format is used by a converter. "
2260 "Please remove the converter first."));
2265 currentFormat().setName(newname);
2270 void PrefFileformats::on_formatED_textChanged(const QString &)
2272 QString t = formatED->text();
2274 bool valid = formatED->validator()->validate(t, p) == QValidator::Acceptable;
2275 setValid(formatLA, valid);
2279 void PrefFileformats::on_formatsCB_editTextChanged(const QString &)
2281 QString t = formatsCB->currentText();
2283 bool valid = formatsCB->validator()->validate(t, p) == QValidator::Acceptable;
2284 setValid(formatsLA, valid);
2288 void PrefFileformats::updatePrettyname()
2290 QString const newname = formatsCB->currentText();
2291 if (newname == toqstr(translateIfPossible(currentFormat().prettyname())))
2294 currentFormat().setPrettyname(qstring_to_ucs4(newname));
2302 void updateComboBox(LyXRC::Alternatives const & alts,
2303 string const & fmt, QComboBox * combo)
2305 LyXRC::Alternatives::const_iterator it =
2307 if (it != alts.end()) {
2308 LyXRC::CommandSet const & cmds = it->second;
2309 LyXRC::CommandSet::const_iterator sit =
2311 LyXRC::CommandSet::const_iterator const sen =
2313 for (; sit != sen; ++sit) {
2314 QString const qcmd = toqstr(*sit);
2315 combo->addItem(qcmd, qcmd);
2322 void PrefFileformats::updateViewers()
2324 Format const f = currentFormat();
2325 viewerCO->blockSignals(true);
2327 viewerCO->addItem(qt_("None"), QString());
2328 viewerCO->addItem(qt_("System Default"), QString("auto"));
2329 updateComboBox(viewer_alternatives, f.name(), viewerCO);
2330 viewerCO->addItem(qt_("Custom"), QString("custom viewer"));
2331 viewerCO->blockSignals(false);
2333 int pos = viewerCO->findData(toqstr(f.viewer()));
2336 viewerED->setEnabled(false);
2337 viewerCO->setCurrentIndex(pos);
2339 viewerED->setEnabled(true);
2340 viewerED->setText(toqstr(f.viewer()));
2341 viewerCO->setCurrentIndex(viewerCO->findData(toqstr("custom viewer")));
2346 void PrefFileformats::updateEditors()
2348 Format const f = currentFormat();
2349 editorCO->blockSignals(true);
2351 editorCO->addItem(qt_("None"), QString());
2352 editorCO->addItem(qt_("System Default"), QString("auto"));
2353 updateComboBox(editor_alternatives, f.name(), editorCO);
2354 editorCO->addItem(qt_("Custom"), QString("custom editor"));
2355 editorCO->blockSignals(false);
2357 int pos = editorCO->findData(toqstr(f.editor()));
2360 editorED->setEnabled(false);
2361 editorCO->setCurrentIndex(pos);
2363 editorED->setEnabled(true);
2364 editorED->setText(toqstr(f.editor()));
2365 editorCO->setCurrentIndex(editorCO->findData(toqstr("custom editor")));
2370 void PrefFileformats::on_viewerCO_currentIndexChanged(int i)
2372 bool const custom = viewerCO->itemData(i).toString() == "custom viewer";
2373 viewerED->setEnabled(custom);
2375 currentFormat().setViewer(fromqstr(viewerCO->itemData(i).toString()));
2379 void PrefFileformats::on_editorCO_currentIndexChanged(int i)
2381 bool const custom = editorCO->itemData(i).toString() == "custom editor";
2382 editorED->setEnabled(custom);
2384 currentFormat().setEditor(fromqstr(editorCO->itemData(i).toString()));
2388 Format & PrefFileformats::currentFormat()
2390 int const i = formatsCB->currentIndex();
2391 int const nr = formatsCB->itemData(i).toInt();
2392 return form_->formats().get(nr);
2396 void PrefFileformats::on_formatNewPB_clicked()
2398 form_->formats().add("", "", docstring(), "", "", "", "", Format::none);
2400 formatsCB->setCurrentIndex(0);
2401 formatsCB->setFocus(Qt::OtherFocusReason);
2405 void PrefFileformats::on_formatRemovePB_clicked()
2407 int const i = formatsCB->currentIndex();
2408 int const nr = formatsCB->itemData(i).toInt();
2409 string const current_text = form_->formats().get(nr).name();
2410 if (form_->converters().formatIsUsed(current_text)) {
2411 Alert::error(_("Format in use"),
2412 _("Cannot remove a Format used by a Converter. "
2413 "Remove the converter first."));
2417 form_->formats().erase(current_text);
2420 on_formatsCB_editTextChanged(formatsCB->currentText());
2425 /////////////////////////////////////////////////////////////////////
2429 /////////////////////////////////////////////////////////////////////
2431 PrefLanguage::PrefLanguage(GuiPreferences * form)
2432 : PrefModule(catLanguage, N_("Language"), form)
2436 connect(visualCursorRB, SIGNAL(clicked()),
2437 this, SIGNAL(changed()));
2438 connect(logicalCursorRB, SIGNAL(clicked()),
2439 this, SIGNAL(changed()));
2440 connect(markForeignCB, SIGNAL(clicked()),
2441 this, SIGNAL(changed()));
2442 connect(respectOSkbdCB, SIGNAL(clicked()),
2443 this, SIGNAL(changed()));
2444 connect(explicitDocLangBeginCB, SIGNAL(clicked()),
2445 this, SIGNAL(changed()));
2446 connect(explicitDocLangEndCB, SIGNAL(clicked()),
2447 this, SIGNAL(changed()));
2448 connect(languagePackageCO, SIGNAL(activated(int)),
2449 this, SIGNAL(changed()));
2450 connect(languagePackageED, SIGNAL(textChanged(QString)),
2451 this, SIGNAL(changed()));
2452 connect(globalCB, SIGNAL(clicked()),
2453 this, SIGNAL(changed()));
2454 connect(startCommandED, SIGNAL(textChanged(QString)),
2455 this, SIGNAL(changed()));
2456 connect(endCommandED, SIGNAL(textChanged(QString)),
2457 this, SIGNAL(changed()));
2458 connect(uiLanguageCO, SIGNAL(activated(int)),
2459 this, SIGNAL(changed()));
2460 connect(defaultDecimalSepED, SIGNAL(textChanged(QString)),
2461 this, SIGNAL(changed()));
2462 connect(defaultDecimalSepCO, SIGNAL(activated(int)),
2463 this, SIGNAL(changed()));
2464 connect(defaultLengthUnitCO, SIGNAL(activated(int)),
2465 this, SIGNAL(changed()));
2467 languagePackageED->setValidator(new NoNewLineValidator(languagePackageED));
2468 startCommandED->setValidator(new NoNewLineValidator(startCommandED));
2469 endCommandED->setValidator(new NoNewLineValidator(endCommandED));
2471 #if QT_VERSION < 0x060000
2472 defaultDecimalSepED->setValidator(new QRegExpValidator(QRegExp("\\S"), this));
2474 defaultDecimalSepED->setValidator(new QRegularExpressionValidator(QRegularExpression("\\S"), this));
2476 defaultDecimalSepED->setMaxLength(1);
2478 defaultLengthUnitCO->addItem(lyx::qt_(unit_name_gui[Length::CM]), Length::CM);
2479 defaultLengthUnitCO->addItem(lyx::qt_(unit_name_gui[Length::IN]), Length::IN);
2481 QAbstractItemModel * language_model = guiApp->languageModel();
2482 language_model->sort(0);
2483 uiLanguageCO->blockSignals(true);
2484 uiLanguageCO->clear();
2485 uiLanguageCO->addItem(qt_("Default"), toqstr("auto"));
2486 for (int i = 0; i != language_model->rowCount(); ++i) {
2487 QModelIndex index = language_model->index(i, 0);
2488 // Filter the list based on the available translation and add
2489 // each language code only once
2490 string const name = fromqstr(index.data(Qt::UserRole).toString());
2491 Language const * lang = languages.getLanguage(name);
2494 // never remove the currently selected language
2495 if (name != form->rc().gui_language
2496 && name != lyxrc.gui_language
2497 && (!Messages::available(lang->code())
2498 || !lang->hasGuiSupport()))
2500 uiLanguageCO->addItem(index.data(Qt::DisplayRole).toString(),
2501 index.data(Qt::UserRole).toString());
2503 uiLanguageCO->blockSignals(false);
2505 // FIXME: restore this when it works (see discussion in #6450).
2506 respectOSkbdCB->hide();
2510 void PrefLanguage::on_uiLanguageCO_currentIndexChanged(int)
2512 QMessageBox::information(this, qt_("LyX needs to be restarted!"),
2513 qt_("The change of user interface language will be fully "
2514 "effective only after a restart."));
2518 void PrefLanguage::on_languagePackageCO_currentIndexChanged(int i)
2521 languagePackageED->setText(save_langpack_);
2522 else if (!languagePackageED->text().isEmpty()) {
2523 save_langpack_ = languagePackageED->text();
2524 languagePackageED->clear();
2526 languagePackageED->setEnabled(i == 2);
2530 void PrefLanguage::on_defaultDecimalSepCO_currentIndexChanged(int i)
2532 defaultDecimalSepED->setEnabled(i == 1);
2536 void PrefLanguage::applyRC(LyXRC & rc) const
2538 rc.visual_cursor = visualCursorRB->isChecked();
2539 rc.mark_foreign_language = markForeignCB->isChecked();
2540 rc.respect_os_kbd_language = respectOSkbdCB->isChecked();
2541 rc.language_auto_begin = !explicitDocLangBeginCB->isChecked();
2542 rc.language_auto_end = !explicitDocLangEndCB->isChecked();
2543 int const p = languagePackageCO->currentIndex();
2545 rc.language_package_selection = LyXRC::LP_AUTO;
2547 rc.language_package_selection = LyXRC::LP_BABEL;
2549 rc.language_package_selection = LyXRC::LP_CUSTOM;
2551 rc.language_package_selection = LyXRC::LP_NONE;
2552 rc.language_custom_package = fromqstr(languagePackageED->text());
2553 rc.language_global_options = globalCB->isChecked();
2554 rc.language_command_begin = fromqstr(startCommandED->text());
2555 rc.language_command_end = fromqstr(endCommandED->text());
2556 rc.gui_language = fromqstr(
2557 uiLanguageCO->itemData(uiLanguageCO->currentIndex()).toString());
2558 if (defaultDecimalSepCO->currentIndex() == 0)
2559 rc.default_decimal_sep = "locale";
2561 rc.default_decimal_sep = fromqstr(defaultDecimalSepED->text());
2562 rc.default_length_unit = (Length::UNIT) defaultLengthUnitCO->itemData(defaultLengthUnitCO->currentIndex()).toInt();
2566 void PrefLanguage::updateRC(LyXRC const & rc)
2568 if (rc.visual_cursor)
2569 visualCursorRB->setChecked(true);
2571 logicalCursorRB->setChecked(true);
2572 markForeignCB->setChecked(rc.mark_foreign_language);
2573 respectOSkbdCB->setChecked(rc.respect_os_kbd_language);
2574 explicitDocLangBeginCB->setChecked(!rc.language_auto_begin);
2575 explicitDocLangEndCB->setChecked(!rc.language_auto_end);
2576 languagePackageCO->setCurrentIndex(rc.language_package_selection);
2577 if (languagePackageCO->currentIndex() == 2) {
2578 languagePackageED->setText(toqstr(rc.language_custom_package));
2579 languagePackageED->setEnabled(true);
2581 languagePackageED->clear();
2582 save_langpack_ = toqstr(rc.language_custom_package);
2583 languagePackageED->setEnabled(false);
2585 defaultDecimalSepED->setEnabled(defaultDecimalSepCO->currentIndex() == 1);
2586 globalCB->setChecked(rc.language_global_options);
2587 startCommandED->setText(toqstr(rc.language_command_begin));
2588 endCommandED->setText(toqstr(rc.language_command_end));
2589 if (rc.default_decimal_sep == "locale") {
2590 defaultDecimalSepCO->setCurrentIndex(0);
2591 defaultDecimalSepED->clear();
2593 defaultDecimalSepCO->setCurrentIndex(1);
2594 defaultDecimalSepED->setText(toqstr(rc.default_decimal_sep));
2596 int pos = defaultLengthUnitCO->findData(int(rc.default_length_unit));
2597 defaultLengthUnitCO->setCurrentIndex(pos);
2599 pos = uiLanguageCO->findData(toqstr(rc.gui_language));
2600 uiLanguageCO->blockSignals(true);
2601 uiLanguageCO->setCurrentIndex(pos);
2602 uiLanguageCO->blockSignals(false);
2606 /////////////////////////////////////////////////////////////////////
2608 // PrefUserInterface
2610 /////////////////////////////////////////////////////////////////////
2612 PrefUserInterface::PrefUserInterface(GuiPreferences * form)
2613 : PrefModule(catLookAndFeel, N_("User Interface"), form)
2617 connect(uiFilePB, SIGNAL(clicked()),
2618 this, SLOT(selectUi()));
2619 connect(uiFileED, SIGNAL(textChanged(QString)),
2620 this, SIGNAL(changed()));
2621 connect(iconSetCO, SIGNAL(activated(int)),
2622 this, SIGNAL(changed()));
2623 connect(useSystemThemeIconsCB, SIGNAL(clicked()),
2624 this, SIGNAL(changed()));
2625 connect(lastfilesSB, SIGNAL(valueChanged(int)),
2626 this, SIGNAL(changed()));
2627 connect(tooltipCB, SIGNAL(toggled(bool)),
2628 this, SIGNAL(changed()));
2629 lastfilesSB->setMaximum(maxlastfiles);
2631 iconSetCO->addItem(qt_("Default"), QString());
2632 iconSetCO->addItem(qt_("Classic"), "classic");
2633 iconSetCO->addItem(qt_("Oxygen"), "oxygen");
2635 #if QT_VERSION >= 0x040600
2636 if (guiApp->platformName() != "qt4x11"
2637 && guiApp->platformName() != "xcb"
2638 && !guiApp->platformName().contains("wayland"))
2640 useSystemThemeIconsCB->hide();
2644 void PrefUserInterface::applyRC(LyXRC & rc) const
2646 rc.icon_set = fromqstr(iconSetCO->itemData(
2647 iconSetCO->currentIndex()).toString());
2649 rc.ui_file = internal_path(fromqstr(uiFileED->text()));
2650 rc.use_system_theme_icons = useSystemThemeIconsCB->isChecked();
2651 rc.num_lastfiles = lastfilesSB->value();
2652 rc.use_tooltip = tooltipCB->isChecked();
2656 void PrefUserInterface::updateRC(LyXRC const & rc)
2658 int iconset = iconSetCO->findData(toqstr(rc.icon_set));
2661 iconSetCO->setCurrentIndex(iconset);
2662 useSystemThemeIconsCB->setChecked(rc.use_system_theme_icons);
2663 uiFileED->setText(toqstr(external_path(rc.ui_file)));
2664 lastfilesSB->setValue(rc.num_lastfiles);
2665 tooltipCB->setChecked(rc.use_tooltip);
2669 void PrefUserInterface::selectUi()
2671 QString file = form_->browseUI(internalPath(uiFileED->text()));
2672 if (!file.isEmpty())
2673 uiFileED->setText(file);
2677 /////////////////////////////////////////////////////////////////////
2679 // PrefDocumentHandling
2681 /////////////////////////////////////////////////////////////////////
2683 PrefDocHandling::PrefDocHandling(GuiPreferences * form)
2684 : PrefModule(catLookAndFeel, N_("Document Handling"), form)
2688 connect(autoSaveCB, SIGNAL(toggled(bool)),
2689 autoSaveSB, SLOT(setEnabled(bool)));
2690 connect(autoSaveCB, SIGNAL(toggled(bool)),
2691 TextLabel1, SLOT(setEnabled(bool)));
2692 connect(openDocumentsInTabsCB, SIGNAL(clicked()),
2693 this, SIGNAL(changed()));
2694 connect(singleInstanceCB, SIGNAL(clicked()),
2695 this, SIGNAL(changed()));
2696 connect(singleCloseTabButtonCB, SIGNAL(clicked()),
2697 this, SIGNAL(changed()));
2698 connect(closeLastViewCO, SIGNAL(activated(int)),
2699 this, SIGNAL(changed()));
2700 connect(restoreCursorCB, SIGNAL(clicked()),
2701 this, SIGNAL(changed()));
2702 connect(loadSessionCB, SIGNAL(clicked()),
2703 this, SIGNAL(changed()));
2704 connect(allowGeometrySessionCB, SIGNAL(clicked()),
2705 this, SIGNAL(changed()));
2706 connect(autoSaveSB, SIGNAL(valueChanged(int)),
2707 this, SIGNAL(changed()));
2708 connect(autoSaveCB, SIGNAL(clicked()),
2709 this, SIGNAL(changed()));
2710 connect(backupCB, SIGNAL(clicked()),
2711 this, SIGNAL(changed()));
2712 connect(saveCompressedCB, SIGNAL(clicked()),
2713 this, SIGNAL(changed()));
2714 connect(saveOriginCB, SIGNAL(clicked()),
2715 this, SIGNAL(changed()));
2719 void PrefDocHandling::applyRC(LyXRC & rc) const
2721 rc.use_lastfilepos = restoreCursorCB->isChecked();
2722 rc.load_session = loadSessionCB->isChecked();
2723 rc.allow_geometry_session = allowGeometrySessionCB->isChecked();
2724 rc.autosave = autoSaveCB->isChecked() ? autoSaveSB->value() * 60 : 0;
2725 rc.make_backup = backupCB->isChecked();
2726 rc.save_compressed = saveCompressedCB->isChecked();
2727 rc.save_origin = saveOriginCB->isChecked();
2728 rc.open_buffers_in_tabs = openDocumentsInTabsCB->isChecked();
2729 rc.single_instance = singleInstanceCB->isChecked();
2730 rc.single_close_tab_button = singleCloseTabButtonCB->isChecked();
2732 switch (closeLastViewCO->currentIndex()) {
2734 rc.close_buffer_with_last_view = "yes";
2737 rc.close_buffer_with_last_view = "no";
2740 rc.close_buffer_with_last_view = "ask";
2748 void PrefDocHandling::updateRC(LyXRC const & rc)
2750 restoreCursorCB->setChecked(rc.use_lastfilepos);
2751 loadSessionCB->setChecked(rc.load_session);
2752 allowGeometrySessionCB->setChecked(rc.allow_geometry_session);
2753 // convert to minutes
2754 bool autosave = rc.autosave > 0;
2755 int mins = rc.autosave / 60;
2758 autoSaveSB->setValue(mins);
2759 autoSaveCB->setChecked(autosave);
2760 autoSaveSB->setEnabled(autosave);
2761 backupCB->setChecked(rc.make_backup);
2762 saveCompressedCB->setChecked(rc.save_compressed);
2763 saveOriginCB->setChecked(rc.save_origin);
2764 openDocumentsInTabsCB->setChecked(rc.open_buffers_in_tabs);
2765 singleInstanceCB->setChecked(rc.single_instance && !rc.lyxpipes.empty());
2766 singleInstanceCB->setEnabled(!rc.lyxpipes.empty());
2767 singleCloseTabButtonCB->setChecked(rc.single_close_tab_button);
2768 if (rc.close_buffer_with_last_view == "yes")
2769 closeLastViewCO->setCurrentIndex(0);
2770 else if (rc.close_buffer_with_last_view == "no")
2771 closeLastViewCO->setCurrentIndex(1);
2772 else if (rc.close_buffer_with_last_view == "ask")
2773 closeLastViewCO->setCurrentIndex(2);
2777 void PrefDocHandling::on_clearSessionPB_clicked()
2779 guiApp->clearSession();
2784 /////////////////////////////////////////////////////////////////////
2788 /////////////////////////////////////////////////////////////////////
2790 PrefEdit::PrefEdit(GuiPreferences * form)
2791 : PrefModule(catEditing, N_("Control"), form)
2795 connect(cursorFollowsCB, SIGNAL(clicked()),
2796 this, SIGNAL(changed()));
2797 connect(scrollBelowCB, SIGNAL(clicked()),
2798 this, SIGNAL(changed()));
2799 connect(macLikeCursorMovementCB, SIGNAL(clicked()),
2800 this, SIGNAL(changed()));
2801 connect(copyCTMarkupCB, SIGNAL(clicked()),
2802 this, SIGNAL(changed()));
2803 connect(sortEnvironmentsCB, SIGNAL(clicked()),
2804 this, SIGNAL(changed()));
2805 connect(groupEnvironmentsCB, SIGNAL(clicked()),
2806 this, SIGNAL(changed()));
2807 connect(macroEditStyleCO, SIGNAL(activated(int)),
2808 this, SIGNAL(changed()));
2809 connect(cursorWidthSB, SIGNAL(valueChanged(int)),
2810 this, SIGNAL(changed()));
2811 connect(citationSearchLE, SIGNAL(textChanged(QString)),
2812 this, SIGNAL(changed()));
2813 connect(fullscreenWidthSB, SIGNAL(valueChanged(int)),
2814 this, SIGNAL(changed()));
2815 connect(toggleTabbarCB, SIGNAL(toggled(bool)),
2816 this, SIGNAL(changed()));
2817 connect(toggleMenubarCB, SIGNAL(toggled(bool)),
2818 this, SIGNAL(changed()));
2819 connect(toggleScrollbarCB, SIGNAL(toggled(bool)),
2820 this, SIGNAL(changed()));
2821 connect(toggleStatusbarCB, SIGNAL(toggled(bool)),
2822 this, SIGNAL(changed()));
2823 connect(toggleToolbarsCB, SIGNAL(toggled(bool)),
2824 this, SIGNAL(changed()));
2828 void PrefEdit::on_fullscreenLimitCB_toggled(bool const state)
2830 fullscreenWidthSB->setEnabled(state);
2831 fullscreenWidthLA->setEnabled(state);
2836 void PrefEdit::on_citationSearchCB_toggled(bool const state)
2838 citationSearchLE->setEnabled(state);
2839 citationSearchLA->setEnabled(state);
2844 void PrefEdit::applyRC(LyXRC & rc) const
2846 rc.cursor_follows_scrollbar = cursorFollowsCB->isChecked();
2847 rc.scroll_below_document = scrollBelowCB->isChecked();
2848 rc.mac_like_cursor_movement = macLikeCursorMovementCB->isChecked();
2849 rc.ct_markup_copied = copyCTMarkupCB->isChecked();
2850 rc.sort_layouts = sortEnvironmentsCB->isChecked();
2851 rc.group_layouts = groupEnvironmentsCB->isChecked();
2852 switch (macroEditStyleCO->currentIndex()) {
2853 case 0: rc.macro_edit_style = LyXRC::MACRO_EDIT_INLINE_BOX; break;
2854 case 1: rc.macro_edit_style = LyXRC::MACRO_EDIT_INLINE; break;
2855 case 2: rc.macro_edit_style = LyXRC::MACRO_EDIT_LIST; break;
2857 rc.cursor_width = cursorWidthSB->value();
2858 rc.citation_search = citationSearchCB->isChecked();
2859 rc.citation_search_pattern = fromqstr(citationSearchLE->text());
2860 rc.full_screen_toolbars = toggleToolbarsCB->isChecked();
2861 rc.full_screen_scrollbar = toggleScrollbarCB->isChecked();
2862 rc.full_screen_statusbar = toggleStatusbarCB->isChecked();
2863 rc.full_screen_tabbar = toggleTabbarCB->isChecked();
2864 rc.full_screen_menubar = toggleMenubarCB->isChecked();
2865 rc.full_screen_width = fullscreenWidthSB->value();
2866 rc.full_screen_limit = fullscreenLimitCB->isChecked();
2870 void PrefEdit::updateRC(LyXRC const & rc)
2872 cursorFollowsCB->setChecked(rc.cursor_follows_scrollbar);
2873 scrollBelowCB->setChecked(rc.scroll_below_document);
2874 macLikeCursorMovementCB->setChecked(rc.mac_like_cursor_movement);
2875 copyCTMarkupCB->setChecked(rc.ct_markup_copied);
2876 sortEnvironmentsCB->setChecked(rc.sort_layouts);
2877 groupEnvironmentsCB->setChecked(rc.group_layouts);
2878 macroEditStyleCO->setCurrentIndex(rc.macro_edit_style);
2879 cursorWidthSB->setValue(rc.cursor_width);
2880 citationSearchCB->setChecked(rc.citation_search);
2881 citationSearchLE->setText(toqstr(rc.citation_search_pattern));
2882 citationSearchLE->setEnabled(rc.citation_search);
2883 citationSearchLA->setEnabled(rc.citation_search);
2884 toggleScrollbarCB->setChecked(rc.full_screen_scrollbar);
2885 toggleStatusbarCB->setChecked(rc.full_screen_statusbar);
2886 toggleToolbarsCB->setChecked(rc.full_screen_toolbars);
2887 toggleTabbarCB->setChecked(rc.full_screen_tabbar);
2888 toggleMenubarCB->setChecked(rc.full_screen_menubar);
2889 fullscreenWidthSB->setValue(rc.full_screen_width);
2890 fullscreenLimitCB->setChecked(rc.full_screen_limit);
2891 fullscreenWidthSB->setEnabled(rc.full_screen_limit);
2892 fullscreenWidthLA->setEnabled(rc.full_screen_limit);
2896 /////////////////////////////////////////////////////////////////////
2900 /////////////////////////////////////////////////////////////////////
2903 GuiShortcutDialog::GuiShortcutDialog(QWidget * parent) : QDialog(parent)
2905 Ui::shortcutUi::setupUi(this);
2906 QDialog::setModal(true);
2907 lfunLE->setValidator(new NoNewLineValidator(lfunLE));
2911 PrefShortcuts::PrefShortcuts(GuiPreferences * form)
2912 : PrefModule(catEditing, N_("Shortcuts"), form),
2913 editItem_(nullptr), mathItem_(nullptr), bufferItem_(nullptr), layoutItem_(nullptr),
2914 systemItem_(nullptr)
2918 shortcutsTW->setColumnCount(2);
2919 shortcutsTW->headerItem()->setText(0, qt_("Function"));
2920 shortcutsTW->headerItem()->setText(1, qt_("Shortcut"));
2921 shortcutsTW->setSortingEnabled(true);
2922 // Multi-selection can be annoying.
2923 // shortcutsTW->setSelectionMode(QAbstractItemView::MultiSelection);
2925 connect(bindFilePB, SIGNAL(clicked()),
2926 this, SLOT(selectBind()));
2927 connect(bindFileED, SIGNAL(textChanged(QString)),
2928 this, SIGNAL(changed()));
2930 shortcut_ = new GuiShortcutDialog(this);
2931 shortcut_bc_.setPolicy(ButtonPolicy::OkCancelPolicy);
2932 shortcut_bc_.setOK(shortcut_->buttonBox->button(QDialogButtonBox::Ok));
2933 shortcut_bc_.setCancel(shortcut_->buttonBox->button(QDialogButtonBox::Cancel));
2935 connect(shortcut_->buttonBox, SIGNAL(accepted()),
2936 this, SIGNAL(changed()));
2937 connect(shortcut_->buttonBox, SIGNAL(rejected()),
2938 shortcut_, SLOT(reject()));
2939 connect(shortcut_->clearPB, SIGNAL(clicked()),
2940 this, SLOT(shortcutClearPressed()));
2941 connect(shortcut_->removePB, SIGNAL(clicked()),
2942 this, SLOT(shortcutRemovePressed()));
2943 connect(shortcut_->buttonBox, SIGNAL(accepted()),
2944 this, SLOT(shortcutOkPressed()));
2945 connect(shortcut_->buttonBox, SIGNAL(rejected()),
2946 this, SLOT(shortcutCancelPressed()));
2950 void PrefShortcuts::applyRC(LyXRC & rc) const
2952 rc.bind_file = internal_path(fromqstr(bindFileED->text()));
2953 // write user_bind and user_unbind to .lyx/bind/user.bind
2954 FileName bind_dir(addPath(package().user_support().absFileName(), "bind"));
2955 if (!bind_dir.exists() && !bind_dir.createDirectory(0777)) {
2956 lyxerr << "LyX could not create the user bind directory '"
2957 << bind_dir << "'. All user-defined key bindings will be lost." << endl;
2960 if (!bind_dir.isDirWritable()) {
2961 lyxerr << "LyX could not write to the user bind directory '"
2962 << bind_dir << "'. All user-defined key bindings will be lost." << endl;
2965 FileName user_bind_file(bind_dir.absFileName() + "/user.bind");
2966 user_unbind_.write(user_bind_file.toFilesystemEncoding(), false, true);
2967 user_bind_.write(user_bind_file.toFilesystemEncoding(), true, false);
2968 // immediately apply the keybindings. Why this is not done before?
2969 // The good thing is that the menus are updated automatically.
2970 theTopLevelKeymap().clear();
2971 theTopLevelKeymap().read("site");
2972 theTopLevelKeymap().read(rc.bind_file, nullptr, KeyMap::Fallback);
2973 theTopLevelKeymap().read("user", nullptr, KeyMap::MissingOK);
2977 void PrefShortcuts::updateRC(LyXRC const & rc)
2979 bindFileED->setText(toqstr(external_path(rc.bind_file)));
2981 system_bind_.clear();
2983 user_unbind_.clear();
2984 system_bind_.read("site");
2985 system_bind_.read(rc.bind_file);
2986 // \unbind in user.bind is added to user_unbind_
2987 user_bind_.read("user", &user_unbind_, KeyMap::MissingOK);
2988 updateShortcutsTW();
2992 void PrefShortcuts::updateShortcutsTW()
2994 shortcutsTW->clear();
2996 editItem_ = new QTreeWidgetItem(shortcutsTW);
2997 editItem_->setText(0, qt_("Cursor, Mouse and Editing Functions"));
2998 editItem_->setFlags(editItem_->flags() & ~Qt::ItemIsSelectable);
3000 mathItem_ = new QTreeWidgetItem(shortcutsTW);
3001 mathItem_->setText(0, qt_("Mathematical Symbols"));
3002 mathItem_->setFlags(mathItem_->flags() & ~Qt::ItemIsSelectable);
3004 bufferItem_ = new QTreeWidgetItem(shortcutsTW);
3005 bufferItem_->setText(0, qt_("Document and Window"));
3006 bufferItem_->setFlags(bufferItem_->flags() & ~Qt::ItemIsSelectable);
3008 layoutItem_ = new QTreeWidgetItem(shortcutsTW);
3009 layoutItem_->setText(0, qt_("Font, Layouts and Textclasses"));
3010 layoutItem_->setFlags(layoutItem_->flags() & ~Qt::ItemIsSelectable);
3012 systemItem_ = new QTreeWidgetItem(shortcutsTW);
3013 systemItem_->setText(0, qt_("System and Miscellaneous"));
3014 systemItem_->setFlags(systemItem_->flags() & ~Qt::ItemIsSelectable);
3016 // listBindings(unbound=true) lists all bound and unbound lfuns
3017 // Items in this list is tagged by its source.
3018 KeyMap::BindingList bindinglist = system_bind_.listBindings(true,
3020 KeyMap::BindingList user_bindinglist = user_bind_.listBindings(false,
3022 KeyMap::BindingList user_unbindinglist = user_unbind_.listBindings(false,
3023 KeyMap::UserUnbind);
3024 bindinglist.insert(bindinglist.end(), user_bindinglist.begin(),
3025 user_bindinglist.end());
3026 bindinglist.insert(bindinglist.end(), user_unbindinglist.begin(),
3027 user_unbindinglist.end());
3029 KeyMap::BindingList::const_iterator it = bindinglist.begin();
3030 KeyMap::BindingList::const_iterator it_end = bindinglist.end();
3031 for (; it != it_end; ++it)
3032 insertShortcutItem(it->request, it->sequence, it->tag);
3034 shortcutsTW->sortItems(0, Qt::AscendingOrder);
3035 on_shortcutsTW_itemSelectionChanged();
3036 on_searchLE_textEdited();
3037 shortcutsTW->resizeColumnToContents(0);
3042 KeyMap::ItemType PrefShortcuts::itemType(QTreeWidgetItem & item)
3044 return static_cast<KeyMap::ItemType>(item.data(0, Qt::UserRole).toInt());
3049 bool PrefShortcuts::isAlwaysHidden(QTreeWidgetItem & item)
3051 // Hide rebound system settings that are empty
3052 return itemType(item) == KeyMap::UserUnbind && item.text(1).isEmpty();
3056 void PrefShortcuts::setItemType(QTreeWidgetItem * item, KeyMap::ItemType tag)
3058 item->setData(0, Qt::UserRole, QVariant(tag));
3062 case KeyMap::System:
3064 case KeyMap::UserBind:
3067 case KeyMap::UserUnbind:
3068 font.setStrikeOut(true);
3070 // this item is not displayed now.
3071 case KeyMap::UserExtraUnbind:
3072 font.setStrikeOut(true);
3075 item->setHidden(isAlwaysHidden(*item));
3076 item->setFont(1, font);
3080 QTreeWidgetItem * PrefShortcuts::insertShortcutItem(FuncRequest const & lfun,
3081 KeySequence const & seq, KeyMap::ItemType tag)
3083 FuncCode const action = lfun.action();
3084 string const action_name = lyxaction.getActionName(action);
3085 QString const lfun_name = toqstr(from_utf8(action_name)
3086 + ' ' + lfun.argument());
3087 QString const shortcut = toqstr(seq.print(KeySequence::ForGui));
3089 QTreeWidgetItem * newItem = nullptr;
3090 // for unbind items, try to find an existing item in the system bind list
3091 if (tag == KeyMap::UserUnbind) {
3092 QList<QTreeWidgetItem*> const items = shortcutsTW->findItems(shortcut,
3093 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 1);
3094 for (auto const & item : items) {
3095 if (item->text(0) == lfun_name || lfun == FuncRequest::unknown) {
3100 // if not found, this unbind item is KeyMap::UserExtraUnbind
3101 // Such an item is not displayed to avoid confusion (what is
3102 // unmatched removed?).
3108 switch(lyxaction.getActionType(action)) {
3109 case LyXAction::Hidden:
3111 case LyXAction::Edit:
3112 newItem = new QTreeWidgetItem(editItem_);
3114 case LyXAction::Math:
3115 newItem = new QTreeWidgetItem(mathItem_);
3117 case LyXAction::Buffer:
3118 newItem = new QTreeWidgetItem(bufferItem_);
3120 case LyXAction::Layout:
3121 newItem = new QTreeWidgetItem(layoutItem_);
3123 case LyXAction::System:
3124 newItem = new QTreeWidgetItem(systemItem_);
3127 // this should not happen
3128 newItem = new QTreeWidgetItem(shortcutsTW);
3130 newItem->setText(0, lfun_name);
3131 newItem->setText(1, shortcut);
3134 // record BindFile representation to recover KeySequence when needed.
3135 newItem->setData(1, Qt::UserRole, toqstr(seq.print(KeySequence::BindFile)));
3136 setItemType(newItem, tag);
3141 void PrefShortcuts::on_shortcutsTW_itemSelectionChanged()
3143 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
3144 removePB->setEnabled(!items.isEmpty() && !items[0]->text(1).isEmpty());
3145 modifyPB->setEnabled(!items.isEmpty());
3146 if (items.isEmpty())
3149 if (itemType(*items[0]) == KeyMap::UserUnbind)
3150 removePB->setText(qt_("Res&tore"));
3152 removePB->setText(qt_("Remo&ve"));
3156 void PrefShortcuts::on_shortcutsTW_itemDoubleClicked()
3162 void PrefShortcuts::modifyShortcut()
3164 QTreeWidgetItem * item = shortcutsTW->currentItem();
3165 if (item->flags() & Qt::ItemIsSelectable) {
3166 shortcut_->lfunLE->setText(item->text(0));
3167 save_lfun_ = item->text(0).trimmed();
3168 shortcut_->shortcutWG->setText(item->text(1));
3170 seq.parse(fromqstr(item->data(1, Qt::UserRole).toString()));
3171 shortcut_->shortcutWG->setKeySequence(seq);
3172 shortcut_->shortcutWG->setFocus();
3178 void PrefShortcuts::unhideEmpty(QString const & lfun, bool select)
3180 // list of items that match lfun
3181 QList<QTreeWidgetItem*> items = shortcutsTW->findItems(lfun,
3182 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 0);
3183 for (auto const & item : items) {
3184 if (isAlwaysHidden(*item)) {
3185 setItemType(item, KeyMap::System);
3187 shortcutsTW->setCurrentItem(item);
3194 void PrefShortcuts::removeShortcut()
3196 // it seems that only one item can be selected, but I am
3197 // removing all selected items anyway.
3198 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
3199 for (auto & item : items) {
3200 string shortcut = fromqstr(item->data(1, Qt::UserRole).toString());
3201 string lfun = fromqstr(item->text(0));
3202 FuncRequest const func = lyxaction.lookupFunc(lfun);
3204 switch (itemType(*item)) {
3205 case KeyMap::System: {
3206 // for system bind, we do not touch the item
3207 // but add an user unbind item
3208 user_unbind_.bind(shortcut, func);
3209 setItemType(item, KeyMap::UserUnbind);
3210 removePB->setText(qt_("Res&tore"));
3213 case KeyMap::UserBind: {
3214 // for user_bind, we remove this bind
3215 QTreeWidgetItem * parent = item->parent();
3216 int itemIdx = parent->indexOfChild(item);
3217 parent->takeChild(itemIdx);
3219 shortcutsTW->scrollToItem(parent->child(itemIdx - 1));
3221 shortcutsTW->scrollToItem(parent);
3222 user_bind_.unbind(shortcut, func);
3223 // If this user binding hid an empty system binding, unhide the
3224 // latter and select it.
3225 unhideEmpty(item->text(0), true);
3228 case KeyMap::UserUnbind: {
3229 // for user_unbind, we remove the unbind, and the item
3230 // become KeyMap::System again.
3232 seq.parse(shortcut);
3233 // Ask the user to replace current binding
3234 if (!validateNewShortcut(func, seq, QString()))
3236 user_unbind_.unbind(shortcut, func);
3237 setItemType(item, KeyMap::System);
3238 removePB->setText(qt_("Remo&ve"));
3241 case KeyMap::UserExtraUnbind: {
3242 // for user unbind that is not in system bind file,
3243 // remove this unbind file
3244 QTreeWidgetItem * parent = item->parent();
3245 parent->takeChild(parent->indexOfChild(item));
3246 user_unbind_.unbind(shortcut, func);
3253 void PrefShortcuts::deactivateShortcuts(QList<QTreeWidgetItem*> const & items)
3255 for (auto item : items) {
3256 string shortcut = fromqstr(item->data(1, Qt::UserRole).toString());
3257 string lfun = fromqstr(item->text(0));
3258 FuncRequest const func = lyxaction.lookupFunc(lfun);
3260 switch (itemType(*item)) {
3261 case KeyMap::System:
3262 // for system bind, we do not touch the item
3263 // but add an user unbind item
3264 user_unbind_.bind(shortcut, func);
3265 setItemType(item, KeyMap::UserUnbind);
3268 case KeyMap::UserBind: {
3269 // for user_bind, we remove this bind
3270 QTreeWidgetItem * parent = item->parent();
3271 int itemIdx = parent->indexOfChild(item);
3272 parent->takeChild(itemIdx);
3273 user_bind_.unbind(shortcut, func);
3274 unhideEmpty(item->text(0), false);
3284 void PrefShortcuts::selectBind()
3286 QString file = form_->browsebind(internalPath(bindFileED->text()));
3287 if (!file.isEmpty()) {
3288 bindFileED->setText(file);
3289 system_bind_ = KeyMap();
3290 system_bind_.read(fromqstr(file));
3291 updateShortcutsTW();
3296 void PrefShortcuts::on_modifyPB_pressed()
3302 void PrefShortcuts::on_newPB_pressed()
3304 shortcut_->lfunLE->clear();
3305 shortcut_->shortcutWG->reset();
3306 save_lfun_ = QString();
3311 void PrefShortcuts::on_removePB_pressed()
3318 void PrefShortcuts::on_searchLE_textEdited()
3320 if (searchLE->text().isEmpty()) {
3321 // show all hidden items
3322 QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Hidden);
3324 (*it)->setHidden(isAlwaysHidden(**it));
3325 // close all categories
3326 for (int i = 0; i < shortcutsTW->topLevelItemCount(); ++i)
3327 shortcutsTW->collapseItem(shortcutsTW->topLevelItem(i));
3330 // search both columns
3331 QList<QTreeWidgetItem *> matched = shortcutsTW->findItems(searchLE->text(),
3332 Qt::MatchFlags(Qt::MatchContains | Qt::MatchRecursive), 0);
3333 matched += shortcutsTW->findItems(searchLE->text(),
3334 Qt::MatchFlags(Qt::MatchContains | Qt::MatchRecursive), 1);
3336 // hide everyone (to avoid searching in matched QList repeatedly
3337 QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Selectable);
3339 (*it++)->setHidden(true);
3340 // show matched items
3341 for (auto & item : matched)
3342 if (!isAlwaysHidden(*item)) {
3343 item->setHidden(false);
3345 item->parent()->setExpanded(true);
3350 docstring makeCmdString(FuncRequest const & f)
3352 docstring actionStr = from_ascii(lyxaction.getActionName(f.action()));
3353 if (!f.argument().empty())
3354 actionStr += " " + f.argument();
3359 FuncRequest PrefShortcuts::currentBinding(KeySequence const & k)
3361 FuncRequest res = user_bind_.getBinding(k);
3362 if (res.action() != LFUN_UNKNOWN_ACTION)
3364 res = system_bind_.getBinding(k);
3365 // Check if it is unbound. Note: user_unbind_ can only unbind one
3366 // FuncRequest per key sequence.
3367 if (user_unbind_.getBinding(k) == res)
3368 return FuncRequest::unknown;
3373 bool PrefShortcuts::validateNewShortcut(FuncRequest const & func,
3374 KeySequence const & k,
3375 QString const & lfun_to_modify)
3377 if (func.action() == LFUN_UNKNOWN_ACTION) {
3378 Alert::error(_("Failed to create shortcut"),
3379 _("Unknown or invalid LyX function"));
3383 // It is not currently possible to bind Hidden lfuns such as self-insert. In
3384 // the future, to remove this limitation, see GuiPrefs::insertShortcutItem
3385 // and how it is used in GuiPrefs::shortcutOkPressed.
3386 if (lyxaction.getActionType(func.action()) == LyXAction::Hidden) {
3387 Alert::error(_("Failed to create shortcut"),
3388 _("This LyX function is hidden and cannot be bound."));
3392 if (k.length() == 0) {
3393 Alert::error(_("Failed to create shortcut"),
3394 _("Invalid or empty key sequence"));
3398 FuncRequest oldBinding = currentBinding(k);
3399 if (oldBinding == func)
3400 // nothing to change
3403 // make sure this key isn't already bound---and, if so, prompt user
3404 // (exclude the lfun the user already wants to modify)
3405 docstring const action_string = makeCmdString(oldBinding);
3406 if (oldBinding.action() != LFUN_UNKNOWN_ACTION
3407 && lfun_to_modify != toqstr(action_string)) {
3408 docstring const new_action_string = makeCmdString(func);
3409 docstring const text = bformat(_("Shortcut `%1$s' is already bound to "
3411 "Are you sure you want to unbind the "
3412 "current shortcut and bind it to %3$s?"),
3413 k.print(KeySequence::ForGui), action_string,
3415 int ret = Alert::prompt(_("Redefine shortcut?"),
3416 text, 0, 1, _("&Redefine"), _("&Cancel"));
3419 QString const sequence_text = toqstr(k.print(KeySequence::ForGui));
3420 QList<QTreeWidgetItem*> items = shortcutsTW->findItems(sequence_text,
3421 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 1);
3422 deactivateShortcuts(items);
3428 void PrefShortcuts::shortcutOkPressed()
3430 QString const new_lfun = shortcut_->lfunLE->text();
3431 FuncRequest const func = lyxaction.lookupFunc(fromqstr(new_lfun));
3432 KeySequence k = shortcut_->shortcutWG->getKeySequence();
3434 // save_lfun_ contains the text of the lfun to modify, if the user clicked
3435 // "modify", or is empty if they clicked "new" (which I do not really like)
3436 if (!validateNewShortcut(func, k, save_lfun_))
3439 if (!save_lfun_.isEmpty()) {
3440 // real modification of the lfun's shortcut,
3441 // so remove the previous one
3442 QList<QTreeWidgetItem*> to_modify = shortcutsTW->selectedItems();
3443 deactivateShortcuts(to_modify);
3446 shortcut_->accept();
3448 QTreeWidgetItem * item = insertShortcutItem(func, k, KeyMap::UserBind);
3450 user_bind_.bind(&k, func);
3451 shortcutsTW->sortItems(0, Qt::AscendingOrder);
3453 item->parent()->setExpanded(true);
3454 shortcutsTW->setCurrentItem(item);
3455 shortcutsTW->scrollToItem(item);
3457 Alert::error(_("Failed to create shortcut"),
3458 _("Can not insert shortcut to the list"));
3464 void PrefShortcuts::shortcutCancelPressed()
3466 shortcut_->shortcutWG->reset();
3470 void PrefShortcuts::shortcutClearPressed()
3472 shortcut_->shortcutWG->reset();
3476 void PrefShortcuts::shortcutRemovePressed()
3478 shortcut_->shortcutWG->removeFromSequence();
3482 /////////////////////////////////////////////////////////////////////
3486 /////////////////////////////////////////////////////////////////////
3488 PrefIdentity::PrefIdentity(GuiPreferences * form)
3489 : PrefModule(QString(), N_("Identity"), form)
3493 connect(nameED, SIGNAL(textChanged(QString)),
3494 this, SIGNAL(changed()));
3495 connect(emailED, SIGNAL(textChanged(QString)),
3496 this, SIGNAL(changed()));
3497 connect(initialsED, SIGNAL(textChanged(QString)),
3498 this, SIGNAL(changed()));
3500 nameED->setValidator(new NoNewLineValidator(nameED));
3501 emailED->setValidator(new NoNewLineValidator(emailED));
3502 initialsED->setValidator(new NoNewLineValidator(initialsED));
3506 void PrefIdentity::applyRC(LyXRC & rc) const
3508 rc.user_name = fromqstr(nameED->text());
3509 rc.user_email = fromqstr(emailED->text());
3510 rc.user_initials = fromqstr(initialsED->text());
3514 void PrefIdentity::updateRC(LyXRC const & rc)
3516 nameED->setText(toqstr(rc.user_name));
3517 emailED->setText(toqstr(rc.user_email));
3518 initialsED->setText(toqstr(rc.user_initials));
3523 /////////////////////////////////////////////////////////////////////
3527 /////////////////////////////////////////////////////////////////////
3529 GuiPreferences::GuiPreferences(GuiView & lv)
3530 : GuiDialog(lv, "prefs", qt_("Preferences"))
3534 QDialog::setModal(false);
3536 connect(buttonBox, SIGNAL(clicked(QAbstractButton *)),
3537 this, SLOT(slotButtonBox(QAbstractButton *)));
3539 addModule(new PrefUserInterface(this));
3540 addModule(new PrefDocHandling(this));
3541 addModule(new PrefEdit(this));
3542 addModule(new PrefShortcuts(this));
3543 PrefScreenFonts * screenfonts = new PrefScreenFonts(this);
3544 connect(this, SIGNAL(prefsApplied(LyXRC const &)),
3545 screenfonts, SLOT(updateScreenFontSizes(LyXRC const &)));
3546 addModule(screenfonts);
3547 addModule(new PrefColors(this));
3548 addModule(new PrefDisplay(this));
3549 addModule(new PrefInput(this));
3550 addModule(new PrefCompletion(this));
3552 addModule(new PrefPaths(this));
3554 addModule(new PrefIdentity(this));
3556 addModule(new PrefLanguage(this));
3557 addModule(new PrefSpellchecker(this));
3559 PrefOutput * output = new PrefOutput(this);
3561 addModule(new PrefLatex(this));
3563 PrefConverters * converters = new PrefConverters(this);
3564 PrefFileformats * formats = new PrefFileformats(this);
3565 connect(formats, SIGNAL(formatsChanged()),
3566 converters, SLOT(updateGui()));
3567 addModule(converters);
3570 prefsPS->setCurrentPanel("User Interface");
3571 // FIXME: hack to work around resizing bug in Qt >= 4.2
3572 // bug verified with Qt 4.2.{0-3} (JSpitzm)
3573 #if QT_VERSION >= 0x040200
3574 prefsPS->updateGeometry();
3577 bc().setPolicy(ButtonPolicy::PreferencesPolicy);
3578 bc().setOK(buttonBox->button(QDialogButtonBox::Ok));
3579 bc().setApply(buttonBox->button(QDialogButtonBox::Apply));
3580 bc().setCancel(buttonBox->button(QDialogButtonBox::Cancel));
3581 bc().setRestore(buttonBox->button(QDialogButtonBox::Reset));
3583 guilyxfiles_ = new GuiLyXFiles(lv);
3584 connect(guilyxfiles_, SIGNAL(fileSelected(QString)),
3585 this, SLOT(slotFileSelected(QString)));
3589 void GuiPreferences::addModule(PrefModule * module)
3591 LASSERT(module, return);
3592 if (module->category().isEmpty())
3593 prefsPS->addPanel(module, module->title());
3595 prefsPS->addPanel(module, module->title(), module->category());
3596 connect(module, SIGNAL(changed()), this, SLOT(change_adaptor()));
3597 modules_.push_back(module);
3601 void GuiPreferences::change_adaptor()
3607 void GuiPreferences::applyRC(LyXRC & rc) const
3609 size_t end = modules_.size();
3610 for (size_t i = 0; i != end; ++i)
3611 modules_[i]->applyRC(rc);
3615 void GuiPreferences::updateRC(LyXRC const & rc)
3617 size_t const end = modules_.size();
3618 for (size_t i = 0; i != end; ++i)
3619 modules_[i]->updateRC(rc);
3623 void GuiPreferences::applyView()
3629 bool GuiPreferences::initialiseParams(string const &)
3632 formats_ = theFormats();
3633 converters_ = theConverters();
3634 converters_.update(formats_);
3635 movers_ = theMovers();
3639 // Make sure that the bc is in the INITIAL state
3640 if (bc().policy().buttonStatus(ButtonPolicy::RESTORE))
3647 void GuiPreferences::dispatchParams()
3650 rc_.write(ss, true);
3651 dispatch(FuncRequest(LFUN_LYXRC_APPLY, ss.str()));
3652 // issue prefsApplied signal. This will update the
3653 // localized screen font sizes.
3655 // FIXME: these need lfuns
3657 Author const & author =
3658 Author(from_utf8(rc_.user_name), from_utf8(rc_.user_email),
3659 from_utf8(rc_.user_initials));
3660 theBufferList().recordCurrentAuthor(author);
3662 theFormats() = formats_;
3664 theConverters() = converters_;
3665 theConverters().update(formats_);
3666 theConverters().buildGraph();
3667 theBufferList().invalidateConverterCache();
3669 theMovers() = movers_;
3671 for (string const & color : colors_)
3672 dispatch(FuncRequest(LFUN_SET_COLOR, color));
3676 if (!tempSaveCB->isChecked())
3677 dispatch(FuncRequest(LFUN_PREFERENCES_SAVE));
3681 void GuiPreferences::setColor(ColorCode col, QString const & hex)
3683 colors_.push_back(lcolor.getLyXName(col) + ' ' + fromqstr(hex));
3687 void GuiPreferences::slotFileSelected(QString const file)
3693 QString GuiPreferences::browseLibFile(QString const & dir,
3694 QString const & name, QString const & ext)
3698 guilyxfiles_->passParams(fromqstr(dir));
3699 guilyxfiles_->selectItem(name);
3700 guilyxfiles_->exec();
3702 QString const result = uifile_;
3704 // remove the extension if it is the default one
3705 QString noextresult;
3706 if (getExtension(result) == ext)
3707 noextresult = removeExtension(result);
3709 noextresult = result;
3711 // remove the directory, if it is the default one
3712 QString const file = onlyFileName(noextresult);
3713 if (toqstr(libFileSearch(dir, file, ext).absFileName()) == result)
3720 QString GuiPreferences::browsebind(QString const & file)
3722 return browseLibFile("bind", file, "bind");
3726 QString GuiPreferences::browseUI(QString const & file)
3728 return browseLibFile("ui", file, "ui");
3732 QString GuiPreferences::browsekbmap(QString const & file)
3734 return browseLibFile("kbd", file, "kmap");
3738 QString GuiPreferences::browse(QString const & file,
3739 QString const & title) const
3741 return browseFile(file, title, QStringList(), true);
3745 } // namespace frontend
3748 #include "moc_GuiPrefs.cpp"