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 connect(screenRomanCO, SIGNAL(activated(QString)),
919 this, SLOT(selectRoman(QString)));
920 connect(screenSansCO, SIGNAL(activated(QString)),
921 this, SLOT(selectSans(QString)));
922 connect(screenTypewriterCO, SIGNAL(activated(QString)),
923 this, SLOT(selectTypewriter(QString)));
925 QFontDatabase fontdb;
926 QStringList families(fontdb.families());
927 for (auto const & family : families) {
928 screenRomanCO->addItem(family);
929 screenSansCO->addItem(family);
930 screenTypewriterCO->addItem(family);
932 connect(screenRomanCO, SIGNAL(activated(QString)),
933 this, SIGNAL(changed()));
934 connect(screenSansCO, SIGNAL(activated(QString)),
935 this, SIGNAL(changed()));
936 connect(screenTypewriterCO, SIGNAL(activated(QString)),
937 this, SIGNAL(changed()));
938 connect(screenZoomSB, SIGNAL(valueChanged(int)),
939 this, SIGNAL(changed()));
940 connect(screenTinyED, SIGNAL(textChanged(QString)),
941 this, SIGNAL(changed()));
942 connect(screenSmallestED, SIGNAL(textChanged(QString)),
943 this, SIGNAL(changed()));
944 connect(screenSmallerED, SIGNAL(textChanged(QString)),
945 this, SIGNAL(changed()));
946 connect(screenSmallED, SIGNAL(textChanged(QString)),
947 this, SIGNAL(changed()));
948 connect(screenNormalED, SIGNAL(textChanged(QString)),
949 this, SIGNAL(changed()));
950 connect(screenLargeED, SIGNAL(textChanged(QString)),
951 this, SIGNAL(changed()));
952 connect(screenLargerED, SIGNAL(textChanged(QString)),
953 this, SIGNAL(changed()));
954 connect(screenLargestED, SIGNAL(textChanged(QString)),
955 this, SIGNAL(changed()));
956 connect(screenHugeED, SIGNAL(textChanged(QString)),
957 this, SIGNAL(changed()));
958 connect(screenHugerED, SIGNAL(textChanged(QString)),
959 this, SIGNAL(changed()));
961 screenTinyED->setValidator(new QDoubleValidator(screenTinyED));
962 screenSmallestED->setValidator(new QDoubleValidator(screenSmallestED));
963 screenSmallerED->setValidator(new QDoubleValidator(screenSmallerED));
964 screenSmallED->setValidator(new QDoubleValidator(screenSmallED));
965 screenNormalED->setValidator(new QDoubleValidator(screenNormalED));
966 screenLargeED->setValidator(new QDoubleValidator(screenLargeED));
967 screenLargerED->setValidator(new QDoubleValidator(screenLargerED));
968 screenLargestED->setValidator(new QDoubleValidator(screenLargestED));
969 screenHugeED->setValidator(new QDoubleValidator(screenHugeED));
970 screenHugerED->setValidator(new QDoubleValidator(screenHugerED));
974 void PrefScreenFonts::applyRC(LyXRC & rc) const
976 LyXRC const oldrc = rc;
978 parseFontName(screenRomanCO->currentText(),
979 rc.roman_font_name, rc.roman_font_foundry);
980 parseFontName(screenSansCO->currentText(),
981 rc.sans_font_name, rc.sans_font_foundry);
982 parseFontName(screenTypewriterCO->currentText(),
983 rc.typewriter_font_name, rc.typewriter_font_foundry);
985 rc.defaultZoom = screenZoomSB->value();
986 rc.font_sizes[TINY_SIZE] = widgetToDoubleStr(screenTinyED);
987 rc.font_sizes[SCRIPT_SIZE] = widgetToDoubleStr(screenSmallestED);
988 rc.font_sizes[FOOTNOTE_SIZE] = widgetToDoubleStr(screenSmallerED);
989 rc.font_sizes[SMALL_SIZE] = widgetToDoubleStr(screenSmallED);
990 rc.font_sizes[NORMAL_SIZE] = widgetToDoubleStr(screenNormalED);
991 rc.font_sizes[LARGE_SIZE] = widgetToDoubleStr(screenLargeED);
992 rc.font_sizes[LARGER_SIZE] = widgetToDoubleStr(screenLargerED);
993 rc.font_sizes[LARGEST_SIZE] = widgetToDoubleStr(screenLargestED);
994 rc.font_sizes[HUGE_SIZE] = widgetToDoubleStr(screenHugeED);
995 rc.font_sizes[HUGER_SIZE] = widgetToDoubleStr(screenHugerED);
999 void PrefScreenFonts::updateRC(LyXRC const & rc)
1001 setComboxFont(screenRomanCO, rc.roman_font_name,
1002 rc.roman_font_foundry);
1003 setComboxFont(screenSansCO, rc.sans_font_name,
1004 rc.sans_font_foundry);
1005 setComboxFont(screenTypewriterCO, rc.typewriter_font_name,
1006 rc.typewriter_font_foundry);
1008 selectRoman(screenRomanCO->currentText());
1009 selectSans(screenSansCO->currentText());
1010 selectTypewriter(screenTypewriterCO->currentText());
1012 screenZoomSB->setValue(rc.defaultZoom);
1013 updateScreenFontSizes(rc);
1017 void PrefScreenFonts::updateScreenFontSizes(LyXRC const & rc)
1019 doubleToWidget(screenTinyED, rc.font_sizes[TINY_SIZE]);
1020 doubleToWidget(screenSmallestED, rc.font_sizes[SCRIPT_SIZE]);
1021 doubleToWidget(screenSmallerED, rc.font_sizes[FOOTNOTE_SIZE]);
1022 doubleToWidget(screenSmallED, rc.font_sizes[SMALL_SIZE]);
1023 doubleToWidget(screenNormalED, rc.font_sizes[NORMAL_SIZE]);
1024 doubleToWidget(screenLargeED, rc.font_sizes[LARGE_SIZE]);
1025 doubleToWidget(screenLargerED, rc.font_sizes[LARGER_SIZE]);
1026 doubleToWidget(screenLargestED, rc.font_sizes[LARGEST_SIZE]);
1027 doubleToWidget(screenHugeED, rc.font_sizes[HUGE_SIZE]);
1028 doubleToWidget(screenHugerED, rc.font_sizes[HUGER_SIZE]);
1032 void PrefScreenFonts::selectRoman(const QString & name)
1034 screenRomanFE->set(QFont(name), name);
1038 void PrefScreenFonts::selectSans(const QString & name)
1040 screenSansFE->set(QFont(name), name);
1044 void PrefScreenFonts::selectTypewriter(const QString & name)
1046 screenTypewriterFE->set(QFont(name), name);
1050 /////////////////////////////////////////////////////////////////////
1054 /////////////////////////////////////////////////////////////////////
1057 PrefColors::PrefColors(GuiPreferences * form)
1058 : PrefModule(catLookAndFeel, N_("Colors"), form)
1062 // FIXME: all of this initialization should be put into the controller.
1063 // See http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg113301.html
1064 // for some discussion of why that is not trivial.
1065 QPixmap icon(32, 32);
1066 for (int i = 0; i < Color_ignore; ++i) {
1067 ColorCode lc = static_cast<ColorCode>(i);
1068 if (lc == Color_none
1069 || lc == Color_black
1070 || lc == Color_white
1072 || lc == Color_brown
1074 || lc == Color_darkgray
1076 || lc == Color_green
1077 || lc == Color_lightgray
1079 || lc == Color_magenta
1080 || lc == Color_olive
1081 || lc == Color_orange
1083 || lc == Color_purple
1086 || lc == Color_violet
1087 || lc == Color_yellow
1088 || lc == Color_inherit
1089 || lc == Color_ignore)
1091 lcolors_.push_back(lc);
1093 sort(lcolors_.begin(), lcolors_.end(), ColorSorter);
1094 vector<ColorCode>::const_iterator cit = lcolors_.begin();
1095 vector<ColorCode>::const_iterator const end = lcolors_.end();
1096 for (; cit != end; ++cit) {
1097 (void) new QListWidgetItem(QIcon(icon),
1098 toqstr(lcolor.getGUIName(*cit)), lyxObjectsLW);
1100 curcolors_.resize(lcolors_.size());
1101 newcolors_.resize(lcolors_.size());
1102 // End initialization
1104 connect(colorChangePB, SIGNAL(clicked()),
1105 this, SLOT(changeColor()));
1106 connect(colorResetPB, SIGNAL(clicked()),
1107 this, SLOT(resetColor()));
1108 connect(colorResetAllPB, SIGNAL(clicked()),
1109 this, SLOT(resetAllColor()));
1110 connect(lyxObjectsLW, SIGNAL(itemSelectionChanged()),
1111 this, SLOT(changeLyxObjectsSelection()));
1112 connect(lyxObjectsLW, SIGNAL(itemActivated(QListWidgetItem*)),
1113 this, SLOT(changeColor()));
1114 connect(syscolorsCB, SIGNAL(toggled(bool)),
1115 this, SIGNAL(changed()));
1116 connect(syscolorsCB, SIGNAL(toggled(bool)),
1117 this, SLOT(changeSysColor()));
1121 void PrefColors::applyRC(LyXRC & rc) const
1125 for (unsigned int i = 0; i < lcolors_.size(); ++i)
1126 if (curcolors_[i] != newcolors_[i])
1127 form_->setColor(lcolors_[i], newcolors_[i]);
1128 rc.use_system_colors = syscolorsCB->isChecked();
1130 if (oldrc.use_system_colors != rc.use_system_colors)
1131 guiApp->colorCache().clear();
1135 void PrefColors::updateRC(LyXRC const & rc)
1137 for (size_type i = 0; i < lcolors_.size(); ++i) {
1138 QColor color = QColor(guiApp->colorCache().get(lcolors_[i], false));
1139 QPixmap coloritem(32, 32);
1140 coloritem.fill(color);
1141 lyxObjectsLW->item(int(i))->setIcon(QIcon(coloritem));
1142 newcolors_[i] = curcolors_[i] = color.name();
1144 syscolorsCB->setChecked(rc.use_system_colors);
1145 changeLyxObjectsSelection();
1147 setDisabledResets();
1151 void PrefColors::changeColor()
1153 int const row = lyxObjectsLW->currentRow();
1159 QString const color = newcolors_[size_t(row)];
1160 QColor const c = QColorDialog::getColor(QColor(color), qApp->focusWidget());
1162 if (setColor(row, c, color)) {
1163 setDisabledResets();
1170 void PrefColors::resetColor()
1172 int const row = lyxObjectsLW->currentRow();
1178 QString const color = newcolors_[size_t(row)];
1179 QColor const c = getDefaultColorByRow(row);
1181 if (setColor(row, c, color)) {
1182 setDisabledResets();
1189 void PrefColors::resetAllColor()
1191 bool isChanged = false;
1193 colorResetAllPB->setDisabled(true);
1195 for (int irow = 0, count = lyxObjectsLW->count(); irow < count; ++irow) {
1196 QString const color = newcolors_[size_t(irow)];
1197 QColor const c = getDefaultColorByRow(irow);
1199 if (setColor(irow, c, color))
1204 setDisabledResets();
1211 bool PrefColors::setColor(int const row, QColor const & new_color,
1212 QString const & old_color)
1214 if (new_color.isValid() && new_color.name() != old_color) {
1215 newcolors_[size_t(row)] = new_color.name();
1216 QPixmap coloritem(32, 32);
1217 coloritem.fill(new_color);
1218 lyxObjectsLW->item(row)->setIcon(QIcon(coloritem));
1225 void PrefColors::setDisabledResets()
1227 int const row = lyxObjectsLW->currentRow();
1228 // set disable reset buttons ...
1230 colorResetPB->setDisabled(isDefaultColor(row, newcolors_[size_t(row)]));
1232 colorResetAllPB->setDisabled(true);
1234 // ... in between process qt events to give quicker visual feedback to the user ...
1235 guiApp->processEvents();
1237 // ... set disable Reset All button
1238 for (int irow = 0, count = lyxObjectsLW->count(); irow < count; ++irow) {
1239 if (!isDefaultColor(irow, newcolors_[size_t(irow)])) {
1240 colorResetAllPB->setDisabled(false);
1241 // the break condition might hide performance issues
1242 // if a non-default color is at the top of the list
1249 bool PrefColors::isDefaultColor(int const row, QString const & color)
1251 return color == getDefaultColorByRow(row).name();
1255 QColor PrefColors::getDefaultColorByRow(int const row)
1257 ColorSet const defaultcolor;
1258 return defaultcolor.getX11HexName(lcolors_[size_t(row)],
1259 guiApp->colorCache().isDarkMode()).c_str();
1263 void PrefColors::changeSysColor()
1265 for (int row = 0 ; row < lyxObjectsLW->count() ; ++row) {
1266 // skip colors that are taken from system palette
1267 bool const disable = syscolorsCB->isChecked()
1268 && guiApp->colorCache().isSystem(lcolors_[size_t(row)]);
1270 QListWidgetItem * const item = lyxObjectsLW->item(row);
1271 Qt::ItemFlags const flags = item->flags();
1274 item->setFlags(flags & ~Qt::ItemIsEnabled);
1276 item->setFlags(flags | Qt::ItemIsEnabled);
1281 void PrefColors::changeLyxObjectsSelection()
1283 int currentRow = lyxObjectsLW->currentRow();
1284 colorChangePB->setDisabled(currentRow < 0);
1287 colorResetPB->setDisabled(true);
1289 colorResetPB->setDisabled(
1290 isDefaultColor(currentRow, newcolors_[size_t(currentRow)]));
1294 /////////////////////////////////////////////////////////////////////
1298 /////////////////////////////////////////////////////////////////////
1300 PrefDisplay::PrefDisplay(GuiPreferences * form)
1301 : PrefModule(catLookAndFeel, N_("Display"), form)
1304 connect(displayGraphicsCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1305 connect(instantPreviewCO, SIGNAL(activated(int)), this, SIGNAL(changed()));
1306 connect(previewSizeSB, SIGNAL(valueChanged(double)), this, SIGNAL(changed()));
1307 connect(paragraphMarkerCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1308 connect(ctAdditionsUnderlinedCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1312 void PrefDisplay::on_instantPreviewCO_currentIndexChanged(int index)
1314 previewSizeSB->setEnabled(index != 0);
1318 void PrefDisplay::applyRC(LyXRC & rc) const
1320 switch (instantPreviewCO->currentIndex()) {
1322 rc.preview = LyXRC::PREVIEW_OFF;
1325 rc.preview = LyXRC::PREVIEW_NO_MATH;
1328 rc.preview = LyXRC::PREVIEW_ON;
1332 rc.display_graphics = displayGraphicsCB->isChecked();
1333 rc.preview_scale_factor = previewSizeSB->value();
1334 rc.paragraph_markers = paragraphMarkerCB->isChecked();
1335 rc.ct_additions_underlined = ctAdditionsUnderlinedCB->isChecked();
1337 // FIXME!! The graphics cache no longer has a changeDisplay method.
1339 if (old_value != rc.display_graphics) {
1340 graphics::GCache & gc = graphics::GCache::get();
1347 void PrefDisplay::updateRC(LyXRC const & rc)
1349 switch (rc.preview) {
1350 case LyXRC::PREVIEW_OFF:
1351 instantPreviewCO->setCurrentIndex(0);
1353 case LyXRC::PREVIEW_NO_MATH :
1354 instantPreviewCO->setCurrentIndex(1);
1356 case LyXRC::PREVIEW_ON :
1357 instantPreviewCO->setCurrentIndex(2);
1361 displayGraphicsCB->setChecked(rc.display_graphics);
1362 previewSizeSB->setValue(rc.preview_scale_factor);
1363 paragraphMarkerCB->setChecked(rc.paragraph_markers);
1364 ctAdditionsUnderlinedCB->setChecked(rc.ct_additions_underlined);
1365 previewSizeSB->setEnabled(
1367 && rc.preview != LyXRC::PREVIEW_OFF);
1371 /////////////////////////////////////////////////////////////////////
1375 /////////////////////////////////////////////////////////////////////
1377 PrefPaths::PrefPaths(GuiPreferences * form)
1378 : PrefModule(QString(), N_("Paths"), form)
1382 connect(workingDirPB, SIGNAL(clicked()), this, SLOT(selectWorkingdir()));
1383 connect(workingDirED, SIGNAL(textChanged(QString)),
1384 this, SIGNAL(changed()));
1386 connect(templateDirPB, SIGNAL(clicked()), this, SLOT(selectTemplatedir()));
1387 connect(templateDirED, SIGNAL(textChanged(QString)),
1388 this, SIGNAL(changed()));
1390 connect(exampleDirPB, SIGNAL(clicked()), this, SLOT(selectExampledir()));
1391 connect(exampleDirED, SIGNAL(textChanged(QString)),
1392 this, SIGNAL(changed()));
1394 connect(backupDirPB, SIGNAL(clicked()), this, SLOT(selectBackupdir()));
1395 connect(backupDirED, SIGNAL(textChanged(QString)),
1396 this, SIGNAL(changed()));
1398 connect(lyxserverDirPB, SIGNAL(clicked()), this, SLOT(selectLyxPipe()));
1399 connect(lyxserverDirED, SIGNAL(textChanged(QString)),
1400 this, SIGNAL(changed()));
1402 connect(thesaurusDirPB, SIGNAL(clicked()), this, SLOT(selectThesaurusdir()));
1403 connect(thesaurusDirED, SIGNAL(textChanged(QString)),
1404 this, SIGNAL(changed()));
1406 connect(tempDirPB, SIGNAL(clicked()), this, SLOT(selectTempdir()));
1407 connect(tempDirED, SIGNAL(textChanged(QString)),
1408 this, SIGNAL(changed()));
1410 #if defined(USE_HUNSPELL)
1411 connect(hunspellDirPB, SIGNAL(clicked()), this, SLOT(selectHunspelldir()));
1412 connect(hunspellDirED, SIGNAL(textChanged(QString)),
1413 this, SIGNAL(changed()));
1415 hunspellDirPB->setEnabled(false);
1416 hunspellDirED->setEnabled(false);
1419 connect(pathPrefixED, SIGNAL(textChanged(QString)),
1420 this, SIGNAL(changed()));
1422 connect(texinputsPrefixED, SIGNAL(textChanged(QString)),
1423 this, SIGNAL(changed()));
1425 pathPrefixED->setValidator(new NoNewLineValidator(pathPrefixED));
1426 texinputsPrefixED->setValidator(new NoNewLineValidator(texinputsPrefixED));
1430 void PrefPaths::applyRC(LyXRC & rc) const
1432 rc.document_path = internal_path(fromqstr(workingDirED->text()));
1433 rc.example_path = internal_path(fromqstr(exampleDirED->text()));
1434 rc.template_path = internal_path(fromqstr(templateDirED->text()));
1435 rc.backupdir_path = internal_path(fromqstr(backupDirED->text()));
1436 rc.tempdir_path = internal_path(fromqstr(tempDirED->text()));
1437 rc.thesaurusdir_path = internal_path(fromqstr(thesaurusDirED->text()));
1438 rc.hunspelldir_path = internal_path(fromqstr(hunspellDirED->text()));
1439 rc.path_prefix = internal_path_list(fromqstr(pathPrefixED->text()));
1440 rc.texinputs_prefix = internal_path_list(fromqstr(texinputsPrefixED->text()));
1441 // FIXME: should be a checkbox only
1442 rc.lyxpipes = internal_path(fromqstr(lyxserverDirED->text()));
1446 void PrefPaths::updateRC(LyXRC const & rc)
1448 workingDirED->setText(toqstr(external_path(rc.document_path)));
1449 exampleDirED->setText(toqstr(external_path(rc.example_path)));
1450 templateDirED->setText(toqstr(external_path(rc.template_path)));
1451 backupDirED->setText(toqstr(external_path(rc.backupdir_path)));
1452 tempDirED->setText(toqstr(external_path(rc.tempdir_path)));
1453 thesaurusDirED->setText(toqstr(external_path(rc.thesaurusdir_path)));
1454 hunspellDirED->setText(toqstr(external_path(rc.hunspelldir_path)));
1455 pathPrefixED->setText(toqstr(external_path_list(rc.path_prefix)));
1456 texinputsPrefixED->setText(toqstr(external_path_list(rc.texinputs_prefix)));
1457 // FIXME: should be a checkbox only
1458 lyxserverDirED->setText(toqstr(external_path(rc.lyxpipes)));
1462 void PrefPaths::selectExampledir()
1464 QString file = browseDir(internalPath(exampleDirED->text()),
1465 qt_("Select directory for example files"));
1466 if (!file.isEmpty())
1467 exampleDirED->setText(file);
1471 void PrefPaths::selectTemplatedir()
1473 QString file = browseDir(internalPath(templateDirED->text()),
1474 qt_("Select a document templates directory"));
1475 if (!file.isEmpty())
1476 templateDirED->setText(file);
1480 void PrefPaths::selectTempdir()
1482 QString file = browseDir(internalPath(tempDirED->text()),
1483 qt_("Select a temporary directory"));
1484 if (!file.isEmpty())
1485 tempDirED->setText(file);
1489 void PrefPaths::selectBackupdir()
1491 QString file = browseDir(internalPath(backupDirED->text()),
1492 qt_("Select a backups directory"));
1493 if (!file.isEmpty())
1494 backupDirED->setText(file);
1498 void PrefPaths::selectWorkingdir()
1500 QString file = browseDir(internalPath(workingDirED->text()),
1501 qt_("Select a document directory"));
1502 if (!file.isEmpty())
1503 workingDirED->setText(file);
1507 void PrefPaths::selectThesaurusdir()
1509 QString file = browseDir(internalPath(thesaurusDirED->text()),
1510 qt_("Set the path to the thesaurus dictionaries"));
1511 if (!file.isEmpty())
1512 thesaurusDirED->setText(file);
1516 void PrefPaths::selectHunspelldir()
1518 QString file = browseDir(internalPath(hunspellDirED->text()),
1519 qt_("Set the path to the Hunspell dictionaries"));
1520 if (!file.isEmpty())
1521 hunspellDirED->setText(file);
1525 void PrefPaths::selectLyxPipe()
1527 QString file = form_->browse(internalPath(lyxserverDirED->text()),
1528 qt_("Give a filename for the LyX server pipe"));
1529 if (!file.isEmpty())
1530 lyxserverDirED->setText(file);
1534 /////////////////////////////////////////////////////////////////////
1538 /////////////////////////////////////////////////////////////////////
1540 PrefSpellchecker::PrefSpellchecker(GuiPreferences * form)
1541 : PrefModule(catLanguage, N_("Spellchecker"), form)
1545 // FIXME: this check should test the target platform (darwin)
1546 #if defined(USE_MACOSX_PACKAGING)
1547 spellcheckerCB->addItem(qt_("Native"), QString("native"));
1548 #define CONNECT_APPLESPELL
1550 #undef CONNECT_APPLESPELL
1552 #if defined(USE_ASPELL)
1553 spellcheckerCB->addItem(qt_("Aspell"), QString("aspell"));
1555 #if defined(USE_ENCHANT)
1556 spellcheckerCB->addItem(qt_("Enchant"), QString("enchant"));
1558 #if defined(USE_HUNSPELL)
1559 spellcheckerCB->addItem(qt_("Hunspell"), QString("hunspell"));
1562 #if defined(CONNECT_APPLESPELL) || defined(USE_ASPELL) || defined(USE_ENCHANT) || defined(USE_HUNSPELL)
1563 connect(spellcheckerCB, SIGNAL(currentIndexChanged(int)),
1564 this, SIGNAL(changed()));
1565 connect(altLanguageED, SIGNAL(textChanged(QString)),
1566 this, SIGNAL(changed()));
1567 connect(escapeCharactersED, SIGNAL(textChanged(QString)),
1568 this, SIGNAL(changed()));
1569 connect(compoundWordCB, SIGNAL(clicked()),
1570 this, SIGNAL(changed()));
1571 connect(spellcheckContinuouslyCB, SIGNAL(clicked()),
1572 this, SIGNAL(changed()));
1573 connect(spellcheckNotesCB, SIGNAL(clicked()),
1574 this, SIGNAL(changed()));
1576 altLanguageED->setValidator(new NoNewLineValidator(altLanguageED));
1577 escapeCharactersED->setValidator(new NoNewLineValidator(escapeCharactersED));
1579 spellcheckerCB->setEnabled(false);
1580 altLanguageED->setEnabled(false);
1581 escapeCharactersED->setEnabled(false);
1582 compoundWordCB->setEnabled(false);
1583 spellcheckContinuouslyCB->setEnabled(false);
1584 spellcheckNotesCB->setEnabled(false);
1589 void PrefSpellchecker::applyRC(LyXRC & rc) const
1591 string const speller = fromqstr(spellcheckerCB->
1592 itemData(spellcheckerCB->currentIndex()).toString());
1593 if (!speller.empty())
1594 rc.spellchecker = speller;
1595 rc.spellchecker_alt_lang = fromqstr(altLanguageED->text());
1596 rc.spellchecker_esc_chars = fromqstr(escapeCharactersED->text());
1597 rc.spellchecker_accept_compound = compoundWordCB->isChecked();
1598 rc.spellcheck_continuously = spellcheckContinuouslyCB->isChecked();
1599 rc.spellcheck_notes = spellcheckNotesCB->isChecked();
1603 void PrefSpellchecker::updateRC(LyXRC const & rc)
1605 spellcheckerCB->setCurrentIndex(
1606 spellcheckerCB->findData(toqstr(rc.spellchecker)));
1607 altLanguageED->setText(toqstr(rc.spellchecker_alt_lang));
1608 escapeCharactersED->setText(toqstr(rc.spellchecker_esc_chars));
1609 compoundWordCB->setChecked(rc.spellchecker_accept_compound);
1610 spellcheckContinuouslyCB->setChecked(rc.spellcheck_continuously);
1611 spellcheckNotesCB->setChecked(rc.spellcheck_notes);
1615 void PrefSpellchecker::on_spellcheckerCB_currentIndexChanged(int index)
1617 QString spellchecker = spellcheckerCB->itemData(index).toString();
1619 compoundWordCB->setEnabled(spellchecker == QString("aspell"));
1624 /////////////////////////////////////////////////////////////////////
1628 /////////////////////////////////////////////////////////////////////
1631 PrefConverters::PrefConverters(GuiPreferences * form)
1632 : PrefModule(catFiles, N_("Converters"), form)
1636 connect(converterNewPB, SIGNAL(clicked()),
1637 this, SLOT(updateConverter()));
1638 connect(converterRemovePB, SIGNAL(clicked()),
1639 this, SLOT(removeConverter()));
1640 connect(converterModifyPB, SIGNAL(clicked()),
1641 this, SLOT(updateConverter()));
1642 connect(convertersLW, SIGNAL(currentRowChanged(int)),
1643 this, SLOT(switchConverter()));
1644 connect(converterFromCO, SIGNAL(activated(QString)),
1645 this, SLOT(changeConverter()));
1646 connect(converterToCO, SIGNAL(activated(QString)),
1647 this, SLOT(changeConverter()));
1648 connect(converterED, SIGNAL(textEdited(QString)),
1649 this, SLOT(changeConverter()));
1650 connect(converterFlagED, SIGNAL(textEdited(QString)),
1651 this, SLOT(changeConverter()));
1652 connect(converterNewPB, SIGNAL(clicked()),
1653 this, SIGNAL(changed()));
1654 connect(converterRemovePB, SIGNAL(clicked()),
1655 this, SIGNAL(changed()));
1656 connect(converterModifyPB, SIGNAL(clicked()),
1657 this, SIGNAL(changed()));
1658 connect(maxAgeLE, SIGNAL(textEdited(QString)),
1659 this, SIGNAL(changed()));
1660 connect(needauthForbiddenCB, SIGNAL(toggled(bool)),
1661 this, SIGNAL(changed()));
1663 converterED->setValidator(new NoNewLineValidator(converterED));
1664 converterFlagED->setValidator(new NoNewLineValidator(converterFlagED));
1665 maxAgeLE->setValidator(new QDoubleValidator(0, HUGE_VAL, 6, maxAgeLE));
1666 //converterDefGB->setFocusProxy(convertersLW);
1670 void PrefConverters::applyRC(LyXRC & rc) const
1672 rc.use_converter_cache = cacheCB->isChecked();
1673 rc.use_converter_needauth_forbidden = needauthForbiddenCB->isChecked();
1674 rc.use_converter_needauth = needauthCB->isChecked();
1675 rc.converter_cache_maxage = int(widgetToDouble(maxAgeLE) * 86400.0);
1679 static void setCheckboxBlockSignals(QCheckBox *cb, bool checked) {
1680 cb->blockSignals(true);
1681 cb->setChecked(checked);
1682 cb->blockSignals(false);
1686 void PrefConverters::updateRC(LyXRC const & rc)
1688 cacheCB->setChecked(rc.use_converter_cache);
1689 needauthForbiddenCB->setChecked(rc.use_converter_needauth_forbidden);
1690 setCheckboxBlockSignals(needauthCB, rc.use_converter_needauth);
1692 doubleToWidget(maxAgeLE, (double(rc.converter_cache_maxage) / 86400.0), 'g', 6);
1697 void PrefConverters::updateGui()
1699 QString const pattern("%1 -> %2");
1700 form_->formats().sort();
1701 form_->converters().update(form_->formats());
1702 // save current selection
1705 .arg(converterFromCO->currentText())
1706 .arg(converterToCO->currentText());
1708 converterFromCO->clear();
1709 converterToCO->clear();
1711 for (Format const & f : form_->formats()) {
1712 QString const name = toqstr(translateIfPossible(f.prettyname()));
1713 converterFromCO->addItem(name);
1714 converterToCO->addItem(name);
1717 // currentRowChanged(int) is also triggered when updating the listwidget
1718 // block signals to avoid unnecessary calls to switchConverter()
1719 convertersLW->blockSignals(true);
1720 convertersLW->clear();
1722 for (Converter const & c : form_->converters()) {
1723 QString const name =
1725 .arg(toqstr(translateIfPossible(c.From()->prettyname())))
1726 .arg(toqstr(translateIfPossible(c.To()->prettyname())));
1727 int type = form_->converters().getNumber(c.From()->name(),
1729 new QListWidgetItem(name, convertersLW, type);
1731 convertersLW->sortItems(Qt::AscendingOrder);
1732 convertersLW->blockSignals(false);
1734 // restore selection
1735 if (current != pattern.arg(QString()).arg(QString())) {
1736 QList<QListWidgetItem *> const item =
1737 convertersLW->findItems(current, Qt::MatchExactly);
1738 if (!item.isEmpty())
1739 convertersLW->setCurrentItem(item.at(0));
1742 // select first element if restoring failed
1743 if (convertersLW->currentRow() == -1)
1744 convertersLW->setCurrentRow(0);
1750 void PrefConverters::switchConverter()
1752 int const cnr = convertersLW->currentItem()->type();
1753 Converter const & c(form_->converters().get(cnr));
1754 converterFromCO->setCurrentIndex(form_->formats().getNumber(c.from()));
1755 converterToCO->setCurrentIndex(form_->formats().getNumber(c.to()));
1756 converterED->setText(toqstr(c.command()));
1757 converterFlagED->setText(toqstr(c.flags()));
1763 void PrefConverters::changeConverter()
1769 void PrefConverters::updateButtons()
1771 if (form_->formats().empty())
1773 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1774 Format const & to = form_->formats().get(converterToCO->currentIndex());
1775 int const sel = form_->converters().getNumber(from.name(), to.name());
1776 bool const known = sel >= 0;
1777 bool const valid = !(converterED->text().isEmpty()
1778 || from.name() == to.name());
1783 if (convertersLW->count() > 0) {
1784 int const cnr = convertersLW->currentItem()->type();
1785 Converter const & c = form_->converters().get(cnr);
1786 old_command = c.command();
1787 old_flag = c.flags();
1790 string const new_command = fromqstr(converterED->text());
1791 string const new_flag = fromqstr(converterFlagED->text());
1793 bool modified = (old_command != new_command || old_flag != new_flag);
1795 converterModifyPB->setEnabled(valid && known && modified);
1796 converterNewPB->setEnabled(valid && !known);
1797 converterRemovePB->setEnabled(known);
1799 maxAgeLE->setEnabled(cacheCB->isChecked());
1800 maxAgeLA->setEnabled(cacheCB->isChecked());
1805 // specify unique from/to or it doesn't appear. This is really bad UI
1806 // this is why we can use the same function for both new and modify
1807 void PrefConverters::updateConverter()
1809 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1810 Format const & to = form_->formats().get(converterToCO->currentIndex());
1811 string const flags = fromqstr(converterFlagED->text());
1812 string const command = fromqstr(converterED->text());
1814 Converter const * old =
1815 form_->converters().getConverter(from.name(), to.name());
1816 form_->converters().add(from.name(), to.name(), command, flags);
1819 form_->converters().updateLast(form_->formats());
1823 // Remove all files created by this converter from the cache, since
1824 // the modified converter might create different files.
1825 ConverterCache::get().remove_all(from.name(), to.name());
1829 void PrefConverters::removeConverter()
1831 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1832 Format const & to = form_->formats().get(converterToCO->currentIndex());
1833 form_->converters().erase(from.name(), to.name());
1837 // Remove all files created by this converter from the cache, since
1838 // a possible new converter might create different files.
1839 ConverterCache::get().remove_all(from.name(), to.name());
1843 void PrefConverters::on_cacheCB_stateChanged(int state)
1845 maxAgeLE->setEnabled(state == Qt::Checked);
1846 maxAgeLA->setEnabled(state == Qt::Checked);
1851 void PrefConverters::on_needauthForbiddenCB_toggled(bool checked)
1853 needauthCB->setEnabled(!checked);
1857 void PrefConverters::on_needauthCB_toggled(bool checked)
1864 int ret = frontend::Alert::prompt(
1865 _("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!"),
1866 0, 0, _("&No"), _("&Yes"));
1870 setCheckboxBlockSignals(needauthCB, true);
1874 /////////////////////////////////////////////////////////////////////
1878 /////////////////////////////////////////////////////////////////////
1880 class FormatValidator : public QValidator
1883 FormatValidator(QWidget *, Formats const & f);
1884 void fixup(QString & input) const override;
1885 QValidator::State validate(QString & input, int & pos) const override;
1887 virtual QString toString(Format const & format) const = 0;
1889 Formats const & formats_;
1893 FormatValidator::FormatValidator(QWidget * parent, Formats const & f)
1894 : QValidator(parent), formats_(f)
1899 void FormatValidator::fixup(QString & input) const
1901 Formats::const_iterator cit = formats_.begin();
1902 Formats::const_iterator end = formats_.end();
1903 for (; cit != end; ++cit) {
1904 QString const name = toString(*cit);
1905 if (distance(formats_.begin(), cit) == nr()) {
1913 QValidator::State FormatValidator::validate(QString & input, int & /*pos*/) const
1915 Formats::const_iterator cit = formats_.begin();
1916 Formats::const_iterator end = formats_.end();
1917 bool unknown = true;
1918 for (; unknown && cit != end; ++cit) {
1919 QString const name = toString(*cit);
1920 if (distance(formats_.begin(), cit) != nr())
1921 unknown = name != input;
1924 if (unknown && !input.isEmpty())
1925 return QValidator::Acceptable;
1927 return QValidator::Intermediate;
1931 int FormatValidator::nr() const
1933 QComboBox * p = qobject_cast<QComboBox *>(parent());
1934 return p->itemData(p->currentIndex()).toInt();
1938 /////////////////////////////////////////////////////////////////////
1940 // FormatNameValidator
1942 /////////////////////////////////////////////////////////////////////
1944 class FormatNameValidator : public FormatValidator
1947 FormatNameValidator(QWidget * parent, Formats const & f)
1948 : FormatValidator(parent, f)
1951 QString toString(Format const & format) const override
1953 return toqstr(format.name());
1958 /////////////////////////////////////////////////////////////////////
1960 // FormatPrettynameValidator
1962 /////////////////////////////////////////////////////////////////////
1964 class FormatPrettynameValidator : public FormatValidator
1967 FormatPrettynameValidator(QWidget * parent, Formats const & f)
1968 : FormatValidator(parent, f)
1971 QString toString(Format const & format) const override
1973 return toqstr(translateIfPossible(format.prettyname()));
1978 /////////////////////////////////////////////////////////////////////
1982 /////////////////////////////////////////////////////////////////////
1984 PrefFileformats::PrefFileformats(GuiPreferences * form)
1985 : PrefModule(catFiles, N_("File Formats"), form)
1989 formatED->setValidator(new FormatNameValidator(formatsCB, form_->formats()));
1990 formatsCB->setValidator(new FormatPrettynameValidator(formatsCB, form_->formats()));
1991 extensionsED->setValidator(new NoNewLineValidator(extensionsED));
1992 shortcutED->setValidator(new NoNewLineValidator(shortcutED));
1993 editorED->setValidator(new NoNewLineValidator(editorED));
1994 viewerED->setValidator(new NoNewLineValidator(viewerED));
1995 copierED->setValidator(new NoNewLineValidator(copierED));
1997 connect(documentCB, SIGNAL(clicked()),
1998 this, SLOT(setFlags()));
1999 connect(vectorCB, SIGNAL(clicked()),
2000 this, SLOT(setFlags()));
2001 connect(exportMenuCB, SIGNAL(clicked()),
2002 this, SLOT(setFlags()));
2003 connect(formatsCB->lineEdit(), SIGNAL(editingFinished()),
2004 this, SLOT(updatePrettyname()));
2005 connect(formatsCB->lineEdit(), SIGNAL(textEdited(QString)),
2006 this, SIGNAL(changed()));
2007 connect(defaultFormatCB, SIGNAL(activated(QString)),
2008 this, SIGNAL(changed()));
2009 connect(defaultOTFFormatCB, SIGNAL(activated(QString)),
2010 this, SIGNAL(changed()));
2011 connect(defaultPlatexFormatCB, SIGNAL(activated(QString)),
2012 this, SIGNAL(changed()));
2013 connect(viewerCO, SIGNAL(activated(int)),
2014 this, SIGNAL(changed()));
2015 connect(editorCO, SIGNAL(activated(int)),
2016 this, SIGNAL(changed()));
2022 string const l10n_shortcut(docstring const & prettyname, string const & shortcut)
2024 if (shortcut.empty())
2027 string l10n_format =
2028 to_utf8(_(to_utf8(prettyname) + '|' + shortcut));
2029 return split(l10n_format, '|');
2035 void PrefFileformats::applyRC(LyXRC & rc) const
2037 QString const default_format = defaultFormatCB->itemData(
2038 defaultFormatCB->currentIndex()).toString();
2039 rc.default_view_format = fromqstr(default_format);
2040 QString const default_otf_format = defaultOTFFormatCB->itemData(
2041 defaultOTFFormatCB->currentIndex()).toString();
2042 rc.default_otf_view_format = fromqstr(default_otf_format);
2043 QString const default_platex_format = defaultPlatexFormatCB->itemData(
2044 defaultPlatexFormatCB->currentIndex()).toString();
2045 rc.default_platex_view_format = fromqstr(default_platex_format);
2049 void PrefFileformats::updateRC(LyXRC const & rc)
2051 viewer_alternatives = rc.viewer_alternatives;
2052 editor_alternatives = rc.editor_alternatives;
2053 bool const init = defaultFormatCB->currentText().isEmpty();
2057 defaultFormatCB->findData(toqstr(rc.default_view_format));
2058 defaultFormatCB->setCurrentIndex(pos);
2059 pos = defaultOTFFormatCB->findData(toqstr(rc.default_otf_view_format));
2060 defaultOTFFormatCB->setCurrentIndex(pos);
2061 defaultOTFFormatCB->setCurrentIndex(pos);
2062 pos = defaultPlatexFormatCB->findData(toqstr(rc.default_platex_view_format));
2063 defaultPlatexFormatCB->setCurrentIndex(pos);
2064 defaultPlatexFormatCB->setCurrentIndex(pos);
2069 void PrefFileformats::updateView()
2071 QString const current = formatsCB->currentText();
2072 QString const current_def = defaultFormatCB->currentText();
2073 QString const current_def_otf = defaultOTFFormatCB->currentText();
2074 QString const current_def_platex = defaultPlatexFormatCB->currentText();
2076 // update comboboxes with formats
2077 formatsCB->blockSignals(true);
2078 defaultFormatCB->blockSignals(true);
2079 defaultOTFFormatCB->blockSignals(true);
2080 defaultPlatexFormatCB->blockSignals(true);
2082 defaultFormatCB->clear();
2083 defaultOTFFormatCB->clear();
2084 defaultPlatexFormatCB->clear();
2085 form_->formats().sort();
2086 for (Format const & f : form_->formats()) {
2087 QString const prettyname = toqstr(translateIfPossible(f.prettyname()));
2088 formatsCB->addItem(prettyname,
2089 QVariant(form_->formats().getNumber(f.name())));
2090 if (f.viewer().empty())
2092 if (form_->converters().isReachable("xhtml", f.name())
2093 || form_->converters().isReachable("dviluatex", f.name())
2094 || form_->converters().isReachable("luatex", f.name())
2095 || form_->converters().isReachable("xetex", f.name())) {
2096 defaultFormatCB->addItem(prettyname,
2097 QVariant(toqstr(f.name())));
2098 defaultOTFFormatCB->addItem(prettyname,
2099 QVariant(toqstr(f.name())));
2101 if (form_->converters().isReachable("latex", f.name())
2102 || form_->converters().isReachable("pdflatex", f.name()))
2103 defaultFormatCB->addItem(prettyname,
2104 QVariant(toqstr(f.name())));
2105 if (form_->converters().isReachable("platex", f.name()))
2106 defaultPlatexFormatCB->addItem(prettyname,
2107 QVariant(toqstr(f.name())));
2111 // restore selections
2112 int item = formatsCB->findText(current, Qt::MatchExactly);
2113 formatsCB->setCurrentIndex(item < 0 ? 0 : item);
2114 on_formatsCB_currentIndexChanged(item < 0 ? 0 : item);
2115 item = defaultFormatCB->findText(current_def, Qt::MatchExactly);
2116 defaultFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2117 item = defaultOTFFormatCB->findText(current_def_otf, Qt::MatchExactly);
2118 defaultOTFFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2119 item = defaultPlatexFormatCB->findText(current_def_platex, Qt::MatchExactly);
2120 defaultPlatexFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2121 formatsCB->blockSignals(false);
2122 defaultFormatCB->blockSignals(false);
2123 defaultOTFFormatCB->blockSignals(false);
2124 defaultPlatexFormatCB->blockSignals(false);
2128 void PrefFileformats::on_formatsCB_currentIndexChanged(int i)
2130 if (form_->formats().empty())
2132 int const nr = formatsCB->itemData(i).toInt();
2133 Format const f = form_->formats().get(nr);
2135 formatED->setText(toqstr(f.name()));
2136 copierED->setText(toqstr(form_->movers().command(f.name())));
2137 extensionsED->setText(toqstr(f.extensions()));
2138 mimeED->setText(toqstr(f.mime()));
2139 shortcutED->setText(
2140 toqstr(l10n_shortcut(f.prettyname(), f.shortcut())));
2141 documentCB->setChecked((f.documentFormat()));
2142 vectorCB->setChecked((f.vectorFormat()));
2143 exportMenuCB->setChecked((f.inExportMenu()));
2144 exportMenuCB->setEnabled((f.documentFormat()));
2150 void PrefFileformats::setFlags()
2152 int flags = Format::none;
2153 if (documentCB->isChecked())
2154 flags |= Format::document;
2155 if (vectorCB->isChecked())
2156 flags |= Format::vector;
2157 if (exportMenuCB->isChecked())
2158 flags |= Format::export_menu;
2159 currentFormat().setFlags(flags);
2160 exportMenuCB->setEnabled(documentCB->isChecked());
2165 void PrefFileformats::on_copierED_textEdited(const QString & s)
2167 string const fmt = fromqstr(formatED->text());
2168 form_->movers().set(fmt, fromqstr(s));
2173 void PrefFileformats::on_extensionsED_textEdited(const QString & s)
2175 currentFormat().setExtensions(fromqstr(s));
2180 void PrefFileformats::on_viewerED_textEdited(const QString & s)
2182 currentFormat().setViewer(fromqstr(s));
2187 void PrefFileformats::on_editorED_textEdited(const QString & s)
2189 currentFormat().setEditor(fromqstr(s));
2194 void PrefFileformats::on_mimeED_textEdited(const QString & s)
2196 currentFormat().setMime(fromqstr(s));
2201 void PrefFileformats::on_shortcutED_textEdited(const QString & s)
2203 string const new_shortcut = fromqstr(s);
2204 if (new_shortcut == l10n_shortcut(currentFormat().prettyname(),
2205 currentFormat().shortcut()))
2207 currentFormat().setShortcut(new_shortcut);
2212 void PrefFileformats::on_formatED_editingFinished()
2214 string const newname = fromqstr(formatED->displayText());
2215 string const oldname = currentFormat().name();
2216 if (newname == oldname)
2218 if (form_->converters().formatIsUsed(oldname)) {
2219 Alert::error(_("Format in use"),
2220 _("You cannot change a format's short name "
2221 "if the format is used by a converter. "
2222 "Please remove the converter first."));
2227 currentFormat().setName(newname);
2232 void PrefFileformats::on_formatED_textChanged(const QString &)
2234 QString t = formatED->text();
2236 bool valid = formatED->validator()->validate(t, p) == QValidator::Acceptable;
2237 setValid(formatLA, valid);
2241 void PrefFileformats::on_formatsCB_editTextChanged(const QString &)
2243 QString t = formatsCB->currentText();
2245 bool valid = formatsCB->validator()->validate(t, p) == QValidator::Acceptable;
2246 setValid(formatsLA, valid);
2250 void PrefFileformats::updatePrettyname()
2252 QString const newname = formatsCB->currentText();
2253 if (newname == toqstr(translateIfPossible(currentFormat().prettyname())))
2256 currentFormat().setPrettyname(qstring_to_ucs4(newname));
2264 void updateComboBox(LyXRC::Alternatives const & alts,
2265 string const & fmt, QComboBox * combo)
2267 LyXRC::Alternatives::const_iterator it =
2269 if (it != alts.end()) {
2270 LyXRC::CommandSet const & cmds = it->second;
2271 LyXRC::CommandSet::const_iterator sit =
2273 LyXRC::CommandSet::const_iterator const sen =
2275 for (; sit != sen; ++sit) {
2276 QString const qcmd = toqstr(*sit);
2277 combo->addItem(qcmd, qcmd);
2284 void PrefFileformats::updateViewers()
2286 Format const f = currentFormat();
2287 viewerCO->blockSignals(true);
2289 viewerCO->addItem(qt_("None"), QString());
2290 updateComboBox(viewer_alternatives, f.name(), viewerCO);
2291 viewerCO->addItem(qt_("Custom"), QString("custom viewer"));
2292 viewerCO->blockSignals(false);
2294 int pos = viewerCO->findData(toqstr(f.viewer()));
2297 viewerED->setEnabled(false);
2298 viewerCO->setCurrentIndex(pos);
2300 viewerED->setEnabled(true);
2301 viewerED->setText(toqstr(f.viewer()));
2302 viewerCO->setCurrentIndex(viewerCO->findData(toqstr("custom viewer")));
2307 void PrefFileformats::updateEditors()
2309 Format const f = currentFormat();
2310 editorCO->blockSignals(true);
2312 editorCO->addItem(qt_("None"), QString());
2313 updateComboBox(editor_alternatives, f.name(), editorCO);
2314 editorCO->addItem(qt_("Custom"), QString("custom editor"));
2315 editorCO->blockSignals(false);
2317 int pos = editorCO->findData(toqstr(f.editor()));
2320 editorED->setEnabled(false);
2321 editorCO->setCurrentIndex(pos);
2323 editorED->setEnabled(true);
2324 editorED->setText(toqstr(f.editor()));
2325 editorCO->setCurrentIndex(editorCO->findData(toqstr("custom editor")));
2330 void PrefFileformats::on_viewerCO_currentIndexChanged(int i)
2332 bool const custom = viewerCO->itemData(i).toString() == "custom viewer";
2333 viewerED->setEnabled(custom);
2335 currentFormat().setViewer(fromqstr(viewerCO->itemData(i).toString()));
2339 void PrefFileformats::on_editorCO_currentIndexChanged(int i)
2341 bool const custom = editorCO->itemData(i).toString() == "custom editor";
2342 editorED->setEnabled(custom);
2344 currentFormat().setEditor(fromqstr(editorCO->itemData(i).toString()));
2348 Format & PrefFileformats::currentFormat()
2350 int const i = formatsCB->currentIndex();
2351 int const nr = formatsCB->itemData(i).toInt();
2352 return form_->formats().get(nr);
2356 void PrefFileformats::on_formatNewPB_clicked()
2358 form_->formats().add("", "", docstring(), "", "", "", "", Format::none);
2360 formatsCB->setCurrentIndex(0);
2361 formatsCB->setFocus(Qt::OtherFocusReason);
2365 void PrefFileformats::on_formatRemovePB_clicked()
2367 int const i = formatsCB->currentIndex();
2368 int const nr = formatsCB->itemData(i).toInt();
2369 string const current_text = form_->formats().get(nr).name();
2370 if (form_->converters().formatIsUsed(current_text)) {
2371 Alert::error(_("Format in use"),
2372 _("Cannot remove a Format used by a Converter. "
2373 "Remove the converter first."));
2377 form_->formats().erase(current_text);
2380 on_formatsCB_editTextChanged(formatsCB->currentText());
2385 /////////////////////////////////////////////////////////////////////
2389 /////////////////////////////////////////////////////////////////////
2391 PrefLanguage::PrefLanguage(GuiPreferences * form)
2392 : PrefModule(catLanguage, N_("Language"), form)
2396 connect(visualCursorRB, SIGNAL(clicked()),
2397 this, SIGNAL(changed()));
2398 connect(logicalCursorRB, SIGNAL(clicked()),
2399 this, SIGNAL(changed()));
2400 connect(markForeignCB, SIGNAL(clicked()),
2401 this, SIGNAL(changed()));
2402 connect(respectOSkbdCB, SIGNAL(clicked()),
2403 this, SIGNAL(changed()));
2404 connect(explicitDocLangBeginCB, SIGNAL(clicked()),
2405 this, SIGNAL(changed()));
2406 connect(explicitDocLangEndCB, SIGNAL(clicked()),
2407 this, SIGNAL(changed()));
2408 connect(languagePackageCO, SIGNAL(activated(int)),
2409 this, SIGNAL(changed()));
2410 connect(languagePackageED, SIGNAL(textChanged(QString)),
2411 this, SIGNAL(changed()));
2412 connect(globalCB, SIGNAL(clicked()),
2413 this, SIGNAL(changed()));
2414 connect(startCommandED, SIGNAL(textChanged(QString)),
2415 this, SIGNAL(changed()));
2416 connect(endCommandED, SIGNAL(textChanged(QString)),
2417 this, SIGNAL(changed()));
2418 connect(uiLanguageCO, SIGNAL(activated(int)),
2419 this, SIGNAL(changed()));
2420 connect(defaultDecimalSepED, SIGNAL(textChanged(QString)),
2421 this, SIGNAL(changed()));
2422 connect(defaultDecimalSepCO, SIGNAL(activated(int)),
2423 this, SIGNAL(changed()));
2424 connect(defaultLengthUnitCO, SIGNAL(activated(int)),
2425 this, SIGNAL(changed()));
2427 languagePackageED->setValidator(new NoNewLineValidator(languagePackageED));
2428 startCommandED->setValidator(new NoNewLineValidator(startCommandED));
2429 endCommandED->setValidator(new NoNewLineValidator(endCommandED));
2431 #if QT_VERSION < 0x060000
2432 defaultDecimalSepED->setValidator(new QRegExpValidator(QRegExp("\\S"), this));
2434 defaultDecimalSepED->setValidator(new QRegularExpressionValidator(QRegularExpression("\\S"), this));
2436 defaultDecimalSepED->setMaxLength(1);
2438 defaultLengthUnitCO->addItem(lyx::qt_(unit_name_gui[Length::CM]), Length::CM);
2439 defaultLengthUnitCO->addItem(lyx::qt_(unit_name_gui[Length::IN]), Length::IN);
2441 QAbstractItemModel * language_model = guiApp->languageModel();
2442 language_model->sort(0);
2443 uiLanguageCO->blockSignals(true);
2444 uiLanguageCO->clear();
2445 uiLanguageCO->addItem(qt_("Default"), toqstr("auto"));
2446 for (int i = 0; i != language_model->rowCount(); ++i) {
2447 QModelIndex index = language_model->index(i, 0);
2448 // Filter the list based on the available translation and add
2449 // each language code only once
2450 string const name = fromqstr(index.data(Qt::UserRole).toString());
2451 Language const * lang = languages.getLanguage(name);
2454 // never remove the currently selected language
2455 if (name != form->rc().gui_language
2456 && name != lyxrc.gui_language
2457 && (!Messages::available(lang->code())
2458 || !lang->hasGuiSupport()))
2460 uiLanguageCO->addItem(index.data(Qt::DisplayRole).toString(),
2461 index.data(Qt::UserRole).toString());
2463 uiLanguageCO->blockSignals(false);
2465 // FIXME: restore this when it works (see discussion in #6450).
2466 respectOSkbdCB->hide();
2470 void PrefLanguage::on_uiLanguageCO_currentIndexChanged(int)
2472 QMessageBox::information(this, qt_("LyX needs to be restarted!"),
2473 qt_("The change of user interface language will be fully "
2474 "effective only after a restart."));
2478 void PrefLanguage::on_languagePackageCO_currentIndexChanged(int i)
2481 languagePackageED->setText(save_langpack_);
2482 else if (!languagePackageED->text().isEmpty()) {
2483 save_langpack_ = languagePackageED->text();
2484 languagePackageED->clear();
2486 languagePackageED->setEnabled(i == 2);
2490 void PrefLanguage::on_defaultDecimalSepCO_currentIndexChanged(int i)
2492 defaultDecimalSepED->setEnabled(i == 1);
2496 void PrefLanguage::applyRC(LyXRC & rc) const
2498 rc.visual_cursor = visualCursorRB->isChecked();
2499 rc.mark_foreign_language = markForeignCB->isChecked();
2500 rc.respect_os_kbd_language = respectOSkbdCB->isChecked();
2501 rc.language_auto_begin = !explicitDocLangBeginCB->isChecked();
2502 rc.language_auto_end = !explicitDocLangEndCB->isChecked();
2503 int const p = languagePackageCO->currentIndex();
2505 rc.language_package_selection = LyXRC::LP_AUTO;
2507 rc.language_package_selection = LyXRC::LP_BABEL;
2509 rc.language_package_selection = LyXRC::LP_CUSTOM;
2511 rc.language_package_selection = LyXRC::LP_NONE;
2512 rc.language_custom_package = fromqstr(languagePackageED->text());
2513 rc.language_global_options = globalCB->isChecked();
2514 rc.language_command_begin = fromqstr(startCommandED->text());
2515 rc.language_command_end = fromqstr(endCommandED->text());
2516 rc.gui_language = fromqstr(
2517 uiLanguageCO->itemData(uiLanguageCO->currentIndex()).toString());
2518 if (defaultDecimalSepCO->currentIndex() == 0)
2519 rc.default_decimal_sep = "locale";
2521 rc.default_decimal_sep = fromqstr(defaultDecimalSepED->text());
2522 rc.default_length_unit = (Length::UNIT) defaultLengthUnitCO->itemData(defaultLengthUnitCO->currentIndex()).toInt();
2526 void PrefLanguage::updateRC(LyXRC const & rc)
2528 if (rc.visual_cursor)
2529 visualCursorRB->setChecked(true);
2531 logicalCursorRB->setChecked(true);
2532 markForeignCB->setChecked(rc.mark_foreign_language);
2533 respectOSkbdCB->setChecked(rc.respect_os_kbd_language);
2534 explicitDocLangBeginCB->setChecked(!rc.language_auto_begin);
2535 explicitDocLangEndCB->setChecked(!rc.language_auto_end);
2536 languagePackageCO->setCurrentIndex(rc.language_package_selection);
2537 if (languagePackageCO->currentIndex() == 2) {
2538 languagePackageED->setText(toqstr(rc.language_custom_package));
2539 languagePackageED->setEnabled(true);
2541 languagePackageED->clear();
2542 save_langpack_ = toqstr(rc.language_custom_package);
2543 languagePackageED->setEnabled(false);
2545 defaultDecimalSepED->setEnabled(defaultDecimalSepCO->currentIndex() == 1);
2546 globalCB->setChecked(rc.language_global_options);
2547 startCommandED->setText(toqstr(rc.language_command_begin));
2548 endCommandED->setText(toqstr(rc.language_command_end));
2549 if (rc.default_decimal_sep == "locale") {
2550 defaultDecimalSepCO->setCurrentIndex(0);
2551 defaultDecimalSepED->clear();
2553 defaultDecimalSepCO->setCurrentIndex(1);
2554 defaultDecimalSepED->setText(toqstr(rc.default_decimal_sep));
2556 int pos = defaultLengthUnitCO->findData(int(rc.default_length_unit));
2557 defaultLengthUnitCO->setCurrentIndex(pos);
2559 pos = uiLanguageCO->findData(toqstr(rc.gui_language));
2560 uiLanguageCO->blockSignals(true);
2561 uiLanguageCO->setCurrentIndex(pos);
2562 uiLanguageCO->blockSignals(false);
2566 /////////////////////////////////////////////////////////////////////
2568 // PrefUserInterface
2570 /////////////////////////////////////////////////////////////////////
2572 PrefUserInterface::PrefUserInterface(GuiPreferences * form)
2573 : PrefModule(catLookAndFeel, N_("User Interface"), form)
2577 connect(uiFilePB, SIGNAL(clicked()),
2578 this, SLOT(selectUi()));
2579 connect(uiFileED, SIGNAL(textChanged(QString)),
2580 this, SIGNAL(changed()));
2581 connect(iconSetCO, SIGNAL(activated(int)),
2582 this, SIGNAL(changed()));
2583 connect(useSystemThemeIconsCB, SIGNAL(clicked()),
2584 this, SIGNAL(changed()));
2585 connect(lastfilesSB, SIGNAL(valueChanged(int)),
2586 this, SIGNAL(changed()));
2587 connect(tooltipCB, SIGNAL(toggled(bool)),
2588 this, SIGNAL(changed()));
2589 lastfilesSB->setMaximum(maxlastfiles);
2591 iconSetCO->addItem(qt_("Default"), QString());
2592 iconSetCO->addItem(qt_("Classic"), "classic");
2593 iconSetCO->addItem(qt_("Oxygen"), "oxygen");
2595 #if QT_VERSION >= 0x040600
2596 if (guiApp->platformName() != "qt4x11"
2597 && guiApp->platformName() != "xcb"
2598 && !guiApp->platformName().contains("wayland"))
2600 useSystemThemeIconsCB->hide();
2604 void PrefUserInterface::applyRC(LyXRC & rc) const
2606 rc.icon_set = fromqstr(iconSetCO->itemData(
2607 iconSetCO->currentIndex()).toString());
2609 rc.ui_file = internal_path(fromqstr(uiFileED->text()));
2610 rc.use_system_theme_icons = useSystemThemeIconsCB->isChecked();
2611 rc.num_lastfiles = lastfilesSB->value();
2612 rc.use_tooltip = tooltipCB->isChecked();
2616 void PrefUserInterface::updateRC(LyXRC const & rc)
2618 int iconset = iconSetCO->findData(toqstr(rc.icon_set));
2621 iconSetCO->setCurrentIndex(iconset);
2622 useSystemThemeIconsCB->setChecked(rc.use_system_theme_icons);
2623 uiFileED->setText(toqstr(external_path(rc.ui_file)));
2624 lastfilesSB->setValue(rc.num_lastfiles);
2625 tooltipCB->setChecked(rc.use_tooltip);
2629 void PrefUserInterface::selectUi()
2631 QString file = form_->browseUI(internalPath(uiFileED->text()));
2632 if (!file.isEmpty())
2633 uiFileED->setText(file);
2637 /////////////////////////////////////////////////////////////////////
2639 // PrefDocumentHandling
2641 /////////////////////////////////////////////////////////////////////
2643 PrefDocHandling::PrefDocHandling(GuiPreferences * form)
2644 : PrefModule(catLookAndFeel, N_("Document Handling"), form)
2648 connect(autoSaveCB, SIGNAL(toggled(bool)),
2649 autoSaveSB, SLOT(setEnabled(bool)));
2650 connect(autoSaveCB, SIGNAL(toggled(bool)),
2651 TextLabel1, SLOT(setEnabled(bool)));
2652 connect(openDocumentsInTabsCB, SIGNAL(clicked()),
2653 this, SIGNAL(changed()));
2654 connect(singleInstanceCB, SIGNAL(clicked()),
2655 this, SIGNAL(changed()));
2656 connect(singleCloseTabButtonCB, SIGNAL(clicked()),
2657 this, SIGNAL(changed()));
2658 connect(closeLastViewCO, SIGNAL(activated(int)),
2659 this, SIGNAL(changed()));
2660 connect(restoreCursorCB, SIGNAL(clicked()),
2661 this, SIGNAL(changed()));
2662 connect(loadSessionCB, SIGNAL(clicked()),
2663 this, SIGNAL(changed()));
2664 connect(allowGeometrySessionCB, SIGNAL(clicked()),
2665 this, SIGNAL(changed()));
2666 connect(autoSaveSB, SIGNAL(valueChanged(int)),
2667 this, SIGNAL(changed()));
2668 connect(autoSaveCB, SIGNAL(clicked()),
2669 this, SIGNAL(changed()));
2670 connect(backupCB, SIGNAL(clicked()),
2671 this, SIGNAL(changed()));
2672 connect(saveCompressedCB, SIGNAL(clicked()),
2673 this, SIGNAL(changed()));
2674 connect(saveOriginCB, SIGNAL(clicked()),
2675 this, SIGNAL(changed()));
2679 void PrefDocHandling::applyRC(LyXRC & rc) const
2681 rc.use_lastfilepos = restoreCursorCB->isChecked();
2682 rc.load_session = loadSessionCB->isChecked();
2683 rc.allow_geometry_session = allowGeometrySessionCB->isChecked();
2684 rc.autosave = autoSaveCB->isChecked() ? autoSaveSB->value() * 60 : 0;
2685 rc.make_backup = backupCB->isChecked();
2686 rc.save_compressed = saveCompressedCB->isChecked();
2687 rc.save_origin = saveOriginCB->isChecked();
2688 rc.open_buffers_in_tabs = openDocumentsInTabsCB->isChecked();
2689 rc.single_instance = singleInstanceCB->isChecked();
2690 rc.single_close_tab_button = singleCloseTabButtonCB->isChecked();
2692 switch (closeLastViewCO->currentIndex()) {
2694 rc.close_buffer_with_last_view = "yes";
2697 rc.close_buffer_with_last_view = "no";
2700 rc.close_buffer_with_last_view = "ask";
2708 void PrefDocHandling::updateRC(LyXRC const & rc)
2710 restoreCursorCB->setChecked(rc.use_lastfilepos);
2711 loadSessionCB->setChecked(rc.load_session);
2712 allowGeometrySessionCB->setChecked(rc.allow_geometry_session);
2713 // convert to minutes
2714 bool autosave = rc.autosave > 0;
2715 int mins = rc.autosave / 60;
2718 autoSaveSB->setValue(mins);
2719 autoSaveCB->setChecked(autosave);
2720 autoSaveSB->setEnabled(autosave);
2721 backupCB->setChecked(rc.make_backup);
2722 saveCompressedCB->setChecked(rc.save_compressed);
2723 saveOriginCB->setChecked(rc.save_origin);
2724 openDocumentsInTabsCB->setChecked(rc.open_buffers_in_tabs);
2725 singleInstanceCB->setChecked(rc.single_instance && !rc.lyxpipes.empty());
2726 singleInstanceCB->setEnabled(!rc.lyxpipes.empty());
2727 singleCloseTabButtonCB->setChecked(rc.single_close_tab_button);
2728 if (rc.close_buffer_with_last_view == "yes")
2729 closeLastViewCO->setCurrentIndex(0);
2730 else if (rc.close_buffer_with_last_view == "no")
2731 closeLastViewCO->setCurrentIndex(1);
2732 else if (rc.close_buffer_with_last_view == "ask")
2733 closeLastViewCO->setCurrentIndex(2);
2737 void PrefDocHandling::on_clearSessionPB_clicked()
2739 guiApp->clearSession();
2744 /////////////////////////////////////////////////////////////////////
2748 /////////////////////////////////////////////////////////////////////
2750 PrefEdit::PrefEdit(GuiPreferences * form)
2751 : PrefModule(catEditing, N_("Control"), form)
2755 connect(cursorFollowsCB, SIGNAL(clicked()),
2756 this, SIGNAL(changed()));
2757 connect(scrollBelowCB, SIGNAL(clicked()),
2758 this, SIGNAL(changed()));
2759 connect(macLikeCursorMovementCB, SIGNAL(clicked()),
2760 this, SIGNAL(changed()));
2761 connect(copyCTMarkupCB, SIGNAL(clicked()),
2762 this, SIGNAL(changed()));
2763 connect(sortEnvironmentsCB, SIGNAL(clicked()),
2764 this, SIGNAL(changed()));
2765 connect(groupEnvironmentsCB, SIGNAL(clicked()),
2766 this, SIGNAL(changed()));
2767 connect(macroEditStyleCO, SIGNAL(activated(int)),
2768 this, SIGNAL(changed()));
2769 connect(cursorWidthSB, SIGNAL(valueChanged(int)),
2770 this, SIGNAL(changed()));
2771 connect(citationSearchLE, SIGNAL(textChanged(QString)),
2772 this, SIGNAL(changed()));
2773 connect(fullscreenWidthSB, SIGNAL(valueChanged(int)),
2774 this, SIGNAL(changed()));
2775 connect(toggleTabbarCB, SIGNAL(toggled(bool)),
2776 this, SIGNAL(changed()));
2777 connect(toggleMenubarCB, SIGNAL(toggled(bool)),
2778 this, SIGNAL(changed()));
2779 connect(toggleScrollbarCB, SIGNAL(toggled(bool)),
2780 this, SIGNAL(changed()));
2781 connect(toggleStatusbarCB, SIGNAL(toggled(bool)),
2782 this, SIGNAL(changed()));
2783 connect(toggleToolbarsCB, SIGNAL(toggled(bool)),
2784 this, SIGNAL(changed()));
2788 void PrefEdit::on_fullscreenLimitCB_toggled(bool const state)
2790 fullscreenWidthSB->setEnabled(state);
2791 fullscreenWidthLA->setEnabled(state);
2796 void PrefEdit::on_citationSearchCB_toggled(bool const state)
2798 citationSearchLE->setEnabled(state);
2799 citationSearchLA->setEnabled(state);
2804 void PrefEdit::applyRC(LyXRC & rc) const
2806 rc.cursor_follows_scrollbar = cursorFollowsCB->isChecked();
2807 rc.scroll_below_document = scrollBelowCB->isChecked();
2808 rc.mac_like_cursor_movement = macLikeCursorMovementCB->isChecked();
2809 rc.ct_markup_copied = copyCTMarkupCB->isChecked();
2810 rc.sort_layouts = sortEnvironmentsCB->isChecked();
2811 rc.group_layouts = groupEnvironmentsCB->isChecked();
2812 switch (macroEditStyleCO->currentIndex()) {
2813 case 0: rc.macro_edit_style = LyXRC::MACRO_EDIT_INLINE_BOX; break;
2814 case 1: rc.macro_edit_style = LyXRC::MACRO_EDIT_INLINE; break;
2815 case 2: rc.macro_edit_style = LyXRC::MACRO_EDIT_LIST; break;
2817 rc.cursor_width = cursorWidthSB->value();
2818 rc.citation_search = citationSearchCB->isChecked();
2819 rc.citation_search_pattern = fromqstr(citationSearchLE->text());
2820 rc.full_screen_toolbars = toggleToolbarsCB->isChecked();
2821 rc.full_screen_scrollbar = toggleScrollbarCB->isChecked();
2822 rc.full_screen_statusbar = toggleStatusbarCB->isChecked();
2823 rc.full_screen_tabbar = toggleTabbarCB->isChecked();
2824 rc.full_screen_menubar = toggleMenubarCB->isChecked();
2825 rc.full_screen_width = fullscreenWidthSB->value();
2826 rc.full_screen_limit = fullscreenLimitCB->isChecked();
2830 void PrefEdit::updateRC(LyXRC const & rc)
2832 cursorFollowsCB->setChecked(rc.cursor_follows_scrollbar);
2833 scrollBelowCB->setChecked(rc.scroll_below_document);
2834 macLikeCursorMovementCB->setChecked(rc.mac_like_cursor_movement);
2835 copyCTMarkupCB->setChecked(rc.ct_markup_copied);
2836 sortEnvironmentsCB->setChecked(rc.sort_layouts);
2837 groupEnvironmentsCB->setChecked(rc.group_layouts);
2838 macroEditStyleCO->setCurrentIndex(rc.macro_edit_style);
2839 cursorWidthSB->setValue(rc.cursor_width);
2840 citationSearchCB->setChecked(rc.citation_search);
2841 citationSearchLE->setText(toqstr(rc.citation_search_pattern));
2842 citationSearchLE->setEnabled(rc.citation_search);
2843 citationSearchLA->setEnabled(rc.citation_search);
2844 toggleScrollbarCB->setChecked(rc.full_screen_scrollbar);
2845 toggleStatusbarCB->setChecked(rc.full_screen_statusbar);
2846 toggleToolbarsCB->setChecked(rc.full_screen_toolbars);
2847 toggleTabbarCB->setChecked(rc.full_screen_tabbar);
2848 toggleMenubarCB->setChecked(rc.full_screen_menubar);
2849 fullscreenWidthSB->setValue(rc.full_screen_width);
2850 fullscreenLimitCB->setChecked(rc.full_screen_limit);
2851 fullscreenWidthSB->setEnabled(rc.full_screen_limit);
2852 fullscreenWidthLA->setEnabled(rc.full_screen_limit);
2856 /////////////////////////////////////////////////////////////////////
2860 /////////////////////////////////////////////////////////////////////
2863 GuiShortcutDialog::GuiShortcutDialog(QWidget * parent) : QDialog(parent)
2865 Ui::shortcutUi::setupUi(this);
2866 QDialog::setModal(true);
2867 lfunLE->setValidator(new NoNewLineValidator(lfunLE));
2871 PrefShortcuts::PrefShortcuts(GuiPreferences * form)
2872 : PrefModule(catEditing, N_("Shortcuts"), form),
2873 editItem_(nullptr), mathItem_(nullptr), bufferItem_(nullptr), layoutItem_(nullptr),
2874 systemItem_(nullptr)
2878 shortcutsTW->setColumnCount(2);
2879 shortcutsTW->headerItem()->setText(0, qt_("Function"));
2880 shortcutsTW->headerItem()->setText(1, qt_("Shortcut"));
2881 shortcutsTW->setSortingEnabled(true);
2882 // Multi-selection can be annoying.
2883 // shortcutsTW->setSelectionMode(QAbstractItemView::MultiSelection);
2885 connect(bindFilePB, SIGNAL(clicked()),
2886 this, SLOT(selectBind()));
2887 connect(bindFileED, SIGNAL(textChanged(QString)),
2888 this, SIGNAL(changed()));
2890 shortcut_ = new GuiShortcutDialog(this);
2891 shortcut_bc_.setPolicy(ButtonPolicy::OkCancelPolicy);
2892 shortcut_bc_.setOK(shortcut_->buttonBox->button(QDialogButtonBox::Ok));
2893 shortcut_bc_.setCancel(shortcut_->buttonBox->button(QDialogButtonBox::Cancel));
2895 connect(shortcut_->buttonBox, SIGNAL(accepted()),
2896 this, SIGNAL(changed()));
2897 connect(shortcut_->buttonBox, SIGNAL(rejected()),
2898 shortcut_, SLOT(reject()));
2899 connect(shortcut_->clearPB, SIGNAL(clicked()),
2900 this, SLOT(shortcutClearPressed()));
2901 connect(shortcut_->removePB, SIGNAL(clicked()),
2902 this, SLOT(shortcutRemovePressed()));
2903 connect(shortcut_->buttonBox, SIGNAL(accepted()),
2904 this, SLOT(shortcutOkPressed()));
2905 connect(shortcut_->buttonBox, SIGNAL(rejected()),
2906 this, SLOT(shortcutCancelPressed()));
2910 void PrefShortcuts::applyRC(LyXRC & rc) const
2912 rc.bind_file = internal_path(fromqstr(bindFileED->text()));
2913 // write user_bind and user_unbind to .lyx/bind/user.bind
2914 FileName bind_dir(addPath(package().user_support().absFileName(), "bind"));
2915 if (!bind_dir.exists() && !bind_dir.createDirectory(0777)) {
2916 lyxerr << "LyX could not create the user bind directory '"
2917 << bind_dir << "'. All user-defined key bindings will be lost." << endl;
2920 if (!bind_dir.isDirWritable()) {
2921 lyxerr << "LyX could not write to the user bind directory '"
2922 << bind_dir << "'. All user-defined key bindings will be lost." << endl;
2925 FileName user_bind_file(bind_dir.absFileName() + "/user.bind");
2926 user_unbind_.write(user_bind_file.toFilesystemEncoding(), false, true);
2927 user_bind_.write(user_bind_file.toFilesystemEncoding(), true, false);
2928 // immediately apply the keybindings. Why this is not done before?
2929 // The good thing is that the menus are updated automatically.
2930 theTopLevelKeymap().clear();
2931 theTopLevelKeymap().read("site");
2932 theTopLevelKeymap().read(rc.bind_file, nullptr, KeyMap::Fallback);
2933 theTopLevelKeymap().read("user", nullptr, KeyMap::MissingOK);
2937 void PrefShortcuts::updateRC(LyXRC const & rc)
2939 bindFileED->setText(toqstr(external_path(rc.bind_file)));
2941 system_bind_.clear();
2943 user_unbind_.clear();
2944 system_bind_.read("site");
2945 system_bind_.read(rc.bind_file);
2946 // \unbind in user.bind is added to user_unbind_
2947 user_bind_.read("user", &user_unbind_, KeyMap::MissingOK);
2948 updateShortcutsTW();
2952 void PrefShortcuts::updateShortcutsTW()
2954 shortcutsTW->clear();
2956 editItem_ = new QTreeWidgetItem(shortcutsTW);
2957 editItem_->setText(0, qt_("Cursor, Mouse and Editing Functions"));
2958 editItem_->setFlags(editItem_->flags() & ~Qt::ItemIsSelectable);
2960 mathItem_ = new QTreeWidgetItem(shortcutsTW);
2961 mathItem_->setText(0, qt_("Mathematical Symbols"));
2962 mathItem_->setFlags(mathItem_->flags() & ~Qt::ItemIsSelectable);
2964 bufferItem_ = new QTreeWidgetItem(shortcutsTW);
2965 bufferItem_->setText(0, qt_("Document and Window"));
2966 bufferItem_->setFlags(bufferItem_->flags() & ~Qt::ItemIsSelectable);
2968 layoutItem_ = new QTreeWidgetItem(shortcutsTW);
2969 layoutItem_->setText(0, qt_("Font, Layouts and Textclasses"));
2970 layoutItem_->setFlags(layoutItem_->flags() & ~Qt::ItemIsSelectable);
2972 systemItem_ = new QTreeWidgetItem(shortcutsTW);
2973 systemItem_->setText(0, qt_("System and Miscellaneous"));
2974 systemItem_->setFlags(systemItem_->flags() & ~Qt::ItemIsSelectable);
2976 // listBindings(unbound=true) lists all bound and unbound lfuns
2977 // Items in this list is tagged by its source.
2978 KeyMap::BindingList bindinglist = system_bind_.listBindings(true,
2980 KeyMap::BindingList user_bindinglist = user_bind_.listBindings(false,
2982 KeyMap::BindingList user_unbindinglist = user_unbind_.listBindings(false,
2983 KeyMap::UserUnbind);
2984 bindinglist.insert(bindinglist.end(), user_bindinglist.begin(),
2985 user_bindinglist.end());
2986 bindinglist.insert(bindinglist.end(), user_unbindinglist.begin(),
2987 user_unbindinglist.end());
2989 KeyMap::BindingList::const_iterator it = bindinglist.begin();
2990 KeyMap::BindingList::const_iterator it_end = bindinglist.end();
2991 for (; it != it_end; ++it)
2992 insertShortcutItem(it->request, it->sequence, it->tag);
2994 shortcutsTW->sortItems(0, Qt::AscendingOrder);
2995 on_shortcutsTW_itemSelectionChanged();
2996 on_searchLE_textEdited();
2997 shortcutsTW->resizeColumnToContents(0);
3002 KeyMap::ItemType PrefShortcuts::itemType(QTreeWidgetItem & item)
3004 return static_cast<KeyMap::ItemType>(item.data(0, Qt::UserRole).toInt());
3009 bool PrefShortcuts::isAlwaysHidden(QTreeWidgetItem & item)
3011 // Hide rebound system settings that are empty
3012 return itemType(item) == KeyMap::UserUnbind && item.text(1).isEmpty();
3016 void PrefShortcuts::setItemType(QTreeWidgetItem * item, KeyMap::ItemType tag)
3018 item->setData(0, Qt::UserRole, QVariant(tag));
3022 case KeyMap::System:
3024 case KeyMap::UserBind:
3027 case KeyMap::UserUnbind:
3028 font.setStrikeOut(true);
3030 // this item is not displayed now.
3031 case KeyMap::UserExtraUnbind:
3032 font.setStrikeOut(true);
3035 item->setHidden(isAlwaysHidden(*item));
3036 item->setFont(1, font);
3040 QTreeWidgetItem * PrefShortcuts::insertShortcutItem(FuncRequest const & lfun,
3041 KeySequence const & seq, KeyMap::ItemType tag)
3043 FuncCode const action = lfun.action();
3044 string const action_name = lyxaction.getActionName(action);
3045 QString const lfun_name = toqstr(from_utf8(action_name)
3046 + ' ' + lfun.argument());
3047 QString const shortcut = toqstr(seq.print(KeySequence::ForGui));
3049 QTreeWidgetItem * newItem = nullptr;
3050 // for unbind items, try to find an existing item in the system bind list
3051 if (tag == KeyMap::UserUnbind) {
3052 QList<QTreeWidgetItem*> const items = shortcutsTW->findItems(lfun_name,
3053 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 0);
3054 for (auto const & item : items) {
3055 if (item->text(1) == shortcut) {
3060 // if not found, this unbind item is KeyMap::UserExtraUnbind
3061 // Such an item is not displayed to avoid confusion (what is
3062 // unmatched removed?).
3068 switch(lyxaction.getActionType(action)) {
3069 case LyXAction::Hidden:
3071 case LyXAction::Edit:
3072 newItem = new QTreeWidgetItem(editItem_);
3074 case LyXAction::Math:
3075 newItem = new QTreeWidgetItem(mathItem_);
3077 case LyXAction::Buffer:
3078 newItem = new QTreeWidgetItem(bufferItem_);
3080 case LyXAction::Layout:
3081 newItem = new QTreeWidgetItem(layoutItem_);
3083 case LyXAction::System:
3084 newItem = new QTreeWidgetItem(systemItem_);
3087 // this should not happen
3088 newItem = new QTreeWidgetItem(shortcutsTW);
3092 newItem->setText(0, lfun_name);
3093 newItem->setText(1, shortcut);
3094 // record BindFile representation to recover KeySequence when needed.
3095 newItem->setData(1, Qt::UserRole, toqstr(seq.print(KeySequence::BindFile)));
3096 setItemType(newItem, tag);
3101 void PrefShortcuts::on_shortcutsTW_itemSelectionChanged()
3103 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
3104 removePB->setEnabled(!items.isEmpty() && !items[0]->text(1).isEmpty());
3105 modifyPB->setEnabled(!items.isEmpty());
3106 if (items.isEmpty())
3109 if (itemType(*items[0]) == KeyMap::UserUnbind)
3110 removePB->setText(qt_("Res&tore"));
3112 removePB->setText(qt_("Remo&ve"));
3116 void PrefShortcuts::on_shortcutsTW_itemDoubleClicked()
3122 void PrefShortcuts::modifyShortcut()
3124 QTreeWidgetItem * item = shortcutsTW->currentItem();
3125 if (item->flags() & Qt::ItemIsSelectable) {
3126 shortcut_->lfunLE->setText(item->text(0));
3127 save_lfun_ = item->text(0).trimmed();
3128 shortcut_->shortcutWG->setText(item->text(1));
3130 seq.parse(fromqstr(item->data(1, Qt::UserRole).toString()));
3131 shortcut_->shortcutWG->setKeySequence(seq);
3132 shortcut_->shortcutWG->setFocus();
3138 void PrefShortcuts::unhideEmpty(QString const & lfun, bool select)
3140 // list of items that match lfun
3141 QList<QTreeWidgetItem*> items = shortcutsTW->findItems(lfun,
3142 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 0);
3143 for (auto const & item : items) {
3144 if (isAlwaysHidden(*item)) {
3145 setItemType(item, KeyMap::System);
3147 shortcutsTW->setCurrentItem(item);
3154 void PrefShortcuts::removeShortcut()
3156 // it seems that only one item can be selected, but I am
3157 // removing all selected items anyway.
3158 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
3159 for (auto & item : items) {
3160 string shortcut = fromqstr(item->data(1, Qt::UserRole).toString());
3161 string lfun = fromqstr(item->text(0));
3162 FuncRequest const func = lyxaction.lookupFunc(lfun);
3164 switch (itemType(*item)) {
3165 case KeyMap::System: {
3166 // for system bind, we do not touch the item
3167 // but add an user unbind item
3168 user_unbind_.bind(shortcut, func);
3169 setItemType(item, KeyMap::UserUnbind);
3170 removePB->setText(qt_("Res&tore"));
3173 case KeyMap::UserBind: {
3174 // for user_bind, we remove this bind
3175 QTreeWidgetItem * parent = item->parent();
3176 int itemIdx = parent->indexOfChild(item);
3177 parent->takeChild(itemIdx);
3179 shortcutsTW->scrollToItem(parent->child(itemIdx - 1));
3181 shortcutsTW->scrollToItem(parent);
3182 user_bind_.unbind(shortcut, func);
3183 // If this user binding hid an empty system binding, unhide the
3184 // latter and select it.
3185 unhideEmpty(item->text(0), true);
3188 case KeyMap::UserUnbind: {
3189 // for user_unbind, we remove the unbind, and the item
3190 // become KeyMap::System again.
3192 seq.parse(shortcut);
3193 // Ask the user to replace current binding
3194 if (!validateNewShortcut(func, seq, QString()))
3196 user_unbind_.unbind(shortcut, func);
3197 setItemType(item, KeyMap::System);
3198 removePB->setText(qt_("Remo&ve"));
3201 case KeyMap::UserExtraUnbind: {
3202 // for user unbind that is not in system bind file,
3203 // remove this unbind file
3204 QTreeWidgetItem * parent = item->parent();
3205 parent->takeChild(parent->indexOfChild(item));
3206 user_unbind_.unbind(shortcut, func);
3213 void PrefShortcuts::deactivateShortcuts(QList<QTreeWidgetItem*> const & items)
3215 for (auto item : items) {
3216 string shortcut = fromqstr(item->data(1, Qt::UserRole).toString());
3217 string lfun = fromqstr(item->text(0));
3218 FuncRequest const func = lyxaction.lookupFunc(lfun);
3220 switch (itemType(*item)) {
3221 case KeyMap::System:
3222 // for system bind, we do not touch the item
3223 // but add an user unbind item
3224 user_unbind_.bind(shortcut, func);
3225 setItemType(item, KeyMap::UserUnbind);
3228 case KeyMap::UserBind: {
3229 // for user_bind, we remove this bind
3230 QTreeWidgetItem * parent = item->parent();
3231 int itemIdx = parent->indexOfChild(item);
3232 parent->takeChild(itemIdx);
3233 user_bind_.unbind(shortcut, func);
3234 unhideEmpty(item->text(0), false);
3244 void PrefShortcuts::selectBind()
3246 QString file = form_->browsebind(internalPath(bindFileED->text()));
3247 if (!file.isEmpty()) {
3248 bindFileED->setText(file);
3249 system_bind_ = KeyMap();
3250 system_bind_.read(fromqstr(file));
3251 updateShortcutsTW();
3256 void PrefShortcuts::on_modifyPB_pressed()
3262 void PrefShortcuts::on_newPB_pressed()
3264 shortcut_->lfunLE->clear();
3265 shortcut_->shortcutWG->reset();
3266 save_lfun_ = QString();
3271 void PrefShortcuts::on_removePB_pressed()
3278 void PrefShortcuts::on_searchLE_textEdited()
3280 if (searchLE->text().isEmpty()) {
3281 // show all hidden items
3282 QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Hidden);
3284 (*it)->setHidden(isAlwaysHidden(**it));
3285 // close all categories
3286 for (int i = 0; i < shortcutsTW->topLevelItemCount(); ++i)
3287 shortcutsTW->collapseItem(shortcutsTW->topLevelItem(i));
3290 // search both columns
3291 QList<QTreeWidgetItem *> matched = shortcutsTW->findItems(searchLE->text(),
3292 Qt::MatchFlags(Qt::MatchContains | Qt::MatchRecursive), 0);
3293 matched += shortcutsTW->findItems(searchLE->text(),
3294 Qt::MatchFlags(Qt::MatchContains | Qt::MatchRecursive), 1);
3296 // hide everyone (to avoid searching in matched QList repeatedly
3297 QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Selectable);
3299 (*it++)->setHidden(true);
3300 // show matched items
3301 for (auto & item : matched)
3302 if (!isAlwaysHidden(*item)) {
3303 item->setHidden(false);
3305 item->parent()->setExpanded(true);
3310 docstring makeCmdString(FuncRequest const & f)
3312 docstring actionStr = from_ascii(lyxaction.getActionName(f.action()));
3313 if (!f.argument().empty())
3314 actionStr += " " + f.argument();
3319 FuncRequest PrefShortcuts::currentBinding(KeySequence const & k)
3321 FuncRequest res = user_bind_.getBinding(k);
3322 if (res.action() != LFUN_UNKNOWN_ACTION)
3324 res = system_bind_.getBinding(k);
3325 // Check if it is unbound. Note: user_unbind_ can only unbind one
3326 // FuncRequest per key sequence.
3327 if (user_unbind_.getBinding(k) == res)
3328 return FuncRequest::unknown;
3333 bool PrefShortcuts::validateNewShortcut(FuncRequest const & func,
3334 KeySequence const & k,
3335 QString const & lfun_to_modify)
3337 if (func.action() == LFUN_UNKNOWN_ACTION) {
3338 Alert::error(_("Failed to create shortcut"),
3339 _("Unknown or invalid LyX function"));
3343 // It is not currently possible to bind Hidden lfuns such as self-insert. In
3344 // the future, to remove this limitation, see GuiPrefs::insertShortcutItem
3345 // and how it is used in GuiPrefs::shortcutOkPressed.
3346 if (lyxaction.getActionType(func.action()) == LyXAction::Hidden) {
3347 Alert::error(_("Failed to create shortcut"),
3348 _("This LyX function is hidden and cannot be bound."));
3352 if (k.length() == 0) {
3353 Alert::error(_("Failed to create shortcut"),
3354 _("Invalid or empty key sequence"));
3358 FuncRequest oldBinding = currentBinding(k);
3359 if (oldBinding == func)
3360 // nothing to change
3363 // make sure this key isn't already bound---and, if so, prompt user
3364 // (exclude the lfun the user already wants to modify)
3365 docstring const action_string = makeCmdString(oldBinding);
3366 if (oldBinding.action() != LFUN_UNKNOWN_ACTION
3367 && lfun_to_modify != toqstr(action_string)) {
3368 docstring const new_action_string = makeCmdString(func);
3369 docstring const text = bformat(_("Shortcut `%1$s' is already bound to "
3371 "Are you sure you want to unbind the "
3372 "current shortcut and bind it to %3$s?"),
3373 k.print(KeySequence::ForGui), action_string,
3375 int ret = Alert::prompt(_("Redefine shortcut?"),
3376 text, 0, 1, _("&Redefine"), _("&Cancel"));
3379 QString const sequence_text = toqstr(k.print(KeySequence::ForGui));
3380 QList<QTreeWidgetItem*> items = shortcutsTW->findItems(sequence_text,
3381 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 1);
3382 deactivateShortcuts(items);
3388 void PrefShortcuts::shortcutOkPressed()
3390 QString const new_lfun = shortcut_->lfunLE->text();
3391 FuncRequest const func = lyxaction.lookupFunc(fromqstr(new_lfun));
3392 KeySequence k = shortcut_->shortcutWG->getKeySequence();
3394 // save_lfun_ contains the text of the lfun to modify, if the user clicked
3395 // "modify", or is empty if they clicked "new" (which I do not really like)
3396 if (!validateNewShortcut(func, k, save_lfun_))
3399 if (!save_lfun_.isEmpty()) {
3400 // real modification of the lfun's shortcut,
3401 // so remove the previous one
3402 QList<QTreeWidgetItem*> to_modify = shortcutsTW->selectedItems();
3403 deactivateShortcuts(to_modify);
3406 shortcut_->accept();
3408 QTreeWidgetItem * item = insertShortcutItem(func, k, KeyMap::UserBind);
3410 user_bind_.bind(&k, func);
3411 shortcutsTW->sortItems(0, Qt::AscendingOrder);
3412 item->parent()->setExpanded(true);
3413 shortcutsTW->setCurrentItem(item);
3414 shortcutsTW->scrollToItem(item);
3416 Alert::error(_("Failed to create shortcut"),
3417 _("Can not insert shortcut to the list"));
3423 void PrefShortcuts::shortcutCancelPressed()
3425 shortcut_->shortcutWG->reset();
3429 void PrefShortcuts::shortcutClearPressed()
3431 shortcut_->shortcutWG->reset();
3435 void PrefShortcuts::shortcutRemovePressed()
3437 shortcut_->shortcutWG->removeFromSequence();
3441 /////////////////////////////////////////////////////////////////////
3445 /////////////////////////////////////////////////////////////////////
3447 PrefIdentity::PrefIdentity(GuiPreferences * form)
3448 : PrefModule(QString(), N_("Identity"), form)
3452 connect(nameED, SIGNAL(textChanged(QString)),
3453 this, SIGNAL(changed()));
3454 connect(emailED, SIGNAL(textChanged(QString)),
3455 this, SIGNAL(changed()));
3456 connect(initialsED, SIGNAL(textChanged(QString)),
3457 this, SIGNAL(changed()));
3459 nameED->setValidator(new NoNewLineValidator(nameED));
3460 emailED->setValidator(new NoNewLineValidator(emailED));
3461 initialsED->setValidator(new NoNewLineValidator(initialsED));
3465 void PrefIdentity::applyRC(LyXRC & rc) const
3467 rc.user_name = fromqstr(nameED->text());
3468 rc.user_email = fromqstr(emailED->text());
3469 rc.user_initials = fromqstr(initialsED->text());
3473 void PrefIdentity::updateRC(LyXRC const & rc)
3475 nameED->setText(toqstr(rc.user_name));
3476 emailED->setText(toqstr(rc.user_email));
3477 initialsED->setText(toqstr(rc.user_initials));
3482 /////////////////////////////////////////////////////////////////////
3486 /////////////////////////////////////////////////////////////////////
3488 GuiPreferences::GuiPreferences(GuiView & lv)
3489 : GuiDialog(lv, "prefs", qt_("Preferences"))
3493 QDialog::setModal(false);
3495 connect(buttonBox, SIGNAL(clicked(QAbstractButton *)),
3496 this, SLOT(slotButtonBox(QAbstractButton *)));
3498 addModule(new PrefUserInterface(this));
3499 addModule(new PrefDocHandling(this));
3500 addModule(new PrefEdit(this));
3501 addModule(new PrefShortcuts(this));
3502 PrefScreenFonts * screenfonts = new PrefScreenFonts(this);
3503 connect(this, SIGNAL(prefsApplied(LyXRC const &)),
3504 screenfonts, SLOT(updateScreenFontSizes(LyXRC const &)));
3505 addModule(screenfonts);
3506 addModule(new PrefColors(this));
3507 addModule(new PrefDisplay(this));
3508 addModule(new PrefInput(this));
3509 addModule(new PrefCompletion(this));
3511 addModule(new PrefPaths(this));
3513 addModule(new PrefIdentity(this));
3515 addModule(new PrefLanguage(this));
3516 addModule(new PrefSpellchecker(this));
3518 PrefOutput * output = new PrefOutput(this);
3520 addModule(new PrefLatex(this));
3522 PrefConverters * converters = new PrefConverters(this);
3523 PrefFileformats * formats = new PrefFileformats(this);
3524 connect(formats, SIGNAL(formatsChanged()),
3525 converters, SLOT(updateGui()));
3526 addModule(converters);
3529 prefsPS->setCurrentPanel("User Interface");
3530 // FIXME: hack to work around resizing bug in Qt >= 4.2
3531 // bug verified with Qt 4.2.{0-3} (JSpitzm)
3532 #if QT_VERSION >= 0x040200
3533 prefsPS->updateGeometry();
3536 bc().setPolicy(ButtonPolicy::PreferencesPolicy);
3537 bc().setOK(buttonBox->button(QDialogButtonBox::Ok));
3538 bc().setApply(buttonBox->button(QDialogButtonBox::Apply));
3539 bc().setCancel(buttonBox->button(QDialogButtonBox::Cancel));
3540 bc().setRestore(buttonBox->button(QDialogButtonBox::Reset));
3542 guilyxfiles_ = new GuiLyXFiles(lv);
3543 connect(guilyxfiles_, SIGNAL(fileSelected(QString)),
3544 this, SLOT(slotFileSelected(QString)));
3548 void GuiPreferences::addModule(PrefModule * module)
3550 LASSERT(module, return);
3551 if (module->category().isEmpty())
3552 prefsPS->addPanel(module, module->title());
3554 prefsPS->addPanel(module, module->title(), module->category());
3555 connect(module, SIGNAL(changed()), this, SLOT(change_adaptor()));
3556 modules_.push_back(module);
3560 void GuiPreferences::change_adaptor()
3566 void GuiPreferences::applyRC(LyXRC & rc) const
3568 size_t end = modules_.size();
3569 for (size_t i = 0; i != end; ++i)
3570 modules_[i]->applyRC(rc);
3574 void GuiPreferences::updateRC(LyXRC const & rc)
3576 size_t const end = modules_.size();
3577 for (size_t i = 0; i != end; ++i)
3578 modules_[i]->updateRC(rc);
3582 void GuiPreferences::applyView()
3588 bool GuiPreferences::initialiseParams(string const &)
3591 formats_ = theFormats();
3592 converters_ = theConverters();
3593 converters_.update(formats_);
3594 movers_ = theMovers();
3598 // Make sure that the bc is in the INITIAL state
3599 if (bc().policy().buttonStatus(ButtonPolicy::RESTORE))
3606 void GuiPreferences::dispatchParams()
3609 rc_.write(ss, true);
3610 dispatch(FuncRequest(LFUN_LYXRC_APPLY, ss.str()));
3611 // issue prefsApplied signal. This will update the
3612 // localized screen font sizes.
3614 // FIXME: these need lfuns
3616 Author const & author =
3617 Author(from_utf8(rc_.user_name), from_utf8(rc_.user_email),
3618 from_utf8(rc_.user_initials));
3619 theBufferList().recordCurrentAuthor(author);
3621 theFormats() = formats_;
3623 theConverters() = converters_;
3624 theConverters().update(formats_);
3625 theConverters().buildGraph();
3626 theBufferList().invalidateConverterCache();
3628 theMovers() = movers_;
3630 for (string const & color : colors_)
3631 dispatch(FuncRequest(LFUN_SET_COLOR, color));
3635 if (!tempSaveCB->isChecked())
3636 dispatch(FuncRequest(LFUN_PREFERENCES_SAVE));
3640 void GuiPreferences::setColor(ColorCode col, QString const & hex)
3642 colors_.push_back(lcolor.getLyXName(col) + ' ' + fromqstr(hex));
3646 void GuiPreferences::slotFileSelected(QString const file)
3652 QString GuiPreferences::browseLibFile(QString const & dir,
3653 QString const & name, QString const & ext)
3657 guilyxfiles_->passParams(fromqstr(dir));
3658 guilyxfiles_->selectItem(name);
3659 guilyxfiles_->exec();
3661 QString const result = uifile_;
3663 // remove the extension if it is the default one
3664 QString noextresult;
3665 if (getExtension(result) == ext)
3666 noextresult = removeExtension(result);
3668 noextresult = result;
3670 // remove the directory, if it is the default one
3671 QString const file = onlyFileName(noextresult);
3672 if (toqstr(libFileSearch(dir, file, ext).absFileName()) == result)
3679 QString GuiPreferences::browsebind(QString const & file)
3681 return browseLibFile("bind", file, "bind");
3685 QString GuiPreferences::browseUI(QString const & file)
3687 return browseLibFile("ui", file, "ui");
3691 QString GuiPreferences::browsekbmap(QString const & file)
3693 return browseLibFile("kbd", file, "kmap");
3697 QString GuiPreferences::browse(QString const & file,
3698 QString const & title) const
3700 return browseFile(file, title, QStringList(), true);
3704 } // namespace frontend
3707 #include "moc_GuiPrefs.cpp"