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 "graphics/GraphicsTypes.h"
54 #include "frontends/alert.h"
55 #include "frontends/Application.h"
56 #include "frontends/FontLoader.h"
58 #include <QAbstractItemModel>
60 #include <QColorDialog>
61 #include <QFontDatabase>
62 #include <QHeaderView>
64 #include <QMessageBox>
65 #include <QPushButton>
68 #include <QTreeWidget>
69 #include <QTreeWidgetItem>
80 using namespace lyx::support;
81 using namespace lyx::support::os;
86 /////////////////////////////////////////////////////////////////////
90 /////////////////////////////////////////////////////////////////////
92 /** Launch a file dialog and return the chosen file.
93 filename: a suggested filename.
94 title: the title of the dialog.
96 dir1 = (name, dir), dir2 = (name, dir): extra buttons on the dialog.
98 QString browseFile(QString const & filename,
99 QString const & title,
100 QStringList const & filters,
102 QString const & label1 = QString(),
103 QString const & dir1 = QString(),
104 QString const & label2 = QString(),
105 QString const & dir2 = QString(),
106 QString const & fallback_dir = QString())
108 QString lastPath = ".";
109 if (!filename.isEmpty())
110 lastPath = onlyPath(filename);
111 else if(!fallback_dir.isEmpty())
112 lastPath = fallback_dir;
114 FileDialog dlg(title);
115 dlg.setButton1(label1, dir1);
116 dlg.setButton2(label2, dir2);
118 FileDialog::Result result;
121 result = dlg.save(lastPath, filters, onlyFileName(filename));
123 result = dlg.open(lastPath, filters, onlyFileName(filename));
125 return result.second;
129 /** Launch a file dialog and return the chosen directory.
130 pathname: a suggested pathname.
131 title: the title of the dialog.
132 dir1 = (name, dir), dir2 = (name, dir): extra buttons on the dialog.
134 QString browseDir(QString const & pathname,
135 QString const & title,
136 QString const & label1 = QString(),
137 QString const & dir1 = QString(),
138 QString const & label2 = QString(),
139 QString const & dir2 = QString())
141 QString lastPath = ".";
142 if (!pathname.isEmpty())
143 lastPath = onlyPath(pathname);
145 FileDialog dlg(title);
146 dlg.setButton1(label1, dir1);
147 dlg.setButton2(label2, dir2);
149 FileDialog::Result const result =
150 dlg.opendir(lastPath, onlyFileName(pathname));
152 return result.second;
156 } // namespace frontend
159 QString browseRelToParent(QString const & filename, QString const & relpath,
160 QString const & title, QStringList const & filters, bool save,
161 QString const & label1, QString const & dir1,
162 QString const & label2, QString const & dir2)
164 QString const fname = makeAbsPath(filename, relpath);
166 QString const outname =
167 frontend::browseFile(fname, title, filters, save, label1, dir1, label2, dir2);
169 QString const reloutname =
170 toqstr(makeRelPath(qstring_to_ucs4(outname), qstring_to_ucs4(relpath)));
172 if (reloutname.startsWith("../"))
179 QString browseRelToSub(QString const & filename, QString const & relpath,
180 QString const & title, QStringList const & filters, bool save,
181 QString const & label1, QString const & dir1,
182 QString const & label2, QString const & dir2)
184 QString const fname = makeAbsPath(filename, relpath);
186 QString const outname =
187 frontend::browseFile(fname, title, filters, save, label1, dir1, label2, dir2);
189 QString const reloutname =
190 toqstr(makeRelPath(qstring_to_ucs4(outname), qstring_to_ucs4(relpath)));
192 QString testname = reloutname;
193 testname.remove(QRegExp("^(\\.\\./)+"));
195 if (testname.contains("/"))
203 /////////////////////////////////////////////////////////////////////
207 /////////////////////////////////////////////////////////////////////
211 QString const catLookAndFeel = N_("Look & Feel");
212 QString const catEditing = N_("Editing");
213 QString const catLanguage = N_("Language Settings");
214 QString const catOutput = N_("Output");
215 QString const catFiles = N_("File Handling");
217 static void parseFontName(QString const & mangled0,
218 string & name, string & foundry)
220 string mangled = fromqstr(mangled0);
221 size_t const idx = mangled.find('[');
222 if (idx == string::npos || idx == 0) {
226 name = mangled.substr(0, idx - 1);
227 foundry = mangled.substr(idx + 1, mangled.size() - idx - 2);
232 static void setComboxFont(QComboBox * cb, string const & family,
233 string const & foundry)
235 QString fontname = toqstr(family);
236 if (!foundry.empty())
237 fontname += " [" + toqstr(foundry) + ']';
239 for (int i = 0; i != cb->count(); ++i) {
240 if (cb->itemText(i) == fontname) {
241 cb->setCurrentIndex(i);
246 // Try matching without foundry name
248 // We count in reverse in order to prefer the Xft foundry
249 for (int i = cb->count(); --i >= 0;) {
250 string name, fnt_foundry;
251 parseFontName(cb->itemText(i), name, fnt_foundry);
252 if (compare_ascii_no_case(name, family) == 0) {
253 cb->setCurrentIndex(i);
258 // family alone can contain e.g. "Helvetica [Adobe]"
259 string tmpname, tmpfoundry;
260 parseFontName(toqstr(family), tmpname, tmpfoundry);
262 // We count in reverse in order to prefer the Xft foundry
263 for (int i = cb->count(); --i >= 0; ) {
264 string name, fnt_foundry;
265 parseFontName(cb->itemText(i), name, fnt_foundry);
266 if (compare_ascii_no_case(name, fnt_foundry) == 0) {
267 cb->setCurrentIndex(i);
272 // Bleh, default fonts, and the names couldn't be found. Hack
277 QString const font_family = toqstr(family);
278 if (font_family == guiApp->romanFontName()) {
279 font.setStyleHint(QFont::Serif);
280 font.setFamily(font_family);
281 } else if (font_family == guiApp->sansFontName()) {
282 font.setStyleHint(QFont::SansSerif);
283 font.setFamily(font_family);
284 } else if (font_family == guiApp->typewriterFontName()) {
285 font.setStyleHint(QFont::TypeWriter);
286 font.setFamily(font_family);
288 LYXERR0("FAILED to find the default font: '"
289 << foundry << "', '" << family << '\'');
293 QFontInfo info(font);
294 string default_font_name, dummyfoundry;
295 parseFontName(info.family(), default_font_name, dummyfoundry);
296 LYXERR0("Apparent font is " << default_font_name);
298 for (int i = 0; i < cb->count(); ++i) {
299 LYXERR0("Looking at " << cb->itemText(i));
300 if (compare_ascii_no_case(fromqstr(cb->itemText(i)),
301 default_font_name) == 0) {
302 cb->setCurrentIndex(i);
307 LYXERR0("FAILED to find the font: '"
308 << foundry << "', '" << family << '\'');
312 /////////////////////////////////////////////////////////////////////
316 /////////////////////////////////////////////////////////////////////
318 PrefOutput::PrefOutput(GuiPreferences * form)
319 : PrefModule(catOutput, N_("General[[settings]]"), form)
323 dviCB->setValidator(new NoNewLineValidator(dviCB));
324 pdfCB->setValidator(new NoNewLineValidator(pdfCB));
326 connect(plaintextLinelengthSB, SIGNAL(valueChanged(int)),
327 this, SIGNAL(changed()));
328 connect(overwriteCO, SIGNAL(activated(int)),
329 this, SIGNAL(changed()));
330 connect(dviCB, SIGNAL(editTextChanged(QString)),
331 this, SIGNAL(changed()));
332 connect(pdfCB, SIGNAL(editTextChanged(QString)),
333 this, SIGNAL(changed()));
334 connect(printerPaperTypeED, SIGNAL(textChanged(QString)),
335 this, SIGNAL(changed()));
336 connect(printerLandscapeED, SIGNAL(textChanged(QString)),
337 this, SIGNAL(changed()));
338 connect(printerPaperSizeED, SIGNAL(textChanged(QString)),
339 this, SIGNAL(changed()));
341 printerPaperTypeED->setValidator(new NoNewLineValidator(printerPaperTypeED));
342 printerLandscapeED->setValidator(new NoNewLineValidator(printerLandscapeED));
343 printerPaperSizeED->setValidator(new NoNewLineValidator(printerPaperSizeED));
346 dviCB->addItem("xdvi -sourceposition '$$n:\\ $$t' $$o");
347 dviCB->addItem("yap -1 -s \"$$n $$t\" $$o");
348 dviCB->addItem("okular --unique \"$$o#src:$$n $$f\"");
349 dviCB->addItem("synctex view -i $$n:0:$$t -o $$o -x \"evince -i %{page+1} $$o\"");
351 pdfCB->addItem("CMCDDE SUMATRA control [ForwardSearch(\\\"$$o\\\",\\\"$$t\\\",$$n,0,0,1)]");
352 pdfCB->addItem("SumatraPDF -reuse-instance \"$$o\" -forward-search \"$$t\" $$n");
353 pdfCB->addItem("synctex view -i $$n:0:$$t -o $$o -x \"xpdf -raise -remote $$t.tmp $$o %{page+1}\"");
354 pdfCB->addItem("okular --unique \"$$o#src:$$n $$f\"");
355 pdfCB->addItem("qpdfview --unique \"$$o#src:$$f:$$n:0\"");
356 pdfCB->addItem("synctex view -i $$n:0:$$t -o $$o -x \"evince -i %{page+1} $$o\"");
357 pdfCB->addItem("/Applications/Skim.app/Contents/SharedSupport/displayline $$n $$o $$t");
361 void PrefOutput::applyRC(LyXRC & rc) const
363 rc.plaintext_linelen = plaintextLinelengthSB->value();
364 rc.forward_search_dvi = fromqstr(dviCB->currentText());
365 rc.forward_search_pdf = fromqstr(pdfCB->currentText());
367 switch (overwriteCO->currentIndex()) {
369 rc.export_overwrite = NO_FILES;
372 rc.export_overwrite = MAIN_FILE;
375 rc.export_overwrite = ALL_FILES;
379 rc.print_paper_flag = fromqstr(printerPaperTypeED->text());
380 rc.print_landscape_flag = fromqstr(printerLandscapeED->text());
381 rc.print_paper_dimension_flag = fromqstr(printerPaperSizeED->text());
385 void PrefOutput::updateRC(LyXRC const & rc)
387 plaintextLinelengthSB->setValue(rc.plaintext_linelen);
388 dviCB->setEditText(toqstr(rc.forward_search_dvi));
389 pdfCB->setEditText(toqstr(rc.forward_search_pdf));
391 switch (rc.export_overwrite) {
393 overwriteCO->setCurrentIndex(0);
396 overwriteCO->setCurrentIndex(1);
399 overwriteCO->setCurrentIndex(2);
403 printerPaperTypeED->setText(toqstr(rc.print_paper_flag));
404 printerLandscapeED->setText(toqstr(rc.print_landscape_flag));
405 printerPaperSizeED->setText(toqstr(rc.print_paper_dimension_flag));
409 /////////////////////////////////////////////////////////////////////
413 /////////////////////////////////////////////////////////////////////
415 PrefInput::PrefInput(GuiPreferences * form)
416 : PrefModule(catEditing, N_("Keyboard/Mouse"), form)
420 connect(keymapCB, SIGNAL(clicked()),
421 this, SIGNAL(changed()));
422 connect(firstKeymapED, SIGNAL(textChanged(QString)),
423 this, SIGNAL(changed()));
424 connect(secondKeymapED, SIGNAL(textChanged(QString)),
425 this, SIGNAL(changed()));
426 connect(mouseWheelSpeedSB, SIGNAL(valueChanged(double)),
427 this, SIGNAL(changed()));
428 connect(scrollzoomEnableCB, SIGNAL(clicked()),
429 this, SIGNAL(changed()));
430 connect(scrollzoomValueCO, SIGNAL(activated(int)),
431 this, SIGNAL(changed()));
432 connect(dontswapCB, SIGNAL(toggled(bool)),
433 this, SIGNAL(changed()));
434 connect(mmPasteCB, SIGNAL(toggled(bool)),
435 this, SIGNAL(changed()));
437 // reveal checkbox for switching Ctrl and Meta on Mac:
440 #if QT_VERSION > 0x040600
444 dontswapCB->setVisible(swapcb);
448 void PrefInput::applyRC(LyXRC & rc) const
450 // FIXME: can derive CB from the two EDs
451 rc.use_kbmap = keymapCB->isChecked();
452 rc.primary_kbmap = internal_path(fromqstr(firstKeymapED->text()));
453 rc.secondary_kbmap = internal_path(fromqstr(secondKeymapED->text()));
454 rc.mouse_wheel_speed = mouseWheelSpeedSB->value();
455 if (scrollzoomEnableCB->isChecked()) {
456 switch (scrollzoomValueCO->currentIndex()) {
458 rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_CTRL;
461 rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_SHIFT;
464 rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_ALT;
468 rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_OFF;
470 rc.mac_dontswap_ctrl_meta = dontswapCB->isChecked();
471 rc.mouse_middlebutton_paste = mmPasteCB->isChecked();
475 void PrefInput::updateRC(LyXRC const & rc)
477 // FIXME: can derive CB from the two EDs
478 keymapCB->setChecked(rc.use_kbmap);
479 firstKeymapED->setText(toqstr(external_path(rc.primary_kbmap)));
480 secondKeymapED->setText(toqstr(external_path(rc.secondary_kbmap)));
481 mouseWheelSpeedSB->setValue(rc.mouse_wheel_speed);
482 switch (rc.scroll_wheel_zoom) {
483 case LyXRC::SCROLL_WHEEL_ZOOM_OFF:
484 scrollzoomEnableCB->setChecked(false);
486 case LyXRC::SCROLL_WHEEL_ZOOM_CTRL:
487 scrollzoomEnableCB->setChecked(true);
488 scrollzoomValueCO->setCurrentIndex(0);
490 case LyXRC::SCROLL_WHEEL_ZOOM_SHIFT:
491 scrollzoomEnableCB->setChecked(true);
492 scrollzoomValueCO->setCurrentIndex(1);
494 case LyXRC::SCROLL_WHEEL_ZOOM_ALT:
495 scrollzoomEnableCB->setChecked(true);
496 scrollzoomValueCO->setCurrentIndex(2);
499 dontswapCB->setChecked(rc.mac_dontswap_ctrl_meta);
500 mmPasteCB->setChecked(rc.mouse_middlebutton_paste);
504 QString PrefInput::testKeymap(QString const & keymap)
506 return form_->browsekbmap(internalPath(keymap));
510 void PrefInput::on_firstKeymapPB_clicked(bool)
512 QString const file = testKeymap(firstKeymapED->text());
514 firstKeymapED->setText(file);
518 void PrefInput::on_secondKeymapPB_clicked(bool)
520 QString const file = testKeymap(secondKeymapED->text());
522 secondKeymapED->setText(file);
526 void PrefInput::on_keymapCB_toggled(bool keymap)
528 firstKeymapLA->setEnabled(keymap);
529 secondKeymapLA->setEnabled(keymap);
530 firstKeymapED->setEnabled(keymap);
531 secondKeymapED->setEnabled(keymap);
532 firstKeymapPB->setEnabled(keymap);
533 secondKeymapPB->setEnabled(keymap);
537 void PrefInput::on_scrollzoomEnableCB_toggled(bool enabled)
539 scrollzoomValueCO->setEnabled(enabled);
543 /////////////////////////////////////////////////////////////////////
547 /////////////////////////////////////////////////////////////////////
549 PrefCompletion::PrefCompletion(GuiPreferences * form)
550 : PrefModule(catEditing, N_("Input Completion"), form)
554 connect(inlineDelaySB, SIGNAL(valueChanged(double)),
555 this, SIGNAL(changed()));
556 connect(inlineMathCB, SIGNAL(clicked()),
557 this, SIGNAL(changed()));
558 connect(inlineTextCB, SIGNAL(clicked()),
559 this, SIGNAL(changed()));
560 connect(inlineDotsCB, SIGNAL(clicked()),
561 this, SIGNAL(changed()));
562 connect(popupDelaySB, SIGNAL(valueChanged(double)),
563 this, SIGNAL(changed()));
564 connect(popupMathCB, SIGNAL(clicked()),
565 this, SIGNAL(changed()));
566 connect(autocorrectionCB, SIGNAL(clicked()),
567 this, SIGNAL(changed()));
568 connect(popupTextCB, SIGNAL(clicked()),
569 this, SIGNAL(changed()));
570 connect(popupAfterCompleteCB, SIGNAL(clicked()),
571 this, SIGNAL(changed()));
572 connect(cursorTextCB, SIGNAL(clicked()),
573 this, SIGNAL(changed()));
574 connect(minlengthSB, SIGNAL(valueChanged(int)),
575 this, SIGNAL(changed()));
579 void PrefCompletion::on_inlineTextCB_clicked()
585 void PrefCompletion::on_popupTextCB_clicked()
591 void PrefCompletion::enableCB()
593 cursorTextCB->setEnabled(
594 popupTextCB->isChecked() || inlineTextCB->isChecked());
598 void PrefCompletion::applyRC(LyXRC & rc) const
600 rc.completion_inline_delay = inlineDelaySB->value();
601 rc.completion_inline_math = inlineMathCB->isChecked();
602 rc.completion_inline_text = inlineTextCB->isChecked();
603 rc.completion_inline_dots = inlineDotsCB->isChecked() ? 13 : -1;
604 rc.completion_popup_delay = popupDelaySB->value();
605 rc.completion_popup_math = popupMathCB->isChecked();
606 rc.autocorrection_math = autocorrectionCB->isChecked();
607 rc.completion_popup_text = popupTextCB->isChecked();
608 rc.completion_cursor_text = cursorTextCB->isChecked();
609 rc.completion_popup_after_complete =
610 popupAfterCompleteCB->isChecked();
611 rc.completion_minlength = minlengthSB->value();
615 void PrefCompletion::updateRC(LyXRC const & rc)
617 inlineDelaySB->setValue(rc.completion_inline_delay);
618 inlineMathCB->setChecked(rc.completion_inline_math);
619 inlineTextCB->setChecked(rc.completion_inline_text);
620 inlineDotsCB->setChecked(rc.completion_inline_dots != -1);
621 popupDelaySB->setValue(rc.completion_popup_delay);
622 popupMathCB->setChecked(rc.completion_popup_math);
623 autocorrectionCB->setChecked(rc.autocorrection_math);
624 popupTextCB->setChecked(rc.completion_popup_text);
625 cursorTextCB->setChecked(rc.completion_cursor_text);
626 popupAfterCompleteCB->setChecked(rc.completion_popup_after_complete);
628 minlengthSB->setValue(rc.completion_minlength);
633 /////////////////////////////////////////////////////////////////////
637 /////////////////////////////////////////////////////////////////////
639 PrefLatex::PrefLatex(GuiPreferences * form)
640 : PrefModule(catOutput, N_("LaTeX"), form)
644 latexDviPaperED->setValidator(new NoNewLineValidator(latexDviPaperED));
645 latexBibtexED->setValidator(new NoNewLineValidator(latexBibtexED));
646 latexJBibtexED->setValidator(new NoNewLineValidator(latexJBibtexED));
647 latexIndexED->setValidator(new NoNewLineValidator(latexIndexED));
648 latexJIndexED->setValidator(new NoNewLineValidator(latexJIndexED));
649 latexNomenclED->setValidator(new NoNewLineValidator(latexNomenclED));
650 latexChecktexED->setValidator(new NoNewLineValidator(latexChecktexED));
652 connect(latexChecktexED, SIGNAL(textChanged(QString)),
653 this, SIGNAL(changed()));
654 connect(latexBibtexCO, SIGNAL(activated(int)),
655 this, SIGNAL(changed()));
656 connect(latexBibtexED, SIGNAL(textChanged(QString)),
657 this, SIGNAL(changed()));
658 connect(latexJBibtexCO, SIGNAL(activated(int)),
659 this, SIGNAL(changed()));
660 connect(latexJBibtexED, SIGNAL(textChanged(QString)),
661 this, SIGNAL(changed()));
662 connect(latexIndexCO, SIGNAL(activated(int)),
663 this, SIGNAL(changed()));
664 connect(latexIndexED, SIGNAL(textChanged(QString)),
665 this, SIGNAL(changed()));
666 connect(latexJIndexED, SIGNAL(textChanged(QString)),
667 this, SIGNAL(changed()));
668 connect(latexAutoresetCB, SIGNAL(clicked()),
669 this, SIGNAL(changed()));
670 connect(latexDviPaperED, SIGNAL(textChanged(QString)),
671 this, SIGNAL(changed()));
672 connect(latexNomenclED, SIGNAL(textChanged(QString)),
673 this, SIGNAL(changed()));
675 #if defined(__CYGWIN__) || defined(_WIN32)
676 pathCB->setVisible(true);
677 connect(pathCB, SIGNAL(clicked()),
678 this, SIGNAL(changed()));
680 pathCB->setVisible(false);
685 void PrefLatex::on_latexBibtexCO_activated(int n)
687 QString const bibtex = latexBibtexCO->itemData(n).toString();
688 if (bibtex.isEmpty()) {
689 latexBibtexED->clear();
690 latexBibtexOptionsLA->setText(qt_("C&ommand:"));
693 for (LyXRC::CommandSet::const_iterator it = bibtex_alternatives.begin();
694 it != bibtex_alternatives.end(); ++it) {
695 QString const bib = toqstr(*it);
696 int ind = bib.indexOf(" ");
697 QString sel_command = bib.left(ind);
698 QString sel_options = ind < 0 ? QString() : bib.mid(ind + 1);
699 if (bibtex == sel_command) {
701 latexBibtexED->clear();
703 latexBibtexED->setText(sel_options.trimmed());
706 latexBibtexOptionsLA->setText(qt_("&Options:"));
710 void PrefLatex::on_latexJBibtexCO_activated(int n)
712 QString const jbibtex = latexJBibtexCO->itemData(n).toString();
713 if (jbibtex.isEmpty()) {
714 latexJBibtexED->clear();
715 latexJBibtexOptionsLA->setText(qt_("Co&mmand:"));
718 for (LyXRC::CommandSet::const_iterator it = jbibtex_alternatives.begin();
719 it != jbibtex_alternatives.end(); ++it) {
720 QString const bib = toqstr(*it);
721 int ind = bib.indexOf(" ");
722 QString sel_command = bib.left(ind);
723 QString sel_options = ind < 0 ? QString() : bib.mid(ind + 1);
724 if (jbibtex == sel_command) {
726 latexJBibtexED->clear();
728 latexJBibtexED->setText(sel_options.trimmed());
731 latexJBibtexOptionsLA->setText(qt_("Opt&ions:"));
735 void PrefLatex::on_latexIndexCO_activated(int n)
737 QString const index = latexIndexCO->itemData(n).toString();
738 if (index.isEmpty()) {
739 latexIndexED->clear();
740 latexIndexOptionsLA->setText(qt_("Co&mmand:"));
743 for (LyXRC::CommandSet::const_iterator it = index_alternatives.begin();
744 it != index_alternatives.end(); ++it) {
745 QString const idx = toqstr(*it);
746 int ind = idx.indexOf(" ");
747 QString sel_command = idx.left(ind);
748 QString sel_options = ind < 0 ? QString() : idx.mid(ind + 1);
749 if (index == sel_command) {
751 latexIndexED->clear();
753 latexIndexED->setText(sel_options.trimmed());
756 latexIndexOptionsLA->setText(qt_("Op&tions:"));
760 void PrefLatex::applyRC(LyXRC & rc) const
762 // If bibtex is not empty, bibopt contains the options, otherwise
763 // it is a customized bibtex command with options.
764 QString const bibtex = latexBibtexCO->itemData(
765 latexBibtexCO->currentIndex()).toString();
766 QString const bibopt = latexBibtexED->text();
767 if (bibtex.isEmpty())
768 rc.bibtex_command = fromqstr(bibopt);
769 else if (bibopt.isEmpty())
770 rc.bibtex_command = fromqstr(bibtex);
772 rc.bibtex_command = fromqstr(bibtex) + " " + fromqstr(bibopt);
774 // If jbibtex is not empty, jbibopt contains the options, otherwise
775 // it is a customized bibtex command with options.
776 QString const jbibtex = latexJBibtexCO->itemData(
777 latexJBibtexCO->currentIndex()).toString();
778 QString const jbibopt = latexJBibtexED->text();
779 if (jbibtex.isEmpty())
780 rc.jbibtex_command = fromqstr(jbibopt);
781 else if (jbibopt.isEmpty())
782 rc.jbibtex_command = fromqstr(jbibtex);
784 rc.jbibtex_command = fromqstr(jbibtex) + " " + fromqstr(jbibopt);
786 // If index is not empty, idxopt contains the options, otherwise
787 // it is a customized index command with options.
788 QString const index = latexIndexCO->itemData(
789 latexIndexCO->currentIndex()).toString();
790 QString const idxopt = latexIndexED->text();
792 rc.index_command = fromqstr(idxopt);
793 else if (idxopt.isEmpty())
794 rc.index_command = fromqstr(index);
796 rc.index_command = fromqstr(index) + " " + fromqstr(idxopt);
798 rc.chktex_command = fromqstr(latexChecktexED->text());
799 rc.jindex_command = fromqstr(latexJIndexED->text());
800 rc.nomencl_command = fromqstr(latexNomenclED->text());
801 rc.auto_reset_options = latexAutoresetCB->isChecked();
802 rc.view_dvi_paper_option = fromqstr(latexDviPaperED->text());
803 #if defined(__CYGWIN__) || defined(_WIN32)
804 rc.windows_style_tex_paths = pathCB->isChecked();
809 void PrefLatex::updateRC(LyXRC const & rc)
811 latexBibtexCO->clear();
813 latexBibtexCO->addItem(qt_("Automatic"), "automatic");
814 latexBibtexCO->addItem(qt_("Custom"), QString());
815 for (LyXRC::CommandSet::const_iterator it = rc.bibtex_alternatives.begin();
816 it != rc.bibtex_alternatives.end(); ++it) {
817 QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
818 latexBibtexCO->addItem(command, command);
821 bibtex_alternatives = rc.bibtex_alternatives;
823 QString const bib = toqstr(rc.bibtex_command);
824 int ind = bib.indexOf(" ");
825 QString sel_command = bib.left(ind);
826 QString sel_options = ind < 0 ? QString() : bib.mid(ind + 1);
828 int pos = latexBibtexCO->findData(sel_command);
830 latexBibtexCO->setCurrentIndex(pos);
831 latexBibtexED->setText(sel_options.trimmed());
832 latexBibtexOptionsLA->setText(qt_("&Options:"));
834 latexBibtexED->setText(toqstr(rc.bibtex_command));
835 latexBibtexCO->setCurrentIndex(0);
836 latexBibtexOptionsLA->setText(qt_("C&ommand:"));
839 latexJBibtexCO->clear();
841 latexJBibtexCO->addItem(qt_("Automatic"), "automatic");
842 latexJBibtexCO->addItem(qt_("Custom"), QString());
843 for (LyXRC::CommandSet::const_iterator it = rc.jbibtex_alternatives.begin();
844 it != rc.jbibtex_alternatives.end(); ++it) {
845 QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
846 latexJBibtexCO->addItem(command, command);
849 jbibtex_alternatives = rc.jbibtex_alternatives;
851 QString const jbib = toqstr(rc.jbibtex_command);
852 ind = jbib.indexOf(" ");
853 sel_command = jbib.left(ind);
854 sel_options = ind < 0 ? QString() : jbib.mid(ind + 1);
856 pos = latexJBibtexCO->findData(sel_command);
858 latexJBibtexCO->setCurrentIndex(pos);
859 latexJBibtexED->setText(sel_options.trimmed());
860 latexJBibtexOptionsLA->setText(qt_("Opt&ions:"));
862 latexJBibtexED->setText(toqstr(rc.bibtex_command));
863 latexJBibtexCO->setCurrentIndex(0);
864 latexJBibtexOptionsLA->setText(qt_("Co&mmand:"));
867 latexIndexCO->clear();
869 latexIndexCO->addItem(qt_("Custom"), QString());
870 for (LyXRC::CommandSet::const_iterator it = rc.index_alternatives.begin();
871 it != rc.index_alternatives.end(); ++it) {
872 QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
873 latexIndexCO->addItem(command, command);
876 index_alternatives = rc.index_alternatives;
878 QString const idx = toqstr(rc.index_command);
879 ind = idx.indexOf(" ");
880 sel_command = idx.left(ind);
881 sel_options = ind < 0 ? QString() : idx.mid(ind + 1);
883 pos = latexIndexCO->findData(sel_command);
885 latexIndexCO->setCurrentIndex(pos);
886 latexIndexED->setText(sel_options.trimmed());
887 latexIndexOptionsLA->setText(qt_("Op&tions:"));
889 latexIndexED->setText(toqstr(rc.index_command));
890 latexIndexCO->setCurrentIndex(0);
891 latexIndexOptionsLA->setText(qt_("Co&mmand:"));
894 latexChecktexED->setText(toqstr(rc.chktex_command));
895 latexJIndexED->setText(toqstr(rc.jindex_command));
896 latexNomenclED->setText(toqstr(rc.nomencl_command));
897 latexAutoresetCB->setChecked(rc.auto_reset_options);
898 latexDviPaperED->setText(toqstr(rc.view_dvi_paper_option));
899 #if defined(__CYGWIN__) || defined(_WIN32)
900 pathCB->setChecked(rc.windows_style_tex_paths);
905 /////////////////////////////////////////////////////////////////////
909 /////////////////////////////////////////////////////////////////////
911 PrefScreenFonts::PrefScreenFonts(GuiPreferences * form)
912 : PrefModule(catLookAndFeel, N_("Screen Fonts"), form)
916 connect(screenRomanCO, SIGNAL(activated(QString)),
917 this, SLOT(selectRoman(QString)));
918 connect(screenSansCO, SIGNAL(activated(QString)),
919 this, SLOT(selectSans(QString)));
920 connect(screenTypewriterCO, SIGNAL(activated(QString)),
921 this, SLOT(selectTypewriter(QString)));
923 QFontDatabase fontdb;
924 QStringList families(fontdb.families());
925 for (auto const & family : families) {
926 screenRomanCO->addItem(family);
927 screenSansCO->addItem(family);
928 screenTypewriterCO->addItem(family);
930 connect(screenRomanCO, SIGNAL(activated(QString)),
931 this, SIGNAL(changed()));
932 connect(screenSansCO, SIGNAL(activated(QString)),
933 this, SIGNAL(changed()));
934 connect(screenTypewriterCO, SIGNAL(activated(QString)),
935 this, SIGNAL(changed()));
936 connect(screenZoomSB, SIGNAL(valueChanged(int)),
937 this, SIGNAL(changed()));
938 connect(screenTinyED, SIGNAL(textChanged(QString)),
939 this, SIGNAL(changed()));
940 connect(screenSmallestED, SIGNAL(textChanged(QString)),
941 this, SIGNAL(changed()));
942 connect(screenSmallerED, SIGNAL(textChanged(QString)),
943 this, SIGNAL(changed()));
944 connect(screenSmallED, SIGNAL(textChanged(QString)),
945 this, SIGNAL(changed()));
946 connect(screenNormalED, SIGNAL(textChanged(QString)),
947 this, SIGNAL(changed()));
948 connect(screenLargeED, SIGNAL(textChanged(QString)),
949 this, SIGNAL(changed()));
950 connect(screenLargerED, SIGNAL(textChanged(QString)),
951 this, SIGNAL(changed()));
952 connect(screenLargestED, SIGNAL(textChanged(QString)),
953 this, SIGNAL(changed()));
954 connect(screenHugeED, SIGNAL(textChanged(QString)),
955 this, SIGNAL(changed()));
956 connect(screenHugerED, SIGNAL(textChanged(QString)),
957 this, SIGNAL(changed()));
959 screenTinyED->setValidator(new QDoubleValidator(screenTinyED));
960 screenSmallestED->setValidator(new QDoubleValidator(screenSmallestED));
961 screenSmallerED->setValidator(new QDoubleValidator(screenSmallerED));
962 screenSmallED->setValidator(new QDoubleValidator(screenSmallED));
963 screenNormalED->setValidator(new QDoubleValidator(screenNormalED));
964 screenLargeED->setValidator(new QDoubleValidator(screenLargeED));
965 screenLargerED->setValidator(new QDoubleValidator(screenLargerED));
966 screenLargestED->setValidator(new QDoubleValidator(screenLargestED));
967 screenHugeED->setValidator(new QDoubleValidator(screenHugeED));
968 screenHugerED->setValidator(new QDoubleValidator(screenHugerED));
972 void PrefScreenFonts::applyRC(LyXRC & rc) const
974 LyXRC const oldrc = rc;
976 parseFontName(screenRomanCO->currentText(),
977 rc.roman_font_name, rc.roman_font_foundry);
978 parseFontName(screenSansCO->currentText(),
979 rc.sans_font_name, rc.sans_font_foundry);
980 parseFontName(screenTypewriterCO->currentText(),
981 rc.typewriter_font_name, rc.typewriter_font_foundry);
983 rc.defaultZoom = screenZoomSB->value();
984 rc.font_sizes[TINY_SIZE] = widgetToDoubleStr(screenTinyED);
985 rc.font_sizes[SCRIPT_SIZE] = widgetToDoubleStr(screenSmallestED);
986 rc.font_sizes[FOOTNOTE_SIZE] = widgetToDoubleStr(screenSmallerED);
987 rc.font_sizes[SMALL_SIZE] = widgetToDoubleStr(screenSmallED);
988 rc.font_sizes[NORMAL_SIZE] = widgetToDoubleStr(screenNormalED);
989 rc.font_sizes[LARGE_SIZE] = widgetToDoubleStr(screenLargeED);
990 rc.font_sizes[LARGER_SIZE] = widgetToDoubleStr(screenLargerED);
991 rc.font_sizes[LARGEST_SIZE] = widgetToDoubleStr(screenLargestED);
992 rc.font_sizes[HUGE_SIZE] = widgetToDoubleStr(screenHugeED);
993 rc.font_sizes[HUGER_SIZE] = widgetToDoubleStr(screenHugerED);
997 void PrefScreenFonts::updateRC(LyXRC const & rc)
999 setComboxFont(screenRomanCO, rc.roman_font_name,
1000 rc.roman_font_foundry);
1001 setComboxFont(screenSansCO, rc.sans_font_name,
1002 rc.sans_font_foundry);
1003 setComboxFont(screenTypewriterCO, rc.typewriter_font_name,
1004 rc.typewriter_font_foundry);
1006 selectRoman(screenRomanCO->currentText());
1007 selectSans(screenSansCO->currentText());
1008 selectTypewriter(screenTypewriterCO->currentText());
1010 screenZoomSB->setValue(rc.defaultZoom);
1011 updateScreenFontSizes(rc);
1015 void PrefScreenFonts::updateScreenFontSizes(LyXRC const & rc)
1017 doubleToWidget(screenTinyED, rc.font_sizes[TINY_SIZE]);
1018 doubleToWidget(screenSmallestED, rc.font_sizes[SCRIPT_SIZE]);
1019 doubleToWidget(screenSmallerED, rc.font_sizes[FOOTNOTE_SIZE]);
1020 doubleToWidget(screenSmallED, rc.font_sizes[SMALL_SIZE]);
1021 doubleToWidget(screenNormalED, rc.font_sizes[NORMAL_SIZE]);
1022 doubleToWidget(screenLargeED, rc.font_sizes[LARGE_SIZE]);
1023 doubleToWidget(screenLargerED, rc.font_sizes[LARGER_SIZE]);
1024 doubleToWidget(screenLargestED, rc.font_sizes[LARGEST_SIZE]);
1025 doubleToWidget(screenHugeED, rc.font_sizes[HUGE_SIZE]);
1026 doubleToWidget(screenHugerED, rc.font_sizes[HUGER_SIZE]);
1030 void PrefScreenFonts::selectRoman(const QString & name)
1032 screenRomanFE->set(QFont(name), name);
1036 void PrefScreenFonts::selectSans(const QString & name)
1038 screenSansFE->set(QFont(name), name);
1042 void PrefScreenFonts::selectTypewriter(const QString & name)
1044 screenTypewriterFE->set(QFont(name), name);
1048 /////////////////////////////////////////////////////////////////////
1052 /////////////////////////////////////////////////////////////////////
1055 PrefColors::PrefColors(GuiPreferences * form)
1056 : PrefModule(catLookAndFeel, N_("Colors"), form)
1060 // FIXME: all of this initialization should be put into the controller.
1061 // See http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg113301.html
1062 // for some discussion of why that is not trivial.
1063 QPixmap icon(32, 32);
1064 for (int i = 0; i < Color_ignore; ++i) {
1065 ColorCode lc = static_cast<ColorCode>(i);
1066 if (lc == Color_none
1067 || lc == Color_black
1068 || lc == Color_white
1070 || lc == Color_brown
1072 || lc == Color_darkgray
1074 || lc == Color_green
1075 || lc == Color_lightgray
1077 || lc == Color_magenta
1078 || lc == Color_olive
1079 || lc == Color_orange
1081 || lc == Color_purple
1084 || lc == Color_violet
1085 || lc == Color_yellow
1086 || lc == Color_inherit
1087 || lc == Color_ignore)
1089 lcolors_.push_back(lc);
1091 sort(lcolors_.begin(), lcolors_.end(), ColorSorter);
1092 vector<ColorCode>::const_iterator cit = lcolors_.begin();
1093 vector<ColorCode>::const_iterator const end = lcolors_.end();
1094 for (; cit != end; ++cit) {
1095 (void) new QListWidgetItem(QIcon(icon),
1096 toqstr(lcolor.getGUIName(*cit)), lyxObjectsLW);
1098 curcolors_.resize(lcolors_.size());
1099 newcolors_.resize(lcolors_.size());
1100 // End initialization
1102 connect(colorChangePB, SIGNAL(clicked()),
1103 this, SLOT(changeColor()));
1104 connect(colorResetPB, SIGNAL(clicked()),
1105 this, SLOT(resetColor()));
1106 connect(colorResetAllPB, SIGNAL(clicked()),
1107 this, SLOT(resetAllColor()));
1108 connect(lyxObjectsLW, SIGNAL(itemSelectionChanged()),
1109 this, SLOT(changeLyxObjectsSelection()));
1110 connect(lyxObjectsLW, SIGNAL(itemActivated(QListWidgetItem*)),
1111 this, SLOT(changeColor()));
1112 connect(syscolorsCB, SIGNAL(toggled(bool)),
1113 this, SIGNAL(changed()));
1114 connect(syscolorsCB, SIGNAL(toggled(bool)),
1115 this, SLOT(changeSysColor()));
1119 void PrefColors::applyRC(LyXRC & rc) const
1123 for (unsigned int i = 0; i < lcolors_.size(); ++i)
1124 if (curcolors_[i] != newcolors_[i])
1125 form_->setColor(lcolors_[i], newcolors_[i]);
1126 rc.use_system_colors = syscolorsCB->isChecked();
1128 if (oldrc.use_system_colors != rc.use_system_colors)
1129 guiApp->colorCache().clear();
1133 void PrefColors::updateRC(LyXRC const & rc)
1135 for (size_type i = 0; i < lcolors_.size(); ++i) {
1136 QColor color = QColor(guiApp->colorCache().get(lcolors_[i], false));
1137 QPixmap coloritem(32, 32);
1138 coloritem.fill(color);
1139 lyxObjectsLW->item(int(i))->setIcon(QIcon(coloritem));
1140 newcolors_[i] = curcolors_[i] = color.name();
1142 syscolorsCB->setChecked(rc.use_system_colors);
1143 changeLyxObjectsSelection();
1145 setDisabledResets();
1149 void PrefColors::changeColor()
1151 int const row = lyxObjectsLW->currentRow();
1157 QString const color = newcolors_[size_t(row)];
1158 QColor const c = QColorDialog::getColor(QColor(color), qApp->focusWidget());
1160 if (setColor(row, c, color)) {
1161 setDisabledResets();
1168 void PrefColors::resetColor()
1170 int const row = lyxObjectsLW->currentRow();
1176 QString const color = newcolors_[size_t(row)];
1177 QColor const c = getDefaultColorByRow(row);
1179 if (setColor(row, c, color)) {
1180 setDisabledResets();
1187 void PrefColors::resetAllColor()
1189 bool isChanged = false;
1191 colorResetAllPB->setDisabled(true);
1193 for (int irow = 0, count = lyxObjectsLW->count(); irow < count; ++irow) {
1194 QString const color = newcolors_[size_t(irow)];
1195 QColor const c = getDefaultColorByRow(irow);
1197 if (setColor(irow, c, color))
1202 setDisabledResets();
1209 bool PrefColors::setColor(int const row, QColor const & new_color,
1210 QString const & old_color)
1212 if (new_color.isValid() && new_color.name() != old_color) {
1213 newcolors_[size_t(row)] = new_color.name();
1214 QPixmap coloritem(32, 32);
1215 coloritem.fill(new_color);
1216 lyxObjectsLW->item(row)->setIcon(QIcon(coloritem));
1223 void PrefColors::setDisabledResets()
1225 int const row = lyxObjectsLW->currentRow();
1226 // set disable reset buttons ...
1228 colorResetPB->setDisabled(isDefaultColor(row, newcolors_[size_t(row)]));
1230 colorResetAllPB->setDisabled(true);
1232 // ... in between process qt events to give quicker visual feedback to the user ...
1233 guiApp->processEvents();
1235 // ... set disable Reset All button
1236 for (int irow = 0, count = lyxObjectsLW->count(); irow < count; ++irow) {
1237 if (!isDefaultColor(irow, newcolors_[size_t(irow)])) {
1238 colorResetAllPB->setDisabled(false);
1239 // the break condition might hide performance issues
1240 // if a non-default color is at the top of the list
1247 bool PrefColors::isDefaultColor(int const row, QString const & color)
1249 return color == getDefaultColorByRow(row).name();
1253 QColor PrefColors::getDefaultColorByRow(int const row)
1255 ColorSet const defaultcolor;
1256 return defaultcolor.getX11HexName(lcolors_[size_t(row)]).c_str();
1260 void PrefColors::changeSysColor()
1262 for (int row = 0 ; row < lyxObjectsLW->count() ; ++row) {
1263 // skip colors that are taken from system palette
1264 bool const disable = syscolorsCB->isChecked()
1265 && guiApp->colorCache().isSystem(lcolors_[size_t(row)]);
1267 QListWidgetItem * const item = lyxObjectsLW->item(row);
1268 Qt::ItemFlags const flags = item->flags();
1271 item->setFlags(flags & ~Qt::ItemIsEnabled);
1273 item->setFlags(flags | Qt::ItemIsEnabled);
1278 void PrefColors::changeLyxObjectsSelection()
1280 int currentRow = lyxObjectsLW->currentRow();
1281 colorChangePB->setDisabled(currentRow < 0);
1284 colorResetPB->setDisabled(true);
1286 colorResetPB->setDisabled(
1287 isDefaultColor(currentRow, newcolors_[size_t(currentRow)]));
1291 /////////////////////////////////////////////////////////////////////
1295 /////////////////////////////////////////////////////////////////////
1297 PrefDisplay::PrefDisplay(GuiPreferences * form)
1298 : PrefModule(catLookAndFeel, N_("Display"), form)
1301 connect(displayGraphicsCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1302 connect(instantPreviewCO, SIGNAL(activated(int)), this, SIGNAL(changed()));
1303 connect(previewSizeSB, SIGNAL(valueChanged(double)), this, SIGNAL(changed()));
1304 connect(paragraphMarkerCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1305 connect(ctAdditionsUnderlinedCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1309 void PrefDisplay::on_instantPreviewCO_currentIndexChanged(int index)
1311 previewSizeSB->setEnabled(index != 0);
1315 void PrefDisplay::applyRC(LyXRC & rc) const
1317 switch (instantPreviewCO->currentIndex()) {
1319 rc.preview = LyXRC::PREVIEW_OFF;
1322 rc.preview = LyXRC::PREVIEW_NO_MATH;
1325 rc.preview = LyXRC::PREVIEW_ON;
1329 rc.display_graphics = displayGraphicsCB->isChecked();
1330 rc.preview_scale_factor = previewSizeSB->value();
1331 rc.paragraph_markers = paragraphMarkerCB->isChecked();
1332 rc.ct_additions_underlined = ctAdditionsUnderlinedCB->isChecked();
1334 // FIXME!! The graphics cache no longer has a changeDisplay method.
1336 if (old_value != rc.display_graphics) {
1337 graphics::GCache & gc = graphics::GCache::get();
1344 void PrefDisplay::updateRC(LyXRC const & rc)
1346 switch (rc.preview) {
1347 case LyXRC::PREVIEW_OFF:
1348 instantPreviewCO->setCurrentIndex(0);
1350 case LyXRC::PREVIEW_NO_MATH :
1351 instantPreviewCO->setCurrentIndex(1);
1353 case LyXRC::PREVIEW_ON :
1354 instantPreviewCO->setCurrentIndex(2);
1358 displayGraphicsCB->setChecked(rc.display_graphics);
1359 previewSizeSB->setValue(rc.preview_scale_factor);
1360 paragraphMarkerCB->setChecked(rc.paragraph_markers);
1361 ctAdditionsUnderlinedCB->setChecked(rc.ct_additions_underlined);
1362 previewSizeSB->setEnabled(
1364 && rc.preview != LyXRC::PREVIEW_OFF);
1368 /////////////////////////////////////////////////////////////////////
1372 /////////////////////////////////////////////////////////////////////
1374 PrefPaths::PrefPaths(GuiPreferences * form)
1375 : PrefModule(QString(), N_("Paths"), form)
1379 connect(workingDirPB, SIGNAL(clicked()), this, SLOT(selectWorkingdir()));
1380 connect(workingDirED, SIGNAL(textChanged(QString)),
1381 this, SIGNAL(changed()));
1383 connect(templateDirPB, SIGNAL(clicked()), this, SLOT(selectTemplatedir()));
1384 connect(templateDirED, SIGNAL(textChanged(QString)),
1385 this, SIGNAL(changed()));
1387 connect(exampleDirPB, SIGNAL(clicked()), this, SLOT(selectExampledir()));
1388 connect(exampleDirED, SIGNAL(textChanged(QString)),
1389 this, SIGNAL(changed()));
1391 connect(backupDirPB, SIGNAL(clicked()), this, SLOT(selectBackupdir()));
1392 connect(backupDirED, SIGNAL(textChanged(QString)),
1393 this, SIGNAL(changed()));
1395 connect(lyxserverDirPB, SIGNAL(clicked()), this, SLOT(selectLyxPipe()));
1396 connect(lyxserverDirED, SIGNAL(textChanged(QString)),
1397 this, SIGNAL(changed()));
1399 connect(thesaurusDirPB, SIGNAL(clicked()), this, SLOT(selectThesaurusdir()));
1400 connect(thesaurusDirED, SIGNAL(textChanged(QString)),
1401 this, SIGNAL(changed()));
1403 connect(tempDirPB, SIGNAL(clicked()), this, SLOT(selectTempdir()));
1404 connect(tempDirED, SIGNAL(textChanged(QString)),
1405 this, SIGNAL(changed()));
1407 #if defined(USE_HUNSPELL)
1408 connect(hunspellDirPB, SIGNAL(clicked()), this, SLOT(selectHunspelldir()));
1409 connect(hunspellDirED, SIGNAL(textChanged(QString)),
1410 this, SIGNAL(changed()));
1412 hunspellDirPB->setEnabled(false);
1413 hunspellDirED->setEnabled(false);
1416 connect(pathPrefixED, SIGNAL(textChanged(QString)),
1417 this, SIGNAL(changed()));
1419 connect(texinputsPrefixED, SIGNAL(textChanged(QString)),
1420 this, SIGNAL(changed()));
1422 pathPrefixED->setValidator(new NoNewLineValidator(pathPrefixED));
1423 texinputsPrefixED->setValidator(new NoNewLineValidator(texinputsPrefixED));
1427 void PrefPaths::applyRC(LyXRC & rc) const
1429 rc.document_path = internal_path(fromqstr(workingDirED->text()));
1430 rc.example_path = internal_path(fromqstr(exampleDirED->text()));
1431 rc.template_path = internal_path(fromqstr(templateDirED->text()));
1432 rc.backupdir_path = internal_path(fromqstr(backupDirED->text()));
1433 rc.tempdir_path = internal_path(fromqstr(tempDirED->text()));
1434 rc.thesaurusdir_path = internal_path(fromqstr(thesaurusDirED->text()));
1435 rc.hunspelldir_path = internal_path(fromqstr(hunspellDirED->text()));
1436 rc.path_prefix = internal_path_list(fromqstr(pathPrefixED->text()));
1437 rc.texinputs_prefix = internal_path_list(fromqstr(texinputsPrefixED->text()));
1438 // FIXME: should be a checkbox only
1439 rc.lyxpipes = internal_path(fromqstr(lyxserverDirED->text()));
1443 void PrefPaths::updateRC(LyXRC const & rc)
1445 workingDirED->setText(toqstr(external_path(rc.document_path)));
1446 exampleDirED->setText(toqstr(external_path(rc.example_path)));
1447 templateDirED->setText(toqstr(external_path(rc.template_path)));
1448 backupDirED->setText(toqstr(external_path(rc.backupdir_path)));
1449 tempDirED->setText(toqstr(external_path(rc.tempdir_path)));
1450 thesaurusDirED->setText(toqstr(external_path(rc.thesaurusdir_path)));
1451 hunspellDirED->setText(toqstr(external_path(rc.hunspelldir_path)));
1452 pathPrefixED->setText(toqstr(external_path_list(rc.path_prefix)));
1453 texinputsPrefixED->setText(toqstr(external_path_list(rc.texinputs_prefix)));
1454 // FIXME: should be a checkbox only
1455 lyxserverDirED->setText(toqstr(external_path(rc.lyxpipes)));
1459 void PrefPaths::selectExampledir()
1461 QString file = browseDir(internalPath(exampleDirED->text()),
1462 qt_("Select directory for example files"));
1463 if (!file.isEmpty())
1464 exampleDirED->setText(file);
1468 void PrefPaths::selectTemplatedir()
1470 QString file = browseDir(internalPath(templateDirED->text()),
1471 qt_("Select a document templates directory"));
1472 if (!file.isEmpty())
1473 templateDirED->setText(file);
1477 void PrefPaths::selectTempdir()
1479 QString file = browseDir(internalPath(tempDirED->text()),
1480 qt_("Select a temporary directory"));
1481 if (!file.isEmpty())
1482 tempDirED->setText(file);
1486 void PrefPaths::selectBackupdir()
1488 QString file = browseDir(internalPath(backupDirED->text()),
1489 qt_("Select a backups directory"));
1490 if (!file.isEmpty())
1491 backupDirED->setText(file);
1495 void PrefPaths::selectWorkingdir()
1497 QString file = browseDir(internalPath(workingDirED->text()),
1498 qt_("Select a document directory"));
1499 if (!file.isEmpty())
1500 workingDirED->setText(file);
1504 void PrefPaths::selectThesaurusdir()
1506 QString file = browseDir(internalPath(thesaurusDirED->text()),
1507 qt_("Set the path to the thesaurus dictionaries"));
1508 if (!file.isEmpty())
1509 thesaurusDirED->setText(file);
1513 void PrefPaths::selectHunspelldir()
1515 QString file = browseDir(internalPath(hunspellDirED->text()),
1516 qt_("Set the path to the Hunspell dictionaries"));
1517 if (!file.isEmpty())
1518 hunspellDirED->setText(file);
1522 void PrefPaths::selectLyxPipe()
1524 QString file = form_->browse(internalPath(lyxserverDirED->text()),
1525 qt_("Give a filename for the LyX server pipe"));
1526 if (!file.isEmpty())
1527 lyxserverDirED->setText(file);
1531 /////////////////////////////////////////////////////////////////////
1535 /////////////////////////////////////////////////////////////////////
1537 PrefSpellchecker::PrefSpellchecker(GuiPreferences * form)
1538 : PrefModule(catLanguage, N_("Spellchecker"), form)
1542 // FIXME: this check should test the target platform (darwin)
1543 #if defined(USE_MACOSX_PACKAGING)
1544 spellcheckerCB->addItem(qt_("Native"), QString("native"));
1545 #define CONNECT_APPLESPELL
1547 #undef CONNECT_APPLESPELL
1549 #if defined(USE_ASPELL)
1550 spellcheckerCB->addItem(qt_("Aspell"), QString("aspell"));
1552 #if defined(USE_ENCHANT)
1553 spellcheckerCB->addItem(qt_("Enchant"), QString("enchant"));
1555 #if defined(USE_HUNSPELL)
1556 spellcheckerCB->addItem(qt_("Hunspell"), QString("hunspell"));
1559 #if defined(CONNECT_APPLESPELL) || defined(USE_ASPELL) || defined(USE_ENCHANT) || defined(USE_HUNSPELL)
1560 connect(spellcheckerCB, SIGNAL(currentIndexChanged(int)),
1561 this, SIGNAL(changed()));
1562 connect(altLanguageED, SIGNAL(textChanged(QString)),
1563 this, SIGNAL(changed()));
1564 connect(escapeCharactersED, SIGNAL(textChanged(QString)),
1565 this, SIGNAL(changed()));
1566 connect(compoundWordCB, SIGNAL(clicked()),
1567 this, SIGNAL(changed()));
1568 connect(spellcheckContinuouslyCB, SIGNAL(clicked()),
1569 this, SIGNAL(changed()));
1570 connect(spellcheckNotesCB, SIGNAL(clicked()),
1571 this, SIGNAL(changed()));
1573 altLanguageED->setValidator(new NoNewLineValidator(altLanguageED));
1574 escapeCharactersED->setValidator(new NoNewLineValidator(escapeCharactersED));
1576 spellcheckerCB->setEnabled(false);
1577 altLanguageED->setEnabled(false);
1578 escapeCharactersED->setEnabled(false);
1579 compoundWordCB->setEnabled(false);
1580 spellcheckContinuouslyCB->setEnabled(false);
1581 spellcheckNotesCB->setEnabled(false);
1586 void PrefSpellchecker::applyRC(LyXRC & rc) const
1588 string const speller = fromqstr(spellcheckerCB->
1589 itemData(spellcheckerCB->currentIndex()).toString());
1590 if (!speller.empty())
1591 rc.spellchecker = speller;
1592 rc.spellchecker_alt_lang = fromqstr(altLanguageED->text());
1593 rc.spellchecker_esc_chars = fromqstr(escapeCharactersED->text());
1594 rc.spellchecker_accept_compound = compoundWordCB->isChecked();
1595 rc.spellcheck_continuously = spellcheckContinuouslyCB->isChecked();
1596 rc.spellcheck_notes = spellcheckNotesCB->isChecked();
1600 void PrefSpellchecker::updateRC(LyXRC const & rc)
1602 spellcheckerCB->setCurrentIndex(
1603 spellcheckerCB->findData(toqstr(rc.spellchecker)));
1604 altLanguageED->setText(toqstr(rc.spellchecker_alt_lang));
1605 escapeCharactersED->setText(toqstr(rc.spellchecker_esc_chars));
1606 compoundWordCB->setChecked(rc.spellchecker_accept_compound);
1607 spellcheckContinuouslyCB->setChecked(rc.spellcheck_continuously);
1608 spellcheckNotesCB->setChecked(rc.spellcheck_notes);
1612 void PrefSpellchecker::on_spellcheckerCB_currentIndexChanged(int index)
1614 QString spellchecker = spellcheckerCB->itemData(index).toString();
1616 compoundWordCB->setEnabled(spellchecker == QString("aspell"));
1621 /////////////////////////////////////////////////////////////////////
1625 /////////////////////////////////////////////////////////////////////
1628 PrefConverters::PrefConverters(GuiPreferences * form)
1629 : PrefModule(catFiles, N_("Converters"), form)
1633 connect(converterNewPB, SIGNAL(clicked()),
1634 this, SLOT(updateConverter()));
1635 connect(converterRemovePB, SIGNAL(clicked()),
1636 this, SLOT(removeConverter()));
1637 connect(converterModifyPB, SIGNAL(clicked()),
1638 this, SLOT(updateConverter()));
1639 connect(convertersLW, SIGNAL(currentRowChanged(int)),
1640 this, SLOT(switchConverter()));
1641 connect(converterFromCO, SIGNAL(activated(QString)),
1642 this, SLOT(changeConverter()));
1643 connect(converterToCO, SIGNAL(activated(QString)),
1644 this, SLOT(changeConverter()));
1645 connect(converterED, SIGNAL(textEdited(QString)),
1646 this, SLOT(changeConverter()));
1647 connect(converterFlagED, SIGNAL(textEdited(QString)),
1648 this, SLOT(changeConverter()));
1649 connect(converterNewPB, SIGNAL(clicked()),
1650 this, SIGNAL(changed()));
1651 connect(converterRemovePB, SIGNAL(clicked()),
1652 this, SIGNAL(changed()));
1653 connect(converterModifyPB, SIGNAL(clicked()),
1654 this, SIGNAL(changed()));
1655 connect(maxAgeLE, SIGNAL(textEdited(QString)),
1656 this, SIGNAL(changed()));
1657 connect(needauthForbiddenCB, SIGNAL(toggled(bool)),
1658 this, SIGNAL(changed()));
1660 converterED->setValidator(new NoNewLineValidator(converterED));
1661 converterFlagED->setValidator(new NoNewLineValidator(converterFlagED));
1662 maxAgeLE->setValidator(new QDoubleValidator(0, HUGE_VAL, 6, maxAgeLE));
1663 //converterDefGB->setFocusProxy(convertersLW);
1667 void PrefConverters::applyRC(LyXRC & rc) const
1669 rc.use_converter_cache = cacheCB->isChecked();
1670 rc.use_converter_needauth_forbidden = needauthForbiddenCB->isChecked();
1671 rc.use_converter_needauth = needauthCB->isChecked();
1672 rc.converter_cache_maxage = int(widgetToDouble(maxAgeLE) * 86400.0);
1676 static void setCheckboxBlockSignals(QCheckBox *cb, bool checked) {
1677 cb->blockSignals(true);
1678 cb->setChecked(checked);
1679 cb->blockSignals(false);
1683 void PrefConverters::updateRC(LyXRC const & rc)
1685 cacheCB->setChecked(rc.use_converter_cache);
1686 needauthForbiddenCB->setChecked(rc.use_converter_needauth_forbidden);
1687 setCheckboxBlockSignals(needauthCB, rc.use_converter_needauth);
1689 doubleToWidget(maxAgeLE, (double(rc.converter_cache_maxage) / 86400.0), 'g', 6);
1694 void PrefConverters::updateGui()
1696 QString const pattern("%1 -> %2");
1697 form_->formats().sort();
1698 form_->converters().update(form_->formats());
1699 // save current selection
1702 .arg(converterFromCO->currentText())
1703 .arg(converterToCO->currentText());
1705 converterFromCO->clear();
1706 converterToCO->clear();
1708 for (Format const & f : form_->formats()) {
1709 QString const name = toqstr(translateIfPossible(f.prettyname()));
1710 converterFromCO->addItem(name);
1711 converterToCO->addItem(name);
1714 // currentRowChanged(int) is also triggered when updating the listwidget
1715 // block signals to avoid unnecessary calls to switchConverter()
1716 convertersLW->blockSignals(true);
1717 convertersLW->clear();
1719 for (Converter const & c : form_->converters()) {
1720 QString const name =
1722 .arg(toqstr(translateIfPossible(c.From()->prettyname())))
1723 .arg(toqstr(translateIfPossible(c.To()->prettyname())));
1724 int type = form_->converters().getNumber(c.From()->name(),
1726 new QListWidgetItem(name, convertersLW, type);
1728 convertersLW->sortItems(Qt::AscendingOrder);
1729 convertersLW->blockSignals(false);
1731 // restore selection
1732 if (current != pattern.arg(QString()).arg(QString())) {
1733 QList<QListWidgetItem *> const item =
1734 convertersLW->findItems(current, Qt::MatchExactly);
1735 if (!item.isEmpty())
1736 convertersLW->setCurrentItem(item.at(0));
1739 // select first element if restoring failed
1740 if (convertersLW->currentRow() == -1)
1741 convertersLW->setCurrentRow(0);
1747 void PrefConverters::switchConverter()
1749 int const cnr = convertersLW->currentItem()->type();
1750 Converter const & c(form_->converters().get(cnr));
1751 converterFromCO->setCurrentIndex(form_->formats().getNumber(c.from()));
1752 converterToCO->setCurrentIndex(form_->formats().getNumber(c.to()));
1753 converterED->setText(toqstr(c.command()));
1754 converterFlagED->setText(toqstr(c.flags()));
1760 void PrefConverters::changeConverter()
1766 void PrefConverters::updateButtons()
1768 if (form_->formats().empty())
1770 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1771 Format const & to = form_->formats().get(converterToCO->currentIndex());
1772 int const sel = form_->converters().getNumber(from.name(), to.name());
1773 bool const known = sel >= 0;
1774 bool const valid = !(converterED->text().isEmpty()
1775 || from.name() == to.name());
1780 if (convertersLW->count() > 0) {
1781 int const cnr = convertersLW->currentItem()->type();
1782 Converter const & c = form_->converters().get(cnr);
1783 old_command = c.command();
1784 old_flag = c.flags();
1787 string const new_command = fromqstr(converterED->text());
1788 string const new_flag = fromqstr(converterFlagED->text());
1790 bool modified = (old_command != new_command || old_flag != new_flag);
1792 converterModifyPB->setEnabled(valid && known && modified);
1793 converterNewPB->setEnabled(valid && !known);
1794 converterRemovePB->setEnabled(known);
1796 maxAgeLE->setEnabled(cacheCB->isChecked());
1797 maxAgeLA->setEnabled(cacheCB->isChecked());
1802 // specify unique from/to or it doesn't appear. This is really bad UI
1803 // this is why we can use the same function for both new and modify
1804 void PrefConverters::updateConverter()
1806 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1807 Format const & to = form_->formats().get(converterToCO->currentIndex());
1808 string const flags = fromqstr(converterFlagED->text());
1809 string const command = fromqstr(converterED->text());
1811 Converter const * old =
1812 form_->converters().getConverter(from.name(), to.name());
1813 form_->converters().add(from.name(), to.name(), command, flags);
1816 form_->converters().updateLast(form_->formats());
1820 // Remove all files created by this converter from the cache, since
1821 // the modified converter might create different files.
1822 ConverterCache::get().remove_all(from.name(), to.name());
1826 void PrefConverters::removeConverter()
1828 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1829 Format const & to = form_->formats().get(converterToCO->currentIndex());
1830 form_->converters().erase(from.name(), to.name());
1834 // Remove all files created by this converter from the cache, since
1835 // a possible new converter might create different files.
1836 ConverterCache::get().remove_all(from.name(), to.name());
1840 void PrefConverters::on_cacheCB_stateChanged(int state)
1842 maxAgeLE->setEnabled(state == Qt::Checked);
1843 maxAgeLA->setEnabled(state == Qt::Checked);
1848 void PrefConverters::on_needauthForbiddenCB_toggled(bool checked)
1850 needauthCB->setEnabled(!checked);
1854 void PrefConverters::on_needauthCB_toggled(bool checked)
1861 int ret = frontend::Alert::prompt(
1862 _("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!"),
1863 0, 0, _("&No"), _("&Yes"));
1867 setCheckboxBlockSignals(needauthCB, true);
1871 /////////////////////////////////////////////////////////////////////
1875 /////////////////////////////////////////////////////////////////////
1877 class FormatValidator : public QValidator
1880 FormatValidator(QWidget *, Formats const & f);
1881 void fixup(QString & input) const override;
1882 QValidator::State validate(QString & input, int & pos) const override;
1884 virtual QString toString(Format const & format) const = 0;
1886 Formats const & formats_;
1890 FormatValidator::FormatValidator(QWidget * parent, Formats const & f)
1891 : QValidator(parent), formats_(f)
1896 void FormatValidator::fixup(QString & input) const
1898 Formats::const_iterator cit = formats_.begin();
1899 Formats::const_iterator end = formats_.end();
1900 for (; cit != end; ++cit) {
1901 QString const name = toString(*cit);
1902 if (distance(formats_.begin(), cit) == nr()) {
1910 QValidator::State FormatValidator::validate(QString & input, int & /*pos*/) const
1912 Formats::const_iterator cit = formats_.begin();
1913 Formats::const_iterator end = formats_.end();
1914 bool unknown = true;
1915 for (; unknown && cit != end; ++cit) {
1916 QString const name = toString(*cit);
1917 if (distance(formats_.begin(), cit) != nr())
1918 unknown = name != input;
1921 if (unknown && !input.isEmpty())
1922 return QValidator::Acceptable;
1924 return QValidator::Intermediate;
1928 int FormatValidator::nr() const
1930 QComboBox * p = qobject_cast<QComboBox *>(parent());
1931 return p->itemData(p->currentIndex()).toInt();
1935 /////////////////////////////////////////////////////////////////////
1937 // FormatNameValidator
1939 /////////////////////////////////////////////////////////////////////
1941 class FormatNameValidator : public FormatValidator
1944 FormatNameValidator(QWidget * parent, Formats const & f)
1945 : FormatValidator(parent, f)
1948 QString toString(Format const & format) const override
1950 return toqstr(format.name());
1955 /////////////////////////////////////////////////////////////////////
1957 // FormatPrettynameValidator
1959 /////////////////////////////////////////////////////////////////////
1961 class FormatPrettynameValidator : public FormatValidator
1964 FormatPrettynameValidator(QWidget * parent, Formats const & f)
1965 : FormatValidator(parent, f)
1968 QString toString(Format const & format) const override
1970 return toqstr(translateIfPossible(format.prettyname()));
1975 /////////////////////////////////////////////////////////////////////
1979 /////////////////////////////////////////////////////////////////////
1981 PrefFileformats::PrefFileformats(GuiPreferences * form)
1982 : PrefModule(catFiles, N_("File Formats"), form)
1986 formatED->setValidator(new FormatNameValidator(formatsCB, form_->formats()));
1987 formatsCB->setValidator(new FormatPrettynameValidator(formatsCB, form_->formats()));
1988 extensionsED->setValidator(new NoNewLineValidator(extensionsED));
1989 shortcutED->setValidator(new NoNewLineValidator(shortcutED));
1990 editorED->setValidator(new NoNewLineValidator(editorED));
1991 viewerED->setValidator(new NoNewLineValidator(viewerED));
1992 copierED->setValidator(new NoNewLineValidator(copierED));
1994 connect(documentCB, SIGNAL(clicked()),
1995 this, SLOT(setFlags()));
1996 connect(vectorCB, SIGNAL(clicked()),
1997 this, SLOT(setFlags()));
1998 connect(exportMenuCB, SIGNAL(clicked()),
1999 this, SLOT(setFlags()));
2000 connect(formatsCB->lineEdit(), SIGNAL(editingFinished()),
2001 this, SLOT(updatePrettyname()));
2002 connect(formatsCB->lineEdit(), SIGNAL(textEdited(QString)),
2003 this, SIGNAL(changed()));
2004 connect(defaultFormatCB, SIGNAL(activated(QString)),
2005 this, SIGNAL(changed()));
2006 connect(defaultOTFFormatCB, SIGNAL(activated(QString)),
2007 this, SIGNAL(changed()));
2008 connect(defaultPlatexFormatCB, SIGNAL(activated(QString)),
2009 this, SIGNAL(changed()));
2010 connect(viewerCO, SIGNAL(activated(int)),
2011 this, SIGNAL(changed()));
2012 connect(editorCO, SIGNAL(activated(int)),
2013 this, SIGNAL(changed()));
2019 string const l10n_shortcut(docstring const & prettyname, string const & shortcut)
2021 if (shortcut.empty())
2024 string l10n_format =
2025 to_utf8(_(to_utf8(prettyname) + '|' + shortcut));
2026 return split(l10n_format, '|');
2032 void PrefFileformats::applyRC(LyXRC & rc) const
2034 QString const default_format = defaultFormatCB->itemData(
2035 defaultFormatCB->currentIndex()).toString();
2036 rc.default_view_format = fromqstr(default_format);
2037 QString const default_otf_format = defaultOTFFormatCB->itemData(
2038 defaultOTFFormatCB->currentIndex()).toString();
2039 rc.default_otf_view_format = fromqstr(default_otf_format);
2040 QString const default_platex_format = defaultPlatexFormatCB->itemData(
2041 defaultPlatexFormatCB->currentIndex()).toString();
2042 rc.default_platex_view_format = fromqstr(default_platex_format);
2046 void PrefFileformats::updateRC(LyXRC const & rc)
2048 viewer_alternatives = rc.viewer_alternatives;
2049 editor_alternatives = rc.editor_alternatives;
2050 bool const init = defaultFormatCB->currentText().isEmpty();
2054 defaultFormatCB->findData(toqstr(rc.default_view_format));
2055 defaultFormatCB->setCurrentIndex(pos);
2056 pos = defaultOTFFormatCB->findData(toqstr(rc.default_otf_view_format));
2057 defaultOTFFormatCB->setCurrentIndex(pos);
2058 defaultOTFFormatCB->setCurrentIndex(pos);
2059 pos = defaultPlatexFormatCB->findData(toqstr(rc.default_platex_view_format));
2060 defaultPlatexFormatCB->setCurrentIndex(pos);
2061 defaultPlatexFormatCB->setCurrentIndex(pos);
2066 void PrefFileformats::updateView()
2068 QString const current = formatsCB->currentText();
2069 QString const current_def = defaultFormatCB->currentText();
2070 QString const current_def_otf = defaultOTFFormatCB->currentText();
2071 QString const current_def_platex = defaultPlatexFormatCB->currentText();
2073 // update comboboxes with formats
2074 formatsCB->blockSignals(true);
2075 defaultFormatCB->blockSignals(true);
2076 defaultOTFFormatCB->blockSignals(true);
2077 defaultPlatexFormatCB->blockSignals(true);
2079 defaultFormatCB->clear();
2080 defaultOTFFormatCB->clear();
2081 defaultPlatexFormatCB->clear();
2082 form_->formats().sort();
2083 for (Format const & f : form_->formats()) {
2084 QString const prettyname = toqstr(translateIfPossible(f.prettyname()));
2085 formatsCB->addItem(prettyname,
2086 QVariant(form_->formats().getNumber(f.name())));
2087 if (f.viewer().empty())
2089 if (form_->converters().isReachable("xhtml", f.name())
2090 || form_->converters().isReachable("dviluatex", f.name())
2091 || form_->converters().isReachable("luatex", f.name())
2092 || form_->converters().isReachable("xetex", f.name())) {
2093 defaultFormatCB->addItem(prettyname,
2094 QVariant(toqstr(f.name())));
2095 defaultOTFFormatCB->addItem(prettyname,
2096 QVariant(toqstr(f.name())));
2098 if (form_->converters().isReachable("latex", f.name())
2099 || form_->converters().isReachable("pdflatex", f.name()))
2100 defaultFormatCB->addItem(prettyname,
2101 QVariant(toqstr(f.name())));
2102 if (form_->converters().isReachable("platex", f.name()))
2103 defaultPlatexFormatCB->addItem(prettyname,
2104 QVariant(toqstr(f.name())));
2108 // restore selections
2109 int item = formatsCB->findText(current, Qt::MatchExactly);
2110 formatsCB->setCurrentIndex(item < 0 ? 0 : item);
2111 on_formatsCB_currentIndexChanged(item < 0 ? 0 : item);
2112 item = defaultFormatCB->findText(current_def, Qt::MatchExactly);
2113 defaultFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2114 item = defaultOTFFormatCB->findText(current_def_otf, Qt::MatchExactly);
2115 defaultOTFFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2116 item = defaultPlatexFormatCB->findText(current_def_platex, Qt::MatchExactly);
2117 defaultPlatexFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2118 formatsCB->blockSignals(false);
2119 defaultFormatCB->blockSignals(false);
2120 defaultOTFFormatCB->blockSignals(false);
2121 defaultPlatexFormatCB->blockSignals(false);
2125 void PrefFileformats::on_formatsCB_currentIndexChanged(int i)
2127 if (form_->formats().empty())
2129 int const nr = formatsCB->itemData(i).toInt();
2130 Format const f = form_->formats().get(nr);
2132 formatED->setText(toqstr(f.name()));
2133 copierED->setText(toqstr(form_->movers().command(f.name())));
2134 extensionsED->setText(toqstr(f.extensions()));
2135 mimeED->setText(toqstr(f.mime()));
2136 shortcutED->setText(
2137 toqstr(l10n_shortcut(f.prettyname(), f.shortcut())));
2138 documentCB->setChecked((f.documentFormat()));
2139 vectorCB->setChecked((f.vectorFormat()));
2140 exportMenuCB->setChecked((f.inExportMenu()));
2141 exportMenuCB->setEnabled((f.documentFormat()));
2147 void PrefFileformats::setFlags()
2149 int flags = Format::none;
2150 if (documentCB->isChecked())
2151 flags |= Format::document;
2152 if (vectorCB->isChecked())
2153 flags |= Format::vector;
2154 if (exportMenuCB->isChecked())
2155 flags |= Format::export_menu;
2156 currentFormat().setFlags(flags);
2157 exportMenuCB->setEnabled(documentCB->isChecked());
2162 void PrefFileformats::on_copierED_textEdited(const QString & s)
2164 string const fmt = fromqstr(formatED->text());
2165 form_->movers().set(fmt, fromqstr(s));
2170 void PrefFileformats::on_extensionsED_textEdited(const QString & s)
2172 currentFormat().setExtensions(fromqstr(s));
2177 void PrefFileformats::on_viewerED_textEdited(const QString & s)
2179 currentFormat().setViewer(fromqstr(s));
2184 void PrefFileformats::on_editorED_textEdited(const QString & s)
2186 currentFormat().setEditor(fromqstr(s));
2191 void PrefFileformats::on_mimeED_textEdited(const QString & s)
2193 currentFormat().setMime(fromqstr(s));
2198 void PrefFileformats::on_shortcutED_textEdited(const QString & s)
2200 string const new_shortcut = fromqstr(s);
2201 if (new_shortcut == l10n_shortcut(currentFormat().prettyname(),
2202 currentFormat().shortcut()))
2204 currentFormat().setShortcut(new_shortcut);
2209 void PrefFileformats::on_formatED_editingFinished()
2211 string const newname = fromqstr(formatED->displayText());
2212 string const oldname = currentFormat().name();
2213 if (newname == oldname)
2215 if (form_->converters().formatIsUsed(oldname)) {
2216 Alert::error(_("Format in use"),
2217 _("You cannot change a format's short name "
2218 "if the format is used by a converter. "
2219 "Please remove the converter first."));
2224 currentFormat().setName(newname);
2229 void PrefFileformats::on_formatED_textChanged(const QString &)
2231 QString t = formatED->text();
2233 bool valid = formatED->validator()->validate(t, p) == QValidator::Acceptable;
2234 setValid(formatLA, valid);
2238 void PrefFileformats::on_formatsCB_editTextChanged(const QString &)
2240 QString t = formatsCB->currentText();
2242 bool valid = formatsCB->validator()->validate(t, p) == QValidator::Acceptable;
2243 setValid(formatsLA, valid);
2247 void PrefFileformats::updatePrettyname()
2249 QString const newname = formatsCB->currentText();
2250 if (newname == toqstr(translateIfPossible(currentFormat().prettyname())))
2253 currentFormat().setPrettyname(qstring_to_ucs4(newname));
2261 void updateComboBox(LyXRC::Alternatives const & alts,
2262 string const & fmt, QComboBox * combo)
2264 LyXRC::Alternatives::const_iterator it =
2266 if (it != alts.end()) {
2267 LyXRC::CommandSet const & cmds = it->second;
2268 LyXRC::CommandSet::const_iterator sit =
2270 LyXRC::CommandSet::const_iterator const sen =
2272 for (; sit != sen; ++sit) {
2273 QString const qcmd = toqstr(*sit);
2274 combo->addItem(qcmd, qcmd);
2281 void PrefFileformats::updateViewers()
2283 Format const f = currentFormat();
2284 viewerCO->blockSignals(true);
2286 viewerCO->addItem(qt_("None"), QString());
2287 updateComboBox(viewer_alternatives, f.name(), viewerCO);
2288 viewerCO->addItem(qt_("Custom"), QString("custom viewer"));
2289 viewerCO->blockSignals(false);
2291 int pos = viewerCO->findData(toqstr(f.viewer()));
2294 viewerED->setEnabled(false);
2295 viewerCO->setCurrentIndex(pos);
2297 viewerED->setEnabled(true);
2298 viewerED->setText(toqstr(f.viewer()));
2299 viewerCO->setCurrentIndex(viewerCO->findData(toqstr("custom viewer")));
2304 void PrefFileformats::updateEditors()
2306 Format const f = currentFormat();
2307 editorCO->blockSignals(true);
2309 editorCO->addItem(qt_("None"), QString());
2310 updateComboBox(editor_alternatives, f.name(), editorCO);
2311 editorCO->addItem(qt_("Custom"), QString("custom editor"));
2312 editorCO->blockSignals(false);
2314 int pos = editorCO->findData(toqstr(f.editor()));
2317 editorED->setEnabled(false);
2318 editorCO->setCurrentIndex(pos);
2320 editorED->setEnabled(true);
2321 editorED->setText(toqstr(f.editor()));
2322 editorCO->setCurrentIndex(editorCO->findData(toqstr("custom editor")));
2327 void PrefFileformats::on_viewerCO_currentIndexChanged(int i)
2329 bool const custom = viewerCO->itemData(i).toString() == "custom viewer";
2330 viewerED->setEnabled(custom);
2332 currentFormat().setViewer(fromqstr(viewerCO->itemData(i).toString()));
2336 void PrefFileformats::on_editorCO_currentIndexChanged(int i)
2338 bool const custom = editorCO->itemData(i).toString() == "custom editor";
2339 editorED->setEnabled(custom);
2341 currentFormat().setEditor(fromqstr(editorCO->itemData(i).toString()));
2345 Format & PrefFileformats::currentFormat()
2347 int const i = formatsCB->currentIndex();
2348 int const nr = formatsCB->itemData(i).toInt();
2349 return form_->formats().get(nr);
2353 void PrefFileformats::on_formatNewPB_clicked()
2355 form_->formats().add("", "", docstring(), "", "", "", "", Format::none);
2357 formatsCB->setCurrentIndex(0);
2358 formatsCB->setFocus(Qt::OtherFocusReason);
2362 void PrefFileformats::on_formatRemovePB_clicked()
2364 int const i = formatsCB->currentIndex();
2365 int const nr = formatsCB->itemData(i).toInt();
2366 string const current_text = form_->formats().get(nr).name();
2367 if (form_->converters().formatIsUsed(current_text)) {
2368 Alert::error(_("Format in use"),
2369 _("Cannot remove a Format used by a Converter. "
2370 "Remove the converter first."));
2374 form_->formats().erase(current_text);
2377 on_formatsCB_editTextChanged(formatsCB->currentText());
2382 /////////////////////////////////////////////////////////////////////
2386 /////////////////////////////////////////////////////////////////////
2388 PrefLanguage::PrefLanguage(GuiPreferences * form)
2389 : PrefModule(catLanguage, N_("Language"), form)
2393 connect(visualCursorRB, SIGNAL(clicked()),
2394 this, SIGNAL(changed()));
2395 connect(logicalCursorRB, SIGNAL(clicked()),
2396 this, SIGNAL(changed()));
2397 connect(markForeignCB, SIGNAL(clicked()),
2398 this, SIGNAL(changed()));
2399 connect(respectOSkbdCB, SIGNAL(clicked()),
2400 this, SIGNAL(changed()));
2401 connect(explicitDocLangBeginCB, SIGNAL(clicked()),
2402 this, SIGNAL(changed()));
2403 connect(explicitDocLangEndCB, SIGNAL(clicked()),
2404 this, SIGNAL(changed()));
2405 connect(languagePackageCO, SIGNAL(activated(int)),
2406 this, SIGNAL(changed()));
2407 connect(languagePackageED, SIGNAL(textChanged(QString)),
2408 this, SIGNAL(changed()));
2409 connect(globalCB, SIGNAL(clicked()),
2410 this, SIGNAL(changed()));
2411 connect(startCommandED, SIGNAL(textChanged(QString)),
2412 this, SIGNAL(changed()));
2413 connect(endCommandED, SIGNAL(textChanged(QString)),
2414 this, SIGNAL(changed()));
2415 connect(uiLanguageCO, SIGNAL(activated(int)),
2416 this, SIGNAL(changed()));
2417 connect(defaultDecimalSepED, SIGNAL(textChanged(QString)),
2418 this, SIGNAL(changed()));
2419 connect(defaultDecimalSepCO, SIGNAL(activated(int)),
2420 this, SIGNAL(changed()));
2421 connect(defaultLengthUnitCO, SIGNAL(activated(int)),
2422 this, SIGNAL(changed()));
2424 languagePackageED->setValidator(new NoNewLineValidator(languagePackageED));
2425 startCommandED->setValidator(new NoNewLineValidator(startCommandED));
2426 endCommandED->setValidator(new NoNewLineValidator(endCommandED));
2428 defaultDecimalSepED->setValidator(new QRegExpValidator(QRegExp("\\S"), this));
2429 defaultDecimalSepED->setMaxLength(1);
2431 defaultLengthUnitCO->addItem(lyx::qt_(unit_name_gui[Length::CM]), Length::CM);
2432 defaultLengthUnitCO->addItem(lyx::qt_(unit_name_gui[Length::IN]), Length::IN);
2434 QAbstractItemModel * language_model = guiApp->languageModel();
2435 language_model->sort(0);
2436 uiLanguageCO->blockSignals(true);
2437 uiLanguageCO->clear();
2438 uiLanguageCO->addItem(qt_("Default"), toqstr("auto"));
2439 for (int i = 0; i != language_model->rowCount(); ++i) {
2440 QModelIndex index = language_model->index(i, 0);
2441 // Filter the list based on the available translation and add
2442 // each language code only once
2443 string const name = fromqstr(index.data(Qt::UserRole).toString());
2444 Language const * lang = languages.getLanguage(name);
2447 // never remove the currently selected language
2448 if (name != form->rc().gui_language
2449 && name != lyxrc.gui_language
2450 && (!Messages::available(lang->code())
2451 || !lang->hasGuiSupport()))
2453 uiLanguageCO->addItem(index.data(Qt::DisplayRole).toString(),
2454 index.data(Qt::UserRole).toString());
2456 uiLanguageCO->blockSignals(false);
2460 void PrefLanguage::on_uiLanguageCO_currentIndexChanged(int)
2462 QMessageBox::information(this, qt_("LyX needs to be restarted!"),
2463 qt_("The change of user interface language will be fully "
2464 "effective only after a restart."));
2468 void PrefLanguage::on_languagePackageCO_currentIndexChanged(int i)
2471 languagePackageED->setText(save_langpack_);
2472 else if (!languagePackageED->text().isEmpty()) {
2473 save_langpack_ = languagePackageED->text();
2474 languagePackageED->clear();
2476 languagePackageED->setEnabled(i == 2);
2480 void PrefLanguage::on_defaultDecimalSepCO_currentIndexChanged(int i)
2482 defaultDecimalSepED->setEnabled(i == 1);
2486 void PrefLanguage::applyRC(LyXRC & rc) const
2488 rc.visual_cursor = visualCursorRB->isChecked();
2489 rc.mark_foreign_language = markForeignCB->isChecked();
2490 rc.respect_os_kbd_language = respectOSkbdCB->isChecked();
2491 rc.language_auto_begin = !explicitDocLangBeginCB->isChecked();
2492 rc.language_auto_end = !explicitDocLangEndCB->isChecked();
2493 int const p = languagePackageCO->currentIndex();
2495 rc.language_package_selection = LyXRC::LP_AUTO;
2497 rc.language_package_selection = LyXRC::LP_BABEL;
2499 rc.language_package_selection = LyXRC::LP_CUSTOM;
2501 rc.language_package_selection = LyXRC::LP_NONE;
2502 rc.language_custom_package = fromqstr(languagePackageED->text());
2503 rc.language_global_options = globalCB->isChecked();
2504 rc.language_command_begin = fromqstr(startCommandED->text());
2505 rc.language_command_end = fromqstr(endCommandED->text());
2506 rc.gui_language = fromqstr(
2507 uiLanguageCO->itemData(uiLanguageCO->currentIndex()).toString());
2508 if (defaultDecimalSepCO->currentIndex() == 0)
2509 rc.default_decimal_sep = "locale";
2511 rc.default_decimal_sep = fromqstr(defaultDecimalSepED->text());
2512 rc.default_length_unit = (Length::UNIT) defaultLengthUnitCO->itemData(defaultLengthUnitCO->currentIndex()).toInt();
2516 void PrefLanguage::updateRC(LyXRC const & rc)
2518 if (rc.visual_cursor)
2519 visualCursorRB->setChecked(true);
2521 logicalCursorRB->setChecked(true);
2522 markForeignCB->setChecked(rc.mark_foreign_language);
2523 respectOSkbdCB->setChecked(rc.respect_os_kbd_language);
2524 explicitDocLangBeginCB->setChecked(!rc.language_auto_begin);
2525 explicitDocLangEndCB->setChecked(!rc.language_auto_end);
2526 languagePackageCO->setCurrentIndex(rc.language_package_selection);
2527 if (languagePackageCO->currentIndex() == 2) {
2528 languagePackageED->setText(toqstr(rc.language_custom_package));
2529 languagePackageED->setEnabled(true);
2531 languagePackageED->clear();
2532 save_langpack_ = toqstr(rc.language_custom_package);
2533 languagePackageED->setEnabled(false);
2535 defaultDecimalSepED->setEnabled(defaultDecimalSepCO->currentIndex() == 1);
2536 globalCB->setChecked(rc.language_global_options);
2537 startCommandED->setText(toqstr(rc.language_command_begin));
2538 endCommandED->setText(toqstr(rc.language_command_end));
2539 if (rc.default_decimal_sep == "locale") {
2540 defaultDecimalSepCO->setCurrentIndex(0);
2541 defaultDecimalSepED->clear();
2543 defaultDecimalSepCO->setCurrentIndex(1);
2544 defaultDecimalSepED->setText(toqstr(rc.default_decimal_sep));
2546 int pos = defaultLengthUnitCO->findData(int(rc.default_length_unit));
2547 defaultLengthUnitCO->setCurrentIndex(pos);
2549 pos = uiLanguageCO->findData(toqstr(rc.gui_language));
2550 uiLanguageCO->blockSignals(true);
2551 uiLanguageCO->setCurrentIndex(pos);
2552 uiLanguageCO->blockSignals(false);
2556 /////////////////////////////////////////////////////////////////////
2558 // PrefUserInterface
2560 /////////////////////////////////////////////////////////////////////
2562 PrefUserInterface::PrefUserInterface(GuiPreferences * form)
2563 : PrefModule(catLookAndFeel, N_("User Interface"), form)
2567 connect(uiFilePB, SIGNAL(clicked()),
2568 this, SLOT(selectUi()));
2569 connect(uiFileED, SIGNAL(textChanged(QString)),
2570 this, SIGNAL(changed()));
2571 connect(iconSetCO, SIGNAL(activated(int)),
2572 this, SIGNAL(changed()));
2573 connect(useSystemThemeIconsCB, SIGNAL(clicked()),
2574 this, SIGNAL(changed()));
2575 connect(lastfilesSB, SIGNAL(valueChanged(int)),
2576 this, SIGNAL(changed()));
2577 connect(tooltipCB, SIGNAL(toggled(bool)),
2578 this, SIGNAL(changed()));
2579 lastfilesSB->setMaximum(maxlastfiles);
2581 iconSetCO->addItem(qt_("Default"), QString());
2582 iconSetCO->addItem(qt_("Classic"), "classic");
2583 iconSetCO->addItem(qt_("Oxygen"), "oxygen");
2585 #if (!(defined Q_WS_X11 || defined(QPA_XCB)) || QT_VERSION < 0x040600)
2586 useSystemThemeIconsCB->hide();
2591 void PrefUserInterface::applyRC(LyXRC & rc) const
2593 rc.icon_set = fromqstr(iconSetCO->itemData(
2594 iconSetCO->currentIndex()).toString());
2596 rc.ui_file = internal_path(fromqstr(uiFileED->text()));
2597 rc.use_system_theme_icons = useSystemThemeIconsCB->isChecked();
2598 rc.num_lastfiles = lastfilesSB->value();
2599 rc.use_tooltip = tooltipCB->isChecked();
2603 void PrefUserInterface::updateRC(LyXRC const & rc)
2605 int iconset = iconSetCO->findData(toqstr(rc.icon_set));
2608 iconSetCO->setCurrentIndex(iconset);
2609 useSystemThemeIconsCB->setChecked(rc.use_system_theme_icons);
2610 uiFileED->setText(toqstr(external_path(rc.ui_file)));
2611 lastfilesSB->setValue(rc.num_lastfiles);
2612 tooltipCB->setChecked(rc.use_tooltip);
2616 void PrefUserInterface::selectUi()
2618 QString file = form_->browseUI(internalPath(uiFileED->text()));
2619 if (!file.isEmpty())
2620 uiFileED->setText(file);
2624 /////////////////////////////////////////////////////////////////////
2626 // PrefDocumentHandling
2628 /////////////////////////////////////////////////////////////////////
2630 PrefDocHandling::PrefDocHandling(GuiPreferences * form)
2631 : PrefModule(catLookAndFeel, N_("Document Handling"), form)
2635 connect(autoSaveCB, SIGNAL(toggled(bool)),
2636 autoSaveSB, SLOT(setEnabled(bool)));
2637 connect(autoSaveCB, SIGNAL(toggled(bool)),
2638 TextLabel1, SLOT(setEnabled(bool)));
2639 connect(openDocumentsInTabsCB, SIGNAL(clicked()),
2640 this, SIGNAL(changed()));
2641 connect(singleInstanceCB, SIGNAL(clicked()),
2642 this, SIGNAL(changed()));
2643 connect(singleCloseTabButtonCB, SIGNAL(clicked()),
2644 this, SIGNAL(changed()));
2645 connect(closeLastViewCO, SIGNAL(activated(int)),
2646 this, SIGNAL(changed()));
2647 connect(restoreCursorCB, SIGNAL(clicked()),
2648 this, SIGNAL(changed()));
2649 connect(loadSessionCB, SIGNAL(clicked()),
2650 this, SIGNAL(changed()));
2651 connect(allowGeometrySessionCB, SIGNAL(clicked()),
2652 this, SIGNAL(changed()));
2653 connect(autoSaveSB, SIGNAL(valueChanged(int)),
2654 this, SIGNAL(changed()));
2655 connect(autoSaveCB, SIGNAL(clicked()),
2656 this, SIGNAL(changed()));
2657 connect(backupCB, SIGNAL(clicked()),
2658 this, SIGNAL(changed()));
2659 connect(saveCompressedCB, SIGNAL(clicked()),
2660 this, SIGNAL(changed()));
2661 connect(saveOriginCB, SIGNAL(clicked()),
2662 this, SIGNAL(changed()));
2666 void PrefDocHandling::applyRC(LyXRC & rc) const
2668 rc.use_lastfilepos = restoreCursorCB->isChecked();
2669 rc.load_session = loadSessionCB->isChecked();
2670 rc.allow_geometry_session = allowGeometrySessionCB->isChecked();
2671 rc.autosave = autoSaveCB->isChecked() ? autoSaveSB->value() * 60 : 0;
2672 rc.make_backup = backupCB->isChecked();
2673 rc.save_compressed = saveCompressedCB->isChecked();
2674 rc.save_origin = saveOriginCB->isChecked();
2675 rc.open_buffers_in_tabs = openDocumentsInTabsCB->isChecked();
2676 rc.single_instance = singleInstanceCB->isChecked();
2677 rc.single_close_tab_button = singleCloseTabButtonCB->isChecked();
2679 switch (closeLastViewCO->currentIndex()) {
2681 rc.close_buffer_with_last_view = "yes";
2684 rc.close_buffer_with_last_view = "no";
2687 rc.close_buffer_with_last_view = "ask";
2695 void PrefDocHandling::updateRC(LyXRC const & rc)
2697 restoreCursorCB->setChecked(rc.use_lastfilepos);
2698 loadSessionCB->setChecked(rc.load_session);
2699 allowGeometrySessionCB->setChecked(rc.allow_geometry_session);
2700 // convert to minutes
2701 bool autosave = rc.autosave > 0;
2702 int mins = rc.autosave / 60;
2705 autoSaveSB->setValue(mins);
2706 autoSaveCB->setChecked(autosave);
2707 autoSaveSB->setEnabled(autosave);
2708 backupCB->setChecked(rc.make_backup);
2709 saveCompressedCB->setChecked(rc.save_compressed);
2710 saveOriginCB->setChecked(rc.save_origin);
2711 openDocumentsInTabsCB->setChecked(rc.open_buffers_in_tabs);
2712 singleInstanceCB->setChecked(rc.single_instance && !rc.lyxpipes.empty());
2713 singleInstanceCB->setEnabled(!rc.lyxpipes.empty());
2714 singleCloseTabButtonCB->setChecked(rc.single_close_tab_button);
2715 if (rc.close_buffer_with_last_view == "yes")
2716 closeLastViewCO->setCurrentIndex(0);
2717 else if (rc.close_buffer_with_last_view == "no")
2718 closeLastViewCO->setCurrentIndex(1);
2719 else if (rc.close_buffer_with_last_view == "ask")
2720 closeLastViewCO->setCurrentIndex(2);
2724 void PrefDocHandling::on_clearSessionPB_clicked()
2726 guiApp->clearSession();
2731 /////////////////////////////////////////////////////////////////////
2735 /////////////////////////////////////////////////////////////////////
2737 PrefEdit::PrefEdit(GuiPreferences * form)
2738 : PrefModule(catEditing, N_("Control"), form)
2742 connect(cursorFollowsCB, SIGNAL(clicked()),
2743 this, SIGNAL(changed()));
2744 connect(scrollBelowCB, SIGNAL(clicked()),
2745 this, SIGNAL(changed()));
2746 connect(macLikeCursorMovementCB, SIGNAL(clicked()),
2747 this, SIGNAL(changed()));
2748 connect(copyCTMarkupCB, SIGNAL(clicked()),
2749 this, SIGNAL(changed()));
2750 connect(sortEnvironmentsCB, SIGNAL(clicked()),
2751 this, SIGNAL(changed()));
2752 connect(groupEnvironmentsCB, SIGNAL(clicked()),
2753 this, SIGNAL(changed()));
2754 connect(macroEditStyleCO, SIGNAL(activated(int)),
2755 this, SIGNAL(changed()));
2756 connect(cursorWidthSB, SIGNAL(valueChanged(int)),
2757 this, SIGNAL(changed()));
2758 connect(citationSearchLE, SIGNAL(textChanged(QString)),
2759 this, SIGNAL(changed()));
2760 connect(fullscreenWidthSB, SIGNAL(valueChanged(int)),
2761 this, SIGNAL(changed()));
2762 connect(toggleTabbarCB, SIGNAL(toggled(bool)),
2763 this, SIGNAL(changed()));
2764 connect(toggleMenubarCB, SIGNAL(toggled(bool)),
2765 this, SIGNAL(changed()));
2766 connect(toggleScrollbarCB, SIGNAL(toggled(bool)),
2767 this, SIGNAL(changed()));
2768 connect(toggleStatusbarCB, SIGNAL(toggled(bool)),
2769 this, SIGNAL(changed()));
2770 connect(toggleToolbarsCB, SIGNAL(toggled(bool)),
2771 this, SIGNAL(changed()));
2775 void PrefEdit::on_fullscreenLimitCB_toggled(bool const state)
2777 fullscreenWidthSB->setEnabled(state);
2778 fullscreenWidthLA->setEnabled(state);
2783 void PrefEdit::on_citationSearchCB_toggled(bool const state)
2785 citationSearchLE->setEnabled(state);
2786 citationSearchLA->setEnabled(state);
2791 void PrefEdit::applyRC(LyXRC & rc) const
2793 rc.cursor_follows_scrollbar = cursorFollowsCB->isChecked();
2794 rc.scroll_below_document = scrollBelowCB->isChecked();
2795 rc.mac_like_cursor_movement = macLikeCursorMovementCB->isChecked();
2796 rc.ct_markup_copied = copyCTMarkupCB->isChecked();
2797 rc.sort_layouts = sortEnvironmentsCB->isChecked();
2798 rc.group_layouts = groupEnvironmentsCB->isChecked();
2799 switch (macroEditStyleCO->currentIndex()) {
2800 case 0: rc.macro_edit_style = LyXRC::MACRO_EDIT_INLINE_BOX; break;
2801 case 1: rc.macro_edit_style = LyXRC::MACRO_EDIT_INLINE; break;
2802 case 2: rc.macro_edit_style = LyXRC::MACRO_EDIT_LIST; break;
2804 rc.cursor_width = cursorWidthSB->value();
2805 rc.citation_search = citationSearchCB->isChecked();
2806 rc.citation_search_pattern = fromqstr(citationSearchLE->text());
2807 rc.full_screen_toolbars = toggleToolbarsCB->isChecked();
2808 rc.full_screen_scrollbar = toggleScrollbarCB->isChecked();
2809 rc.full_screen_statusbar = toggleStatusbarCB->isChecked();
2810 rc.full_screen_tabbar = toggleTabbarCB->isChecked();
2811 rc.full_screen_menubar = toggleMenubarCB->isChecked();
2812 rc.full_screen_width = fullscreenWidthSB->value();
2813 rc.full_screen_limit = fullscreenLimitCB->isChecked();
2817 void PrefEdit::updateRC(LyXRC const & rc)
2819 cursorFollowsCB->setChecked(rc.cursor_follows_scrollbar);
2820 scrollBelowCB->setChecked(rc.scroll_below_document);
2821 macLikeCursorMovementCB->setChecked(rc.mac_like_cursor_movement);
2822 copyCTMarkupCB->setChecked(rc.ct_markup_copied);
2823 sortEnvironmentsCB->setChecked(rc.sort_layouts);
2824 groupEnvironmentsCB->setChecked(rc.group_layouts);
2825 macroEditStyleCO->setCurrentIndex(rc.macro_edit_style);
2826 cursorWidthSB->setValue(rc.cursor_width);
2827 citationSearchCB->setChecked(rc.citation_search);
2828 citationSearchLE->setText(toqstr(rc.citation_search_pattern));
2829 citationSearchLE->setEnabled(rc.citation_search);
2830 citationSearchLA->setEnabled(rc.citation_search);
2831 toggleScrollbarCB->setChecked(rc.full_screen_scrollbar);
2832 toggleStatusbarCB->setChecked(rc.full_screen_statusbar);
2833 toggleToolbarsCB->setChecked(rc.full_screen_toolbars);
2834 toggleTabbarCB->setChecked(rc.full_screen_tabbar);
2835 toggleMenubarCB->setChecked(rc.full_screen_menubar);
2836 fullscreenWidthSB->setValue(rc.full_screen_width);
2837 fullscreenLimitCB->setChecked(rc.full_screen_limit);
2838 fullscreenWidthSB->setEnabled(rc.full_screen_limit);
2839 fullscreenWidthLA->setEnabled(rc.full_screen_limit);
2843 /////////////////////////////////////////////////////////////////////
2847 /////////////////////////////////////////////////////////////////////
2850 GuiShortcutDialog::GuiShortcutDialog(QWidget * parent) : QDialog(parent)
2852 Ui::shortcutUi::setupUi(this);
2853 QDialog::setModal(true);
2854 lfunLE->setValidator(new NoNewLineValidator(lfunLE));
2858 PrefShortcuts::PrefShortcuts(GuiPreferences * form)
2859 : PrefModule(catEditing, N_("Shortcuts"), form),
2860 editItem_(nullptr), mathItem_(nullptr), bufferItem_(nullptr), layoutItem_(nullptr),
2861 systemItem_(nullptr)
2865 shortcutsTW->setColumnCount(2);
2866 shortcutsTW->headerItem()->setText(0, qt_("Function"));
2867 shortcutsTW->headerItem()->setText(1, qt_("Shortcut"));
2868 shortcutsTW->setSortingEnabled(true);
2869 // Multi-selection can be annoying.
2870 // shortcutsTW->setSelectionMode(QAbstractItemView::MultiSelection);
2872 connect(bindFilePB, SIGNAL(clicked()),
2873 this, SLOT(selectBind()));
2874 connect(bindFileED, SIGNAL(textChanged(QString)),
2875 this, SIGNAL(changed()));
2877 shortcut_ = new GuiShortcutDialog(this);
2878 shortcut_bc_.setPolicy(ButtonPolicy::OkCancelPolicy);
2879 shortcut_bc_.setOK(shortcut_->buttonBox->button(QDialogButtonBox::Ok));
2880 shortcut_bc_.setCancel(shortcut_->buttonBox->button(QDialogButtonBox::Cancel));
2882 connect(shortcut_->buttonBox, SIGNAL(accepted()),
2883 this, SIGNAL(changed()));
2884 connect(shortcut_->buttonBox, SIGNAL(rejected()),
2885 shortcut_, SLOT(reject()));
2886 connect(shortcut_->clearPB, SIGNAL(clicked()),
2887 this, SLOT(shortcutClearPressed()));
2888 connect(shortcut_->removePB, SIGNAL(clicked()),
2889 this, SLOT(shortcutRemovePressed()));
2890 connect(shortcut_->buttonBox, SIGNAL(accepted()),
2891 this, SLOT(shortcutOkPressed()));
2892 connect(shortcut_->buttonBox, SIGNAL(rejected()),
2893 this, SLOT(shortcutCancelPressed()));
2897 void PrefShortcuts::applyRC(LyXRC & rc) const
2899 rc.bind_file = internal_path(fromqstr(bindFileED->text()));
2900 // write user_bind and user_unbind to .lyx/bind/user.bind
2901 FileName bind_dir(addPath(package().user_support().absFileName(), "bind"));
2902 if (!bind_dir.exists() && !bind_dir.createDirectory(0777)) {
2903 lyxerr << "LyX could not create the user bind directory '"
2904 << bind_dir << "'. All user-defined key bindings will be lost." << endl;
2907 if (!bind_dir.isDirWritable()) {
2908 lyxerr << "LyX could not write to the user bind directory '"
2909 << bind_dir << "'. All user-defined key bindings will be lost." << endl;
2912 FileName user_bind_file(bind_dir.absFileName() + "/user.bind");
2913 user_unbind_.write(user_bind_file.toFilesystemEncoding(), false, true);
2914 user_bind_.write(user_bind_file.toFilesystemEncoding(), true, false);
2915 // immediately apply the keybindings. Why this is not done before?
2916 // The good thing is that the menus are updated automatically.
2917 theTopLevelKeymap().clear();
2918 theTopLevelKeymap().read("site");
2919 theTopLevelKeymap().read(rc.bind_file, nullptr, KeyMap::Fallback);
2920 theTopLevelKeymap().read("user", nullptr, KeyMap::MissingOK);
2924 void PrefShortcuts::updateRC(LyXRC const & rc)
2926 bindFileED->setText(toqstr(external_path(rc.bind_file)));
2928 system_bind_.clear();
2930 user_unbind_.clear();
2931 system_bind_.read("site");
2932 system_bind_.read(rc.bind_file);
2933 // \unbind in user.bind is added to user_unbind_
2934 user_bind_.read("user", &user_unbind_, KeyMap::MissingOK);
2935 updateShortcutsTW();
2939 void PrefShortcuts::updateShortcutsTW()
2941 shortcutsTW->clear();
2943 editItem_ = new QTreeWidgetItem(shortcutsTW);
2944 editItem_->setText(0, qt_("Cursor, Mouse and Editing Functions"));
2945 editItem_->setFlags(editItem_->flags() & ~Qt::ItemIsSelectable);
2947 mathItem_ = new QTreeWidgetItem(shortcutsTW);
2948 mathItem_->setText(0, qt_("Mathematical Symbols"));
2949 mathItem_->setFlags(mathItem_->flags() & ~Qt::ItemIsSelectable);
2951 bufferItem_ = new QTreeWidgetItem(shortcutsTW);
2952 bufferItem_->setText(0, qt_("Document and Window"));
2953 bufferItem_->setFlags(bufferItem_->flags() & ~Qt::ItemIsSelectable);
2955 layoutItem_ = new QTreeWidgetItem(shortcutsTW);
2956 layoutItem_->setText(0, qt_("Font, Layouts and Textclasses"));
2957 layoutItem_->setFlags(layoutItem_->flags() & ~Qt::ItemIsSelectable);
2959 systemItem_ = new QTreeWidgetItem(shortcutsTW);
2960 systemItem_->setText(0, qt_("System and Miscellaneous"));
2961 systemItem_->setFlags(systemItem_->flags() & ~Qt::ItemIsSelectable);
2963 // listBindings(unbound=true) lists all bound and unbound lfuns
2964 // Items in this list is tagged by its source.
2965 KeyMap::BindingList bindinglist = system_bind_.listBindings(true,
2967 KeyMap::BindingList user_bindinglist = user_bind_.listBindings(false,
2969 KeyMap::BindingList user_unbindinglist = user_unbind_.listBindings(false,
2970 KeyMap::UserUnbind);
2971 bindinglist.insert(bindinglist.end(), user_bindinglist.begin(),
2972 user_bindinglist.end());
2973 bindinglist.insert(bindinglist.end(), user_unbindinglist.begin(),
2974 user_unbindinglist.end());
2976 KeyMap::BindingList::const_iterator it = bindinglist.begin();
2977 KeyMap::BindingList::const_iterator it_end = bindinglist.end();
2978 for (; it != it_end; ++it)
2979 insertShortcutItem(it->request, it->sequence, it->tag);
2981 shortcutsTW->sortItems(0, Qt::AscendingOrder);
2982 on_shortcutsTW_itemSelectionChanged();
2983 on_searchLE_textEdited();
2984 shortcutsTW->resizeColumnToContents(0);
2989 KeyMap::ItemType PrefShortcuts::itemType(QTreeWidgetItem & item)
2991 return static_cast<KeyMap::ItemType>(item.data(0, Qt::UserRole).toInt());
2996 bool PrefShortcuts::isAlwaysHidden(QTreeWidgetItem & item)
2998 // Hide rebound system settings that are empty
2999 return itemType(item) == KeyMap::UserUnbind && item.text(1).isEmpty();
3003 void PrefShortcuts::setItemType(QTreeWidgetItem * item, KeyMap::ItemType tag)
3005 item->setData(0, Qt::UserRole, QVariant(tag));
3009 case KeyMap::System:
3011 case KeyMap::UserBind:
3014 case KeyMap::UserUnbind:
3015 font.setStrikeOut(true);
3017 // this item is not displayed now.
3018 case KeyMap::UserExtraUnbind:
3019 font.setStrikeOut(true);
3022 item->setHidden(isAlwaysHidden(*item));
3023 item->setFont(1, font);
3027 QTreeWidgetItem * PrefShortcuts::insertShortcutItem(FuncRequest const & lfun,
3028 KeySequence const & seq, KeyMap::ItemType tag)
3030 FuncCode const action = lfun.action();
3031 string const action_name = lyxaction.getActionName(action);
3032 QString const lfun_name = toqstr(from_utf8(action_name)
3033 + ' ' + lfun.argument());
3034 QString const shortcut = toqstr(seq.print(KeySequence::ForGui));
3036 QTreeWidgetItem * newItem = nullptr;
3037 // for unbind items, try to find an existing item in the system bind list
3038 if (tag == KeyMap::UserUnbind) {
3039 QList<QTreeWidgetItem*> const items = shortcutsTW->findItems(lfun_name,
3040 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 0);
3041 for (auto const & item : items) {
3042 if (item->text(1) == shortcut) {
3047 // if not found, this unbind item is KeyMap::UserExtraUnbind
3048 // Such an item is not displayed to avoid confusion (what is
3049 // unmatched removed?).
3055 switch(lyxaction.getActionType(action)) {
3056 case LyXAction::Hidden:
3058 case LyXAction::Edit:
3059 newItem = new QTreeWidgetItem(editItem_);
3061 case LyXAction::Math:
3062 newItem = new QTreeWidgetItem(mathItem_);
3064 case LyXAction::Buffer:
3065 newItem = new QTreeWidgetItem(bufferItem_);
3067 case LyXAction::Layout:
3068 newItem = new QTreeWidgetItem(layoutItem_);
3070 case LyXAction::System:
3071 newItem = new QTreeWidgetItem(systemItem_);
3074 // this should not happen
3075 newItem = new QTreeWidgetItem(shortcutsTW);
3079 newItem->setText(0, lfun_name);
3080 newItem->setText(1, shortcut);
3081 // record BindFile representation to recover KeySequence when needed.
3082 newItem->setData(1, Qt::UserRole, toqstr(seq.print(KeySequence::BindFile)));
3083 setItemType(newItem, tag);
3088 void PrefShortcuts::on_shortcutsTW_itemSelectionChanged()
3090 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
3091 removePB->setEnabled(!items.isEmpty() && !items[0]->text(1).isEmpty());
3092 modifyPB->setEnabled(!items.isEmpty());
3093 if (items.isEmpty())
3096 if (itemType(*items[0]) == KeyMap::UserUnbind)
3097 removePB->setText(qt_("Res&tore"));
3099 removePB->setText(qt_("Remo&ve"));
3103 void PrefShortcuts::on_shortcutsTW_itemDoubleClicked()
3109 void PrefShortcuts::modifyShortcut()
3111 QTreeWidgetItem * item = shortcutsTW->currentItem();
3112 if (item->flags() & Qt::ItemIsSelectable) {
3113 shortcut_->lfunLE->setText(item->text(0));
3114 save_lfun_ = item->text(0).trimmed();
3115 shortcut_->shortcutWG->setText(item->text(1));
3117 seq.parse(fromqstr(item->data(1, Qt::UserRole).toString()));
3118 shortcut_->shortcutWG->setKeySequence(seq);
3119 shortcut_->shortcutWG->setFocus();
3125 void PrefShortcuts::unhideEmpty(QString const & lfun, bool select)
3127 // list of items that match lfun
3128 QList<QTreeWidgetItem*> items = shortcutsTW->findItems(lfun,
3129 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 0);
3130 for (auto const & item : items) {
3131 if (isAlwaysHidden(*item)) {
3132 setItemType(item, KeyMap::System);
3134 shortcutsTW->setCurrentItem(item);
3141 void PrefShortcuts::removeShortcut()
3143 // it seems that only one item can be selected, but I am
3144 // removing all selected items anyway.
3145 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
3146 for (auto & item : items) {
3147 string shortcut = fromqstr(item->data(1, Qt::UserRole).toString());
3148 string lfun = fromqstr(item->text(0));
3149 FuncRequest const func = lyxaction.lookupFunc(lfun);
3151 switch (itemType(*item)) {
3152 case KeyMap::System: {
3153 // for system bind, we do not touch the item
3154 // but add an user unbind item
3155 user_unbind_.bind(shortcut, func);
3156 setItemType(item, KeyMap::UserUnbind);
3157 removePB->setText(qt_("Res&tore"));
3160 case KeyMap::UserBind: {
3161 // for user_bind, we remove this bind
3162 QTreeWidgetItem * parent = item->parent();
3163 int itemIdx = parent->indexOfChild(item);
3164 parent->takeChild(itemIdx);
3166 shortcutsTW->scrollToItem(parent->child(itemIdx - 1));
3168 shortcutsTW->scrollToItem(parent);
3169 user_bind_.unbind(shortcut, func);
3170 // If this user binding hid an empty system binding, unhide the
3171 // latter and select it.
3172 unhideEmpty(item->text(0), true);
3175 case KeyMap::UserUnbind: {
3176 // for user_unbind, we remove the unbind, and the item
3177 // become KeyMap::System again.
3179 seq.parse(shortcut);
3180 // Ask the user to replace current binding
3181 if (!validateNewShortcut(func, seq, QString()))
3183 user_unbind_.unbind(shortcut, func);
3184 setItemType(item, KeyMap::System);
3185 removePB->setText(qt_("Remo&ve"));
3188 case KeyMap::UserExtraUnbind: {
3189 // for user unbind that is not in system bind file,
3190 // remove this unbind file
3191 QTreeWidgetItem * parent = item->parent();
3192 parent->takeChild(parent->indexOfChild(item));
3193 user_unbind_.unbind(shortcut, func);
3200 void PrefShortcuts::deactivateShortcuts(QList<QTreeWidgetItem*> const & items)
3202 for (auto item : items) {
3203 string shortcut = fromqstr(item->data(1, Qt::UserRole).toString());
3204 string lfun = fromqstr(item->text(0));
3205 FuncRequest const func = lyxaction.lookupFunc(lfun);
3207 switch (itemType(*item)) {
3208 case KeyMap::System:
3209 // for system bind, we do not touch the item
3210 // but add an user unbind item
3211 user_unbind_.bind(shortcut, func);
3212 setItemType(item, KeyMap::UserUnbind);
3215 case KeyMap::UserBind: {
3216 // for user_bind, we remove this bind
3217 QTreeWidgetItem * parent = item->parent();
3218 int itemIdx = parent->indexOfChild(item);
3219 parent->takeChild(itemIdx);
3220 user_bind_.unbind(shortcut, func);
3221 unhideEmpty(item->text(0), false);
3231 void PrefShortcuts::selectBind()
3233 QString file = form_->browsebind(internalPath(bindFileED->text()));
3234 if (!file.isEmpty()) {
3235 bindFileED->setText(file);
3236 system_bind_ = KeyMap();
3237 system_bind_.read(fromqstr(file));
3238 updateShortcutsTW();
3243 void PrefShortcuts::on_modifyPB_pressed()
3249 void PrefShortcuts::on_newPB_pressed()
3251 shortcut_->lfunLE->clear();
3252 shortcut_->shortcutWG->reset();
3253 save_lfun_ = QString();
3258 void PrefShortcuts::on_removePB_pressed()
3265 void PrefShortcuts::on_searchLE_textEdited()
3267 if (searchLE->text().isEmpty()) {
3268 // show all hidden items
3269 QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Hidden);
3271 (*it)->setHidden(isAlwaysHidden(**it));
3272 // close all categories
3273 for (int i = 0; i < shortcutsTW->topLevelItemCount(); ++i)
3274 shortcutsTW->collapseItem(shortcutsTW->topLevelItem(i));
3277 // search both columns
3278 QList<QTreeWidgetItem *> matched = shortcutsTW->findItems(searchLE->text(),
3279 Qt::MatchFlags(Qt::MatchContains | Qt::MatchRecursive), 0);
3280 matched += shortcutsTW->findItems(searchLE->text(),
3281 Qt::MatchFlags(Qt::MatchContains | Qt::MatchRecursive), 1);
3283 // hide everyone (to avoid searching in matched QList repeatedly
3284 QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Selectable);
3286 (*it++)->setHidden(true);
3287 // show matched items
3288 for (auto & item : matched)
3289 if (!isAlwaysHidden(*item)) {
3290 item->setHidden(false);
3292 item->parent()->setExpanded(true);
3297 docstring makeCmdString(FuncRequest const & f)
3299 docstring actionStr = from_ascii(lyxaction.getActionName(f.action()));
3300 if (!f.argument().empty())
3301 actionStr += " " + f.argument();
3306 FuncRequest PrefShortcuts::currentBinding(KeySequence const & k)
3308 FuncRequest res = user_bind_.getBinding(k);
3309 if (res.action() != LFUN_UNKNOWN_ACTION)
3311 res = system_bind_.getBinding(k);
3312 // Check if it is unbound. Note: user_unbind_ can only unbind one
3313 // FuncRequest per key sequence.
3314 if (user_unbind_.getBinding(k) == res)
3315 return FuncRequest::unknown;
3320 bool PrefShortcuts::validateNewShortcut(FuncRequest const & func,
3321 KeySequence const & k,
3322 QString const & lfun_to_modify)
3324 if (func.action() == LFUN_UNKNOWN_ACTION) {
3325 Alert::error(_("Failed to create shortcut"),
3326 _("Unknown or invalid LyX function"));
3330 // It is not currently possible to bind Hidden lfuns such as self-insert. In
3331 // the future, to remove this limitation, see GuiPrefs::insertShortcutItem
3332 // and how it is used in GuiPrefs::shortcutOkPressed.
3333 if (lyxaction.getActionType(func.action()) == LyXAction::Hidden) {
3334 Alert::error(_("Failed to create shortcut"),
3335 _("This LyX function is hidden and cannot be bound."));
3339 if (k.length() == 0) {
3340 Alert::error(_("Failed to create shortcut"),
3341 _("Invalid or empty key sequence"));
3345 FuncRequest oldBinding = currentBinding(k);
3346 if (oldBinding == func)
3347 // nothing to change
3350 // make sure this key isn't already bound---and, if so, prompt user
3351 // (exclude the lfun the user already wants to modify)
3352 docstring const action_string = makeCmdString(oldBinding);
3353 if (oldBinding.action() != LFUN_UNKNOWN_ACTION
3354 && lfun_to_modify != toqstr(action_string)) {
3355 docstring const new_action_string = makeCmdString(func);
3356 docstring const text = bformat(_("Shortcut `%1$s' is already bound to "
3358 "Are you sure you want to unbind the "
3359 "current shortcut and bind it to %3$s?"),
3360 k.print(KeySequence::ForGui), action_string,
3362 int ret = Alert::prompt(_("Redefine shortcut?"),
3363 text, 0, 1, _("&Redefine"), _("&Cancel"));
3366 QString const sequence_text = toqstr(k.print(KeySequence::ForGui));
3367 QList<QTreeWidgetItem*> items = shortcutsTW->findItems(sequence_text,
3368 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 1);
3369 deactivateShortcuts(items);
3375 void PrefShortcuts::shortcutOkPressed()
3377 QString const new_lfun = shortcut_->lfunLE->text();
3378 FuncRequest const func = lyxaction.lookupFunc(fromqstr(new_lfun));
3379 KeySequence k = shortcut_->shortcutWG->getKeySequence();
3381 // save_lfun_ contains the text of the lfun to modify, if the user clicked
3382 // "modify", or is empty if they clicked "new" (which I do not really like)
3383 if (!validateNewShortcut(func, k, save_lfun_))
3386 if (!save_lfun_.isEmpty()) {
3387 // real modification of the lfun's shortcut,
3388 // so remove the previous one
3389 QList<QTreeWidgetItem*> to_modify = shortcutsTW->selectedItems();
3390 deactivateShortcuts(to_modify);
3393 shortcut_->accept();
3395 QTreeWidgetItem * item = insertShortcutItem(func, k, KeyMap::UserBind);
3397 user_bind_.bind(&k, func);
3398 shortcutsTW->sortItems(0, Qt::AscendingOrder);
3399 item->parent()->setExpanded(true);
3400 shortcutsTW->setCurrentItem(item);
3401 shortcutsTW->scrollToItem(item);
3403 Alert::error(_("Failed to create shortcut"),
3404 _("Can not insert shortcut to the list"));
3410 void PrefShortcuts::shortcutCancelPressed()
3412 shortcut_->shortcutWG->reset();
3416 void PrefShortcuts::shortcutClearPressed()
3418 shortcut_->shortcutWG->reset();
3422 void PrefShortcuts::shortcutRemovePressed()
3424 shortcut_->shortcutWG->removeFromSequence();
3428 /////////////////////////////////////////////////////////////////////
3432 /////////////////////////////////////////////////////////////////////
3434 PrefIdentity::PrefIdentity(GuiPreferences * form)
3435 : PrefModule(QString(), N_("Identity"), form)
3439 connect(nameED, SIGNAL(textChanged(QString)),
3440 this, SIGNAL(changed()));
3441 connect(emailED, SIGNAL(textChanged(QString)),
3442 this, SIGNAL(changed()));
3443 connect(initialsED, SIGNAL(textChanged(QString)),
3444 this, SIGNAL(changed()));
3446 nameED->setValidator(new NoNewLineValidator(nameED));
3447 emailED->setValidator(new NoNewLineValidator(emailED));
3448 initialsED->setValidator(new NoNewLineValidator(initialsED));
3452 void PrefIdentity::applyRC(LyXRC & rc) const
3454 rc.user_name = fromqstr(nameED->text());
3455 rc.user_email = fromqstr(emailED->text());
3456 rc.user_initials = fromqstr(initialsED->text());
3460 void PrefIdentity::updateRC(LyXRC const & rc)
3462 nameED->setText(toqstr(rc.user_name));
3463 emailED->setText(toqstr(rc.user_email));
3464 initialsED->setText(toqstr(rc.user_initials));
3469 /////////////////////////////////////////////////////////////////////
3473 /////////////////////////////////////////////////////////////////////
3475 GuiPreferences::GuiPreferences(GuiView & lv)
3476 : GuiDialog(lv, "prefs", qt_("Preferences"))
3480 QDialog::setModal(false);
3482 connect(buttonBox, SIGNAL(clicked(QAbstractButton *)),
3483 this, SLOT(slotButtonBox(QAbstractButton *)));
3485 addModule(new PrefUserInterface(this));
3486 addModule(new PrefDocHandling(this));
3487 addModule(new PrefEdit(this));
3488 addModule(new PrefShortcuts(this));
3489 PrefScreenFonts * screenfonts = new PrefScreenFonts(this);
3490 connect(this, SIGNAL(prefsApplied(LyXRC const &)),
3491 screenfonts, SLOT(updateScreenFontSizes(LyXRC const &)));
3492 addModule(screenfonts);
3493 addModule(new PrefColors(this));
3494 addModule(new PrefDisplay(this));
3495 addModule(new PrefInput(this));
3496 addModule(new PrefCompletion(this));
3498 addModule(new PrefPaths(this));
3500 addModule(new PrefIdentity(this));
3502 addModule(new PrefLanguage(this));
3503 addModule(new PrefSpellchecker(this));
3505 PrefOutput * output = new PrefOutput(this);
3507 addModule(new PrefLatex(this));
3509 PrefConverters * converters = new PrefConverters(this);
3510 PrefFileformats * formats = new PrefFileformats(this);
3511 connect(formats, SIGNAL(formatsChanged()),
3512 converters, SLOT(updateGui()));
3513 addModule(converters);
3516 prefsPS->setCurrentPanel("User Interface");
3517 // FIXME: hack to work around resizing bug in Qt >= 4.2
3518 // bug verified with Qt 4.2.{0-3} (JSpitzm)
3519 #if QT_VERSION >= 0x040200
3520 prefsPS->updateGeometry();
3523 bc().setPolicy(ButtonPolicy::PreferencesPolicy);
3524 bc().setOK(buttonBox->button(QDialogButtonBox::Ok));
3525 bc().setApply(buttonBox->button(QDialogButtonBox::Apply));
3526 bc().setCancel(buttonBox->button(QDialogButtonBox::Cancel));
3527 bc().setRestore(buttonBox->button(QDialogButtonBox::Reset));
3529 guilyxfiles_ = new GuiLyXFiles(lv);
3530 connect(guilyxfiles_, SIGNAL(fileSelected(QString)),
3531 this, SLOT(slotFileSelected(QString)));
3535 void GuiPreferences::addModule(PrefModule * module)
3537 LASSERT(module, return);
3538 if (module->category().isEmpty())
3539 prefsPS->addPanel(module, module->title());
3541 prefsPS->addPanel(module, module->title(), module->category());
3542 connect(module, SIGNAL(changed()), this, SLOT(change_adaptor()));
3543 modules_.push_back(module);
3547 void GuiPreferences::change_adaptor()
3553 void GuiPreferences::applyRC(LyXRC & rc) const
3555 size_t end = modules_.size();
3556 for (size_t i = 0; i != end; ++i)
3557 modules_[i]->applyRC(rc);
3561 void GuiPreferences::updateRC(LyXRC const & rc)
3563 size_t const end = modules_.size();
3564 for (size_t i = 0; i != end; ++i)
3565 modules_[i]->updateRC(rc);
3569 void GuiPreferences::applyView()
3575 bool GuiPreferences::initialiseParams(string const &)
3578 formats_ = theFormats();
3579 converters_ = theConverters();
3580 converters_.update(formats_);
3581 movers_ = theMovers();
3585 // Make sure that the bc is in the INITIAL state
3586 if (bc().policy().buttonStatus(ButtonPolicy::RESTORE))
3593 void GuiPreferences::dispatchParams()
3596 rc_.write(ss, true);
3597 dispatch(FuncRequest(LFUN_LYXRC_APPLY, ss.str()));
3598 // issue prefsApplied signal. This will update the
3599 // localized screen font sizes.
3601 // FIXME: these need lfuns
3603 Author const & author =
3604 Author(from_utf8(rc_.user_name), from_utf8(rc_.user_email),
3605 from_utf8(rc_.user_initials));
3606 theBufferList().recordCurrentAuthor(author);
3608 theFormats() = formats_;
3610 theConverters() = converters_;
3611 theConverters().update(formats_);
3612 theConverters().buildGraph();
3613 theBufferList().invalidateConverterCache();
3615 theMovers() = movers_;
3617 for (string const & color : colors_)
3618 dispatch(FuncRequest(LFUN_SET_COLOR, color));
3622 if (!tempSaveCB->isChecked())
3623 dispatch(FuncRequest(LFUN_PREFERENCES_SAVE));
3627 void GuiPreferences::setColor(ColorCode col, QString const & hex)
3629 colors_.push_back(lcolor.getLyXName(col) + ' ' + fromqstr(hex));
3633 void GuiPreferences::slotFileSelected(QString const file)
3639 QString GuiPreferences::browseLibFile(QString const & dir,
3640 QString const & name, QString const & ext)
3644 guilyxfiles_->passParams(fromqstr(dir));
3645 guilyxfiles_->selectItem(name);
3646 guilyxfiles_->exec();
3648 QString const result = uifile_;
3650 // remove the extension if it is the default one
3651 QString noextresult;
3652 if (getExtension(result) == ext)
3653 noextresult = removeExtension(result);
3655 noextresult = result;
3657 // remove the directory, if it is the default one
3658 QString const file = onlyFileName(noextresult);
3659 if (toqstr(libFileSearch(dir, file, ext).absFileName()) == result)
3666 QString GuiPreferences::browsebind(QString const & file)
3668 return browseLibFile("bind", file, "bind");
3672 QString GuiPreferences::browseUI(QString const & file)
3674 return browseLibFile("ui", file, "ui");
3678 QString GuiPreferences::browsekbmap(QString const & file)
3680 return browseLibFile("kbd", file, "kmap");
3684 QString GuiPreferences::browse(QString const & file,
3685 QString const & title) const
3687 return browseFile(file, title, QStringList(), true);
3691 Dialog * createGuiPreferences(GuiView & lv) { return new GuiPreferences(lv); }
3694 } // namespace frontend
3697 #include "moc_GuiPrefs.cpp"