3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
9 * Full author contact details are available in file CREDITS.
16 #include "ColorCache.h"
17 #include "FileDialog.h"
18 #include "GuiApplication.h"
19 #include "GuiFontExample.h"
20 #include "GuiFontLoader.h"
21 #include "GuiKeySymbol.h"
22 #include "GuiLyXFiles.h"
24 #include "qt_helpers.h"
25 #include "Validator.h"
28 #include "BufferList.h"
31 #include "ConverterCache.h"
32 #include "FontEnums.h"
33 #include "FuncRequest.h"
34 #include "KeySequence.h"
36 #include "LyXAction.h"
38 #include "PanelStack.h"
40 #include "SpellChecker.h"
42 #include "support/debug.h"
43 #include "support/FileName.h"
44 #include "support/filetools.h"
45 #include "support/gettext.h"
46 #include "support/lassert.h"
47 #include "support/lstrings.h"
48 #include "support/Messages.h"
49 #include "support/os.h"
50 #include "support/Package.h"
52 #include "frontends/alert.h"
53 #include "frontends/Application.h"
54 #include "frontends/FontLoader.h"
56 #include <QAbstractItemModel>
58 #include <QColorDialog>
59 #include <QFontDatabase>
60 #include <QHeaderView>
62 #include <QMessageBox>
63 #include <QPushButton>
66 #include <QTreeWidget>
67 #include <QTreeWidgetItem>
78 using namespace lyx::support;
79 using namespace lyx::support::os;
84 /////////////////////////////////////////////////////////////////////
88 /////////////////////////////////////////////////////////////////////
90 /** Launch a file dialog and return the chosen file.
91 filename: a suggested filename.
92 title: the title of the dialog.
94 dir1 = (name, dir), dir2 = (name, dir): extra buttons on the dialog.
96 QString browseFile(QString const & filename,
97 QString const & title,
98 QStringList const & filters,
100 QString const & label1 = QString(),
101 QString const & dir1 = QString(),
102 QString const & label2 = QString(),
103 QString const & dir2 = QString(),
104 QString const & fallback_dir = QString())
106 QString lastPath = ".";
107 if (!filename.isEmpty())
108 lastPath = onlyPath(filename);
109 else if(!fallback_dir.isEmpty())
110 lastPath = fallback_dir;
112 FileDialog dlg(title);
113 dlg.setButton1(label1, dir1);
114 dlg.setButton2(label2, dir2);
116 FileDialog::Result result;
119 result = dlg.save(lastPath, filters, onlyFileName(filename));
121 result = dlg.open(lastPath, filters, onlyFileName(filename));
123 return result.second;
127 /** Launch a file dialog and return the chosen directory.
128 pathname: a suggested pathname.
129 title: the title of the dialog.
130 dir1 = (name, dir), dir2 = (name, dir): extra buttons on the dialog.
132 QString browseDir(QString const & pathname,
133 QString const & title,
134 QString const & label1 = QString(),
135 QString const & dir1 = QString(),
136 QString const & label2 = QString(),
137 QString const & dir2 = QString())
139 QString lastPath = ".";
140 if (!pathname.isEmpty())
141 lastPath = onlyPath(pathname);
143 FileDialog dlg(title);
144 dlg.setButton1(label1, dir1);
145 dlg.setButton2(label2, dir2);
147 FileDialog::Result const result =
148 dlg.opendir(lastPath, onlyFileName(pathname));
150 return result.second;
154 } // namespace frontend
157 QString browseRelToParent(QString const & filename, QString const & relpath,
158 QString const & title, QStringList const & filters, bool save,
159 QString const & label1, QString const & dir1,
160 QString const & label2, QString const & dir2)
162 QString const fname = makeAbsPath(filename, relpath);
164 QString const outname =
165 frontend::browseFile(fname, title, filters, save, label1, dir1, label2, dir2);
167 QString const reloutname =
168 toqstr(makeRelPath(qstring_to_ucs4(outname), qstring_to_ucs4(relpath)));
170 if (reloutname.startsWith("../"))
177 QString browseRelToSub(QString const & filename, QString const & relpath,
178 QString const & title, QStringList const & filters, bool save,
179 QString const & label1, QString const & dir1,
180 QString const & label2, QString const & dir2)
182 QString const fname = makeAbsPath(filename, relpath);
184 QString const outname =
185 frontend::browseFile(fname, title, filters, save, label1, dir1, label2, dir2);
187 QString const reloutname =
188 toqstr(makeRelPath(qstring_to_ucs4(outname), qstring_to_ucs4(relpath)));
190 QString testname = reloutname;
191 testname.remove(QRegExp("^(\\.\\./)+"));
193 if (testname.contains("/"))
201 /////////////////////////////////////////////////////////////////////
205 /////////////////////////////////////////////////////////////////////
209 QString const catLookAndFeel = N_("Look & Feel");
210 QString const catEditing = N_("Editing");
211 QString const catLanguage = N_("Language Settings");
212 QString const catOutput = N_("Output");
213 QString const catFiles = N_("File Handling");
215 static void parseFontName(QString const & mangled0,
216 string & name, string & foundry)
218 string mangled = fromqstr(mangled0);
219 size_t const idx = mangled.find('[');
220 if (idx == string::npos || idx == 0) {
224 name = mangled.substr(0, idx - 1);
225 foundry = mangled.substr(idx + 1, mangled.size() - idx - 2);
230 static void setComboxFont(QComboBox * cb, string const & family,
231 string const & foundry)
233 QString fontname = toqstr(family);
234 if (!foundry.empty())
235 fontname += " [" + toqstr(foundry) + ']';
237 for (int i = 0; i != cb->count(); ++i) {
238 if (cb->itemText(i) == fontname) {
239 cb->setCurrentIndex(i);
244 // Try matching without foundry name
246 // We count in reverse in order to prefer the Xft foundry
247 for (int i = cb->count(); --i >= 0;) {
248 string name, fnt_foundry;
249 parseFontName(cb->itemText(i), name, fnt_foundry);
250 if (compare_ascii_no_case(name, family) == 0) {
251 cb->setCurrentIndex(i);
256 // family alone can contain e.g. "Helvetica [Adobe]"
257 string tmpname, tmpfoundry;
258 parseFontName(toqstr(family), tmpname, tmpfoundry);
260 // We count in reverse in order to prefer the Xft foundry
261 for (int i = cb->count(); --i >= 0; ) {
262 string name, fnt_foundry;
263 parseFontName(cb->itemText(i), name, fnt_foundry);
264 if (compare_ascii_no_case(name, fnt_foundry) == 0) {
265 cb->setCurrentIndex(i);
270 // Bleh, default fonts, and the names couldn't be found. Hack
275 QString const font_family = toqstr(family);
276 if (font_family == guiApp->romanFontName()) {
277 font.setStyleHint(QFont::Serif);
278 font.setFamily(font_family);
279 } else if (font_family == guiApp->sansFontName()) {
280 font.setStyleHint(QFont::SansSerif);
281 font.setFamily(font_family);
282 } else if (font_family == guiApp->typewriterFontName()) {
283 font.setStyleHint(QFont::TypeWriter);
284 font.setFamily(font_family);
286 LYXERR0("FAILED to find the default font: '"
287 << foundry << "', '" << family << '\'');
291 QFontInfo info(font);
292 string default_font_name, dummyfoundry;
293 parseFontName(info.family(), default_font_name, dummyfoundry);
294 LYXERR0("Apparent font is " << default_font_name);
296 for (int i = 0; i < cb->count(); ++i) {
297 LYXERR0("Looking at " << cb->itemText(i));
298 if (compare_ascii_no_case(fromqstr(cb->itemText(i)),
299 default_font_name) == 0) {
300 cb->setCurrentIndex(i);
305 LYXERR0("FAILED to find the font: '"
306 << foundry << "', '" << family << '\'');
310 /////////////////////////////////////////////////////////////////////
314 /////////////////////////////////////////////////////////////////////
316 PrefOutput::PrefOutput(GuiPreferences * form)
317 : PrefModule(catOutput, N_("General[[settings]]"), form)
321 dviCB->setValidator(new NoNewLineValidator(dviCB));
322 pdfCB->setValidator(new NoNewLineValidator(pdfCB));
324 connect(plaintextLinelengthSB, SIGNAL(valueChanged(int)),
325 this, SIGNAL(changed()));
326 connect(overwriteCO, SIGNAL(activated(int)),
327 this, SIGNAL(changed()));
328 connect(dviCB, SIGNAL(editTextChanged(QString)),
329 this, SIGNAL(changed()));
330 connect(pdfCB, SIGNAL(editTextChanged(QString)),
331 this, SIGNAL(changed()));
332 connect(printerPaperTypeED, SIGNAL(textChanged(QString)),
333 this, SIGNAL(changed()));
334 connect(printerLandscapeED, SIGNAL(textChanged(QString)),
335 this, SIGNAL(changed()));
336 connect(printerPaperSizeED, SIGNAL(textChanged(QString)),
337 this, SIGNAL(changed()));
339 printerPaperTypeED->setValidator(new NoNewLineValidator(printerPaperTypeED));
340 printerLandscapeED->setValidator(new NoNewLineValidator(printerLandscapeED));
341 printerPaperSizeED->setValidator(new NoNewLineValidator(printerPaperSizeED));
344 dviCB->addItem("xdvi -sourceposition '$$n:\\ $$t' $$o");
345 dviCB->addItem("yap -1 -s \"$$n $$t\" $$o");
346 dviCB->addItem("okular --unique \"$$o#src:$$n $$f\"");
347 dviCB->addItem("synctex view -i $$n:0:$$t -o $$o -x \"evince -i %{page+1} $$o\"");
349 pdfCB->addItem("CMCDDE SUMATRA control [ForwardSearch(\\\"$$o\\\",\\\"$$t\\\",$$n,0,0,1)]");
350 pdfCB->addItem("SumatraPDF -reuse-instance \"$$o\" -forward-search \"$$t\" $$n");
351 pdfCB->addItem("synctex view -i $$n:0:$$t -o $$o -x \"xpdf -raise -remote $$t.tmp $$o %{page+1}\"");
352 pdfCB->addItem("okular --unique \"$$o#src:$$n $$f\"");
353 pdfCB->addItem("qpdfview --unique \"$$o#src:$$f:$$n:0\"");
354 pdfCB->addItem("synctex view -i $$n:0:$$t -o $$o -x \"evince -i %{page+1} $$o\"");
355 pdfCB->addItem("/Applications/Skim.app/Contents/SharedSupport/displayline $$n $$o $$t");
359 void PrefOutput::applyRC(LyXRC & rc) const
361 rc.plaintext_linelen = plaintextLinelengthSB->value();
362 rc.forward_search_dvi = fromqstr(dviCB->currentText());
363 rc.forward_search_pdf = fromqstr(pdfCB->currentText());
365 switch (overwriteCO->currentIndex()) {
367 rc.export_overwrite = NO_FILES;
370 rc.export_overwrite = MAIN_FILE;
373 rc.export_overwrite = ALL_FILES;
377 rc.print_paper_flag = fromqstr(printerPaperTypeED->text());
378 rc.print_landscape_flag = fromqstr(printerLandscapeED->text());
379 rc.print_paper_dimension_flag = fromqstr(printerPaperSizeED->text());
383 void PrefOutput::updateRC(LyXRC const & rc)
385 plaintextLinelengthSB->setValue(rc.plaintext_linelen);
386 dviCB->setEditText(toqstr(rc.forward_search_dvi));
387 pdfCB->setEditText(toqstr(rc.forward_search_pdf));
389 switch (rc.export_overwrite) {
391 overwriteCO->setCurrentIndex(0);
394 overwriteCO->setCurrentIndex(1);
397 overwriteCO->setCurrentIndex(2);
401 printerPaperTypeED->setText(toqstr(rc.print_paper_flag));
402 printerLandscapeED->setText(toqstr(rc.print_landscape_flag));
403 printerPaperSizeED->setText(toqstr(rc.print_paper_dimension_flag));
407 /////////////////////////////////////////////////////////////////////
411 /////////////////////////////////////////////////////////////////////
413 PrefInput::PrefInput(GuiPreferences * form)
414 : PrefModule(catEditing, N_("Keyboard/Mouse"), form)
418 connect(keymapCB, SIGNAL(clicked()),
419 this, SIGNAL(changed()));
420 connect(firstKeymapED, SIGNAL(textChanged(QString)),
421 this, SIGNAL(changed()));
422 connect(secondKeymapED, SIGNAL(textChanged(QString)),
423 this, SIGNAL(changed()));
424 connect(mouseWheelSpeedSB, SIGNAL(valueChanged(double)),
425 this, SIGNAL(changed()));
426 connect(scrollzoomEnableCB, SIGNAL(clicked()),
427 this, SIGNAL(changed()));
428 connect(scrollzoomValueCO, SIGNAL(activated(int)),
429 this, SIGNAL(changed()));
430 connect(dontswapCB, SIGNAL(toggled(bool)),
431 this, SIGNAL(changed()));
432 connect(mmPasteCB, SIGNAL(toggled(bool)),
433 this, SIGNAL(changed()));
435 // reveal checkbox for switching Ctrl and Meta on Mac:
438 #if QT_VERSION > 0x040600
442 dontswapCB->setVisible(swapcb);
446 void PrefInput::applyRC(LyXRC & rc) const
448 // FIXME: can derive CB from the two EDs
449 rc.use_kbmap = keymapCB->isChecked();
450 rc.primary_kbmap = internal_path(fromqstr(firstKeymapED->text()));
451 rc.secondary_kbmap = internal_path(fromqstr(secondKeymapED->text()));
452 rc.mouse_wheel_speed = mouseWheelSpeedSB->value();
453 if (scrollzoomEnableCB->isChecked()) {
454 switch (scrollzoomValueCO->currentIndex()) {
456 rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_CTRL;
459 rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_SHIFT;
462 rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_ALT;
466 rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_OFF;
468 rc.mac_dontswap_ctrl_meta = dontswapCB->isChecked();
469 rc.mouse_middlebutton_paste = mmPasteCB->isChecked();
473 void PrefInput::updateRC(LyXRC const & rc)
475 // FIXME: can derive CB from the two EDs
476 keymapCB->setChecked(rc.use_kbmap);
477 firstKeymapED->setText(toqstr(external_path(rc.primary_kbmap)));
478 secondKeymapED->setText(toqstr(external_path(rc.secondary_kbmap)));
479 mouseWheelSpeedSB->setValue(rc.mouse_wheel_speed);
480 switch (rc.scroll_wheel_zoom) {
481 case LyXRC::SCROLL_WHEEL_ZOOM_OFF:
482 scrollzoomEnableCB->setChecked(false);
484 case LyXRC::SCROLL_WHEEL_ZOOM_CTRL:
485 scrollzoomEnableCB->setChecked(true);
486 scrollzoomValueCO->setCurrentIndex(0);
488 case LyXRC::SCROLL_WHEEL_ZOOM_SHIFT:
489 scrollzoomEnableCB->setChecked(true);
490 scrollzoomValueCO->setCurrentIndex(1);
492 case LyXRC::SCROLL_WHEEL_ZOOM_ALT:
493 scrollzoomEnableCB->setChecked(true);
494 scrollzoomValueCO->setCurrentIndex(2);
497 dontswapCB->setChecked(rc.mac_dontswap_ctrl_meta);
498 mmPasteCB->setChecked(rc.mouse_middlebutton_paste);
502 QString PrefInput::testKeymap(QString const & keymap)
504 return form_->browsekbmap(internalPath(keymap));
508 void PrefInput::on_firstKeymapPB_clicked(bool)
510 QString const file = testKeymap(firstKeymapED->text());
512 firstKeymapED->setText(file);
516 void PrefInput::on_secondKeymapPB_clicked(bool)
518 QString const file = testKeymap(secondKeymapED->text());
520 secondKeymapED->setText(file);
524 void PrefInput::on_keymapCB_toggled(bool keymap)
526 firstKeymapLA->setEnabled(keymap);
527 secondKeymapLA->setEnabled(keymap);
528 firstKeymapED->setEnabled(keymap);
529 secondKeymapED->setEnabled(keymap);
530 firstKeymapPB->setEnabled(keymap);
531 secondKeymapPB->setEnabled(keymap);
535 void PrefInput::on_scrollzoomEnableCB_toggled(bool enabled)
537 scrollzoomValueCO->setEnabled(enabled);
541 /////////////////////////////////////////////////////////////////////
545 /////////////////////////////////////////////////////////////////////
547 PrefCompletion::PrefCompletion(GuiPreferences * form)
548 : PrefModule(catEditing, N_("Input Completion"), form)
552 connect(inlineDelaySB, SIGNAL(valueChanged(double)),
553 this, SIGNAL(changed()));
554 connect(inlineMathCB, SIGNAL(clicked()),
555 this, SIGNAL(changed()));
556 connect(inlineTextCB, SIGNAL(clicked()),
557 this, SIGNAL(changed()));
558 connect(inlineDotsCB, SIGNAL(clicked()),
559 this, SIGNAL(changed()));
560 connect(popupDelaySB, SIGNAL(valueChanged(double)),
561 this, SIGNAL(changed()));
562 connect(popupMathCB, SIGNAL(clicked()),
563 this, SIGNAL(changed()));
564 connect(autocorrectionCB, SIGNAL(clicked()),
565 this, SIGNAL(changed()));
566 connect(popupTextCB, SIGNAL(clicked()),
567 this, SIGNAL(changed()));
568 connect(popupAfterCompleteCB, SIGNAL(clicked()),
569 this, SIGNAL(changed()));
570 connect(cursorTextCB, SIGNAL(clicked()),
571 this, SIGNAL(changed()));
572 connect(minlengthSB, SIGNAL(valueChanged(int)),
573 this, SIGNAL(changed()));
577 void PrefCompletion::on_inlineTextCB_clicked()
583 void PrefCompletion::on_popupTextCB_clicked()
589 void PrefCompletion::enableCB()
591 cursorTextCB->setEnabled(
592 popupTextCB->isChecked() || inlineTextCB->isChecked());
596 void PrefCompletion::applyRC(LyXRC & rc) const
598 rc.completion_inline_delay = inlineDelaySB->value();
599 rc.completion_inline_math = inlineMathCB->isChecked();
600 rc.completion_inline_text = inlineTextCB->isChecked();
601 rc.completion_inline_dots = inlineDotsCB->isChecked() ? 13 : -1;
602 rc.completion_popup_delay = popupDelaySB->value();
603 rc.completion_popup_math = popupMathCB->isChecked();
604 rc.autocorrection_math = autocorrectionCB->isChecked();
605 rc.completion_popup_text = popupTextCB->isChecked();
606 rc.completion_cursor_text = cursorTextCB->isChecked();
607 rc.completion_popup_after_complete =
608 popupAfterCompleteCB->isChecked();
609 rc.completion_minlength = minlengthSB->value();
613 void PrefCompletion::updateRC(LyXRC const & rc)
615 inlineDelaySB->setValue(rc.completion_inline_delay);
616 inlineMathCB->setChecked(rc.completion_inline_math);
617 inlineTextCB->setChecked(rc.completion_inline_text);
618 inlineDotsCB->setChecked(rc.completion_inline_dots != -1);
619 popupDelaySB->setValue(rc.completion_popup_delay);
620 popupMathCB->setChecked(rc.completion_popup_math);
621 autocorrectionCB->setChecked(rc.autocorrection_math);
622 popupTextCB->setChecked(rc.completion_popup_text);
623 cursorTextCB->setChecked(rc.completion_cursor_text);
624 popupAfterCompleteCB->setChecked(rc.completion_popup_after_complete);
626 minlengthSB->setValue(rc.completion_minlength);
631 /////////////////////////////////////////////////////////////////////
635 /////////////////////////////////////////////////////////////////////
637 PrefLatex::PrefLatex(GuiPreferences * form)
638 : PrefModule(catOutput, N_("LaTeX"), form)
642 latexDviPaperED->setValidator(new NoNewLineValidator(latexDviPaperED));
643 latexBibtexED->setValidator(new NoNewLineValidator(latexBibtexED));
644 latexJBibtexED->setValidator(new NoNewLineValidator(latexJBibtexED));
645 latexIndexED->setValidator(new NoNewLineValidator(latexIndexED));
646 latexJIndexED->setValidator(new NoNewLineValidator(latexJIndexED));
647 latexNomenclED->setValidator(new NoNewLineValidator(latexNomenclED));
648 latexChecktexED->setValidator(new NoNewLineValidator(latexChecktexED));
650 connect(latexChecktexED, SIGNAL(textChanged(QString)),
651 this, SIGNAL(changed()));
652 connect(latexBibtexCO, SIGNAL(activated(int)),
653 this, SIGNAL(changed()));
654 connect(latexBibtexED, SIGNAL(textChanged(QString)),
655 this, SIGNAL(changed()));
656 connect(latexJBibtexCO, SIGNAL(activated(int)),
657 this, SIGNAL(changed()));
658 connect(latexJBibtexED, SIGNAL(textChanged(QString)),
659 this, SIGNAL(changed()));
660 connect(latexIndexCO, SIGNAL(activated(int)),
661 this, SIGNAL(changed()));
662 connect(latexIndexED, SIGNAL(textChanged(QString)),
663 this, SIGNAL(changed()));
664 connect(latexJIndexED, SIGNAL(textChanged(QString)),
665 this, SIGNAL(changed()));
666 connect(latexAutoresetCB, SIGNAL(clicked()),
667 this, SIGNAL(changed()));
668 connect(latexDviPaperED, SIGNAL(textChanged(QString)),
669 this, SIGNAL(changed()));
670 connect(latexNomenclED, SIGNAL(textChanged(QString)),
671 this, SIGNAL(changed()));
673 #if defined(__CYGWIN__) || defined(_WIN32)
674 pathCB->setVisible(true);
675 connect(pathCB, SIGNAL(clicked()),
676 this, SIGNAL(changed()));
678 pathCB->setVisible(false);
683 void PrefLatex::on_latexBibtexCO_activated(int n)
685 QString const bibtex = latexBibtexCO->itemData(n).toString();
686 if (bibtex.isEmpty()) {
687 latexBibtexED->clear();
688 latexBibtexOptionsLA->setText(qt_("C&ommand:"));
691 for (LyXRC::CommandSet::const_iterator it = bibtex_alternatives.begin();
692 it != bibtex_alternatives.end(); ++it) {
693 QString const bib = toqstr(*it);
694 int ind = bib.indexOf(" ");
695 QString sel_command = bib.left(ind);
696 QString sel_options = ind < 0 ? QString() : bib.mid(ind + 1);
697 if (bibtex == sel_command) {
699 latexBibtexED->clear();
701 latexBibtexED->setText(sel_options.trimmed());
704 latexBibtexOptionsLA->setText(qt_("&Options:"));
708 void PrefLatex::on_latexJBibtexCO_activated(int n)
710 QString const jbibtex = latexJBibtexCO->itemData(n).toString();
711 if (jbibtex.isEmpty()) {
712 latexJBibtexED->clear();
713 latexJBibtexOptionsLA->setText(qt_("Co&mmand:"));
716 for (LyXRC::CommandSet::const_iterator it = jbibtex_alternatives.begin();
717 it != jbibtex_alternatives.end(); ++it) {
718 QString const bib = toqstr(*it);
719 int ind = bib.indexOf(" ");
720 QString sel_command = bib.left(ind);
721 QString sel_options = ind < 0 ? QString() : bib.mid(ind + 1);
722 if (jbibtex == sel_command) {
724 latexJBibtexED->clear();
726 latexJBibtexED->setText(sel_options.trimmed());
729 latexJBibtexOptionsLA->setText(qt_("Opt&ions:"));
733 void PrefLatex::on_latexIndexCO_activated(int n)
735 QString const index = latexIndexCO->itemData(n).toString();
736 if (index.isEmpty()) {
737 latexIndexED->clear();
738 latexIndexOptionsLA->setText(qt_("Co&mmand:"));
741 for (LyXRC::CommandSet::const_iterator it = index_alternatives.begin();
742 it != index_alternatives.end(); ++it) {
743 QString const idx = toqstr(*it);
744 int ind = idx.indexOf(" ");
745 QString sel_command = idx.left(ind);
746 QString sel_options = ind < 0 ? QString() : idx.mid(ind + 1);
747 if (index == sel_command) {
749 latexIndexED->clear();
751 latexIndexED->setText(sel_options.trimmed());
754 latexIndexOptionsLA->setText(qt_("Op&tions:"));
758 void PrefLatex::applyRC(LyXRC & rc) const
760 // If bibtex is not empty, bibopt contains the options, otherwise
761 // it is a customized bibtex command with options.
762 QString const bibtex = latexBibtexCO->itemData(
763 latexBibtexCO->currentIndex()).toString();
764 QString const bibopt = latexBibtexED->text();
765 if (bibtex.isEmpty())
766 rc.bibtex_command = fromqstr(bibopt);
767 else if (bibopt.isEmpty())
768 rc.bibtex_command = fromqstr(bibtex);
770 rc.bibtex_command = fromqstr(bibtex) + " " + fromqstr(bibopt);
772 // If jbibtex is not empty, jbibopt contains the options, otherwise
773 // it is a customized bibtex command with options.
774 QString const jbibtex = latexJBibtexCO->itemData(
775 latexJBibtexCO->currentIndex()).toString();
776 QString const jbibopt = latexJBibtexED->text();
777 if (jbibtex.isEmpty())
778 rc.jbibtex_command = fromqstr(jbibopt);
779 else if (jbibopt.isEmpty())
780 rc.jbibtex_command = fromqstr(jbibtex);
782 rc.jbibtex_command = fromqstr(jbibtex) + " " + fromqstr(jbibopt);
784 // If index is not empty, idxopt contains the options, otherwise
785 // it is a customized index command with options.
786 QString const index = latexIndexCO->itemData(
787 latexIndexCO->currentIndex()).toString();
788 QString const idxopt = latexIndexED->text();
790 rc.index_command = fromqstr(idxopt);
791 else if (idxopt.isEmpty())
792 rc.index_command = fromqstr(index);
794 rc.index_command = fromqstr(index) + " " + fromqstr(idxopt);
796 rc.chktex_command = fromqstr(latexChecktexED->text());
797 rc.jindex_command = fromqstr(latexJIndexED->text());
798 rc.nomencl_command = fromqstr(latexNomenclED->text());
799 rc.auto_reset_options = latexAutoresetCB->isChecked();
800 rc.view_dvi_paper_option = fromqstr(latexDviPaperED->text());
801 #if defined(__CYGWIN__) || defined(_WIN32)
802 rc.windows_style_tex_paths = pathCB->isChecked();
807 void PrefLatex::updateRC(LyXRC const & rc)
809 latexBibtexCO->clear();
811 latexBibtexCO->addItem(qt_("Automatic"), "automatic");
812 latexBibtexCO->addItem(qt_("Custom"), QString());
813 for (LyXRC::CommandSet::const_iterator it = rc.bibtex_alternatives.begin();
814 it != rc.bibtex_alternatives.end(); ++it) {
815 QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
816 latexBibtexCO->addItem(command, command);
819 bibtex_alternatives = rc.bibtex_alternatives;
821 QString const bib = toqstr(rc.bibtex_command);
822 int ind = bib.indexOf(" ");
823 QString sel_command = bib.left(ind);
824 QString sel_options = ind < 0 ? QString() : bib.mid(ind + 1);
826 int pos = latexBibtexCO->findData(sel_command);
828 latexBibtexCO->setCurrentIndex(pos);
829 latexBibtexED->setText(sel_options.trimmed());
830 latexBibtexOptionsLA->setText(qt_("&Options:"));
832 latexBibtexED->setText(toqstr(rc.bibtex_command));
833 latexBibtexCO->setCurrentIndex(0);
834 latexBibtexOptionsLA->setText(qt_("C&ommand:"));
837 latexJBibtexCO->clear();
839 latexJBibtexCO->addItem(qt_("Automatic"), "automatic");
840 latexJBibtexCO->addItem(qt_("Custom"), QString());
841 for (LyXRC::CommandSet::const_iterator it = rc.jbibtex_alternatives.begin();
842 it != rc.jbibtex_alternatives.end(); ++it) {
843 QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
844 latexJBibtexCO->addItem(command, command);
847 jbibtex_alternatives = rc.jbibtex_alternatives;
849 QString const jbib = toqstr(rc.jbibtex_command);
850 ind = jbib.indexOf(" ");
851 sel_command = jbib.left(ind);
852 sel_options = ind < 0 ? QString() : jbib.mid(ind + 1);
854 pos = latexJBibtexCO->findData(sel_command);
856 latexJBibtexCO->setCurrentIndex(pos);
857 latexJBibtexED->setText(sel_options.trimmed());
858 latexJBibtexOptionsLA->setText(qt_("Opt&ions:"));
860 latexJBibtexED->setText(toqstr(rc.bibtex_command));
861 latexJBibtexCO->setCurrentIndex(0);
862 latexJBibtexOptionsLA->setText(qt_("Co&mmand:"));
865 latexIndexCO->clear();
867 latexIndexCO->addItem(qt_("Custom"), QString());
868 for (LyXRC::CommandSet::const_iterator it = rc.index_alternatives.begin();
869 it != rc.index_alternatives.end(); ++it) {
870 QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
871 latexIndexCO->addItem(command, command);
874 index_alternatives = rc.index_alternatives;
876 QString const idx = toqstr(rc.index_command);
877 ind = idx.indexOf(" ");
878 sel_command = idx.left(ind);
879 sel_options = ind < 0 ? QString() : idx.mid(ind + 1);
881 pos = latexIndexCO->findData(sel_command);
883 latexIndexCO->setCurrentIndex(pos);
884 latexIndexED->setText(sel_options.trimmed());
885 latexIndexOptionsLA->setText(qt_("Op&tions:"));
887 latexIndexED->setText(toqstr(rc.index_command));
888 latexIndexCO->setCurrentIndex(0);
889 latexIndexOptionsLA->setText(qt_("Co&mmand:"));
892 latexChecktexED->setText(toqstr(rc.chktex_command));
893 latexJIndexED->setText(toqstr(rc.jindex_command));
894 latexNomenclED->setText(toqstr(rc.nomencl_command));
895 latexAutoresetCB->setChecked(rc.auto_reset_options);
896 latexDviPaperED->setText(toqstr(rc.view_dvi_paper_option));
897 #if defined(__CYGWIN__) || defined(_WIN32)
898 pathCB->setChecked(rc.windows_style_tex_paths);
903 /////////////////////////////////////////////////////////////////////
907 /////////////////////////////////////////////////////////////////////
909 PrefScreenFonts::PrefScreenFonts(GuiPreferences * form)
910 : PrefModule(catLookAndFeel, N_("Screen Fonts"), form)
914 connect(screenRomanCO, SIGNAL(activated(QString)),
915 this, SLOT(selectRoman(QString)));
916 connect(screenSansCO, SIGNAL(activated(QString)),
917 this, SLOT(selectSans(QString)));
918 connect(screenTypewriterCO, SIGNAL(activated(QString)),
919 this, SLOT(selectTypewriter(QString)));
921 QFontDatabase fontdb;
922 QStringList families(fontdb.families());
923 for (auto const & family : families) {
924 screenRomanCO->addItem(family);
925 screenSansCO->addItem(family);
926 screenTypewriterCO->addItem(family);
928 connect(screenRomanCO, SIGNAL(activated(QString)),
929 this, SIGNAL(changed()));
930 connect(screenSansCO, SIGNAL(activated(QString)),
931 this, SIGNAL(changed()));
932 connect(screenTypewriterCO, SIGNAL(activated(QString)),
933 this, SIGNAL(changed()));
934 connect(screenZoomSB, SIGNAL(valueChanged(int)),
935 this, SIGNAL(changed()));
936 connect(screenTinyED, SIGNAL(textChanged(QString)),
937 this, SIGNAL(changed()));
938 connect(screenSmallestED, SIGNAL(textChanged(QString)),
939 this, SIGNAL(changed()));
940 connect(screenSmallerED, SIGNAL(textChanged(QString)),
941 this, SIGNAL(changed()));
942 connect(screenSmallED, SIGNAL(textChanged(QString)),
943 this, SIGNAL(changed()));
944 connect(screenNormalED, SIGNAL(textChanged(QString)),
945 this, SIGNAL(changed()));
946 connect(screenLargeED, SIGNAL(textChanged(QString)),
947 this, SIGNAL(changed()));
948 connect(screenLargerED, SIGNAL(textChanged(QString)),
949 this, SIGNAL(changed()));
950 connect(screenLargestED, SIGNAL(textChanged(QString)),
951 this, SIGNAL(changed()));
952 connect(screenHugeED, SIGNAL(textChanged(QString)),
953 this, SIGNAL(changed()));
954 connect(screenHugerED, SIGNAL(textChanged(QString)),
955 this, SIGNAL(changed()));
957 screenTinyED->setValidator(new QDoubleValidator(screenTinyED));
958 screenSmallestED->setValidator(new QDoubleValidator(screenSmallestED));
959 screenSmallerED->setValidator(new QDoubleValidator(screenSmallerED));
960 screenSmallED->setValidator(new QDoubleValidator(screenSmallED));
961 screenNormalED->setValidator(new QDoubleValidator(screenNormalED));
962 screenLargeED->setValidator(new QDoubleValidator(screenLargeED));
963 screenLargerED->setValidator(new QDoubleValidator(screenLargerED));
964 screenLargestED->setValidator(new QDoubleValidator(screenLargestED));
965 screenHugeED->setValidator(new QDoubleValidator(screenHugeED));
966 screenHugerED->setValidator(new QDoubleValidator(screenHugerED));
970 void PrefScreenFonts::applyRC(LyXRC & rc) const
972 LyXRC const oldrc = rc;
974 parseFontName(screenRomanCO->currentText(),
975 rc.roman_font_name, rc.roman_font_foundry);
976 parseFontName(screenSansCO->currentText(),
977 rc.sans_font_name, rc.sans_font_foundry);
978 parseFontName(screenTypewriterCO->currentText(),
979 rc.typewriter_font_name, rc.typewriter_font_foundry);
981 rc.defaultZoom = screenZoomSB->value();
982 rc.font_sizes[TINY_SIZE] = widgetToDoubleStr(screenTinyED);
983 rc.font_sizes[SCRIPT_SIZE] = widgetToDoubleStr(screenSmallestED);
984 rc.font_sizes[FOOTNOTE_SIZE] = widgetToDoubleStr(screenSmallerED);
985 rc.font_sizes[SMALL_SIZE] = widgetToDoubleStr(screenSmallED);
986 rc.font_sizes[NORMAL_SIZE] = widgetToDoubleStr(screenNormalED);
987 rc.font_sizes[LARGE_SIZE] = widgetToDoubleStr(screenLargeED);
988 rc.font_sizes[LARGER_SIZE] = widgetToDoubleStr(screenLargerED);
989 rc.font_sizes[LARGEST_SIZE] = widgetToDoubleStr(screenLargestED);
990 rc.font_sizes[HUGE_SIZE] = widgetToDoubleStr(screenHugeED);
991 rc.font_sizes[HUGER_SIZE] = widgetToDoubleStr(screenHugerED);
995 void PrefScreenFonts::updateRC(LyXRC const & rc)
997 setComboxFont(screenRomanCO, rc.roman_font_name,
998 rc.roman_font_foundry);
999 setComboxFont(screenSansCO, rc.sans_font_name,
1000 rc.sans_font_foundry);
1001 setComboxFont(screenTypewriterCO, rc.typewriter_font_name,
1002 rc.typewriter_font_foundry);
1004 selectRoman(screenRomanCO->currentText());
1005 selectSans(screenSansCO->currentText());
1006 selectTypewriter(screenTypewriterCO->currentText());
1008 screenZoomSB->setValue(rc.defaultZoom);
1009 updateScreenFontSizes(rc);
1013 void PrefScreenFonts::updateScreenFontSizes(LyXRC const & rc)
1015 doubleToWidget(screenTinyED, rc.font_sizes[TINY_SIZE]);
1016 doubleToWidget(screenSmallestED, rc.font_sizes[SCRIPT_SIZE]);
1017 doubleToWidget(screenSmallerED, rc.font_sizes[FOOTNOTE_SIZE]);
1018 doubleToWidget(screenSmallED, rc.font_sizes[SMALL_SIZE]);
1019 doubleToWidget(screenNormalED, rc.font_sizes[NORMAL_SIZE]);
1020 doubleToWidget(screenLargeED, rc.font_sizes[LARGE_SIZE]);
1021 doubleToWidget(screenLargerED, rc.font_sizes[LARGER_SIZE]);
1022 doubleToWidget(screenLargestED, rc.font_sizes[LARGEST_SIZE]);
1023 doubleToWidget(screenHugeED, rc.font_sizes[HUGE_SIZE]);
1024 doubleToWidget(screenHugerED, rc.font_sizes[HUGER_SIZE]);
1028 void PrefScreenFonts::selectRoman(const QString & name)
1030 screenRomanFE->set(QFont(name), name);
1034 void PrefScreenFonts::selectSans(const QString & name)
1036 screenSansFE->set(QFont(name), name);
1040 void PrefScreenFonts::selectTypewriter(const QString & name)
1042 screenTypewriterFE->set(QFont(name), name);
1046 /////////////////////////////////////////////////////////////////////
1050 /////////////////////////////////////////////////////////////////////
1053 PrefColors::PrefColors(GuiPreferences * form)
1054 : PrefModule(catLookAndFeel, N_("Colors"), form)
1058 // FIXME: all of this initialization should be put into the controller.
1059 // See http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg113301.html
1060 // for some discussion of why that is not trivial.
1061 QPixmap icon(32, 32);
1062 for (int i = 0; i < Color_ignore; ++i) {
1063 ColorCode lc = static_cast<ColorCode>(i);
1064 if (lc == Color_none
1065 || lc == Color_black
1066 || lc == Color_white
1068 || lc == Color_brown
1070 || lc == Color_darkgray
1072 || lc == Color_green
1073 || lc == Color_lightgray
1075 || lc == Color_magenta
1076 || lc == Color_olive
1077 || lc == Color_orange
1079 || lc == Color_purple
1082 || lc == Color_violet
1083 || lc == Color_yellow
1084 || lc == Color_inherit
1085 || lc == Color_ignore)
1087 lcolors_.push_back(lc);
1089 sort(lcolors_.begin(), lcolors_.end(), ColorSorter);
1090 vector<ColorCode>::const_iterator cit = lcolors_.begin();
1091 vector<ColorCode>::const_iterator const end = lcolors_.end();
1092 for (; cit != end; ++cit) {
1093 (void) new QListWidgetItem(QIcon(icon),
1094 toqstr(lcolor.getGUIName(*cit)), lyxObjectsLW);
1096 curcolors_.resize(lcolors_.size());
1097 newcolors_.resize(lcolors_.size());
1098 // End initialization
1100 connect(colorChangePB, SIGNAL(clicked()),
1101 this, SLOT(changeColor()));
1102 connect(colorResetPB, SIGNAL(clicked()),
1103 this, SLOT(resetColor()));
1104 connect(colorResetAllPB, SIGNAL(clicked()),
1105 this, SLOT(resetAllColor()));
1106 connect(lyxObjectsLW, SIGNAL(itemSelectionChanged()),
1107 this, SLOT(changeLyxObjectsSelection()));
1108 connect(lyxObjectsLW, SIGNAL(itemActivated(QListWidgetItem*)),
1109 this, SLOT(changeColor()));
1110 connect(syscolorsCB, SIGNAL(toggled(bool)),
1111 this, SIGNAL(changed()));
1112 connect(syscolorsCB, SIGNAL(toggled(bool)),
1113 this, SLOT(changeSysColor()));
1117 void PrefColors::applyRC(LyXRC & rc) const
1121 for (unsigned int i = 0; i < lcolors_.size(); ++i)
1122 if (curcolors_[i] != newcolors_[i])
1123 form_->setColor(lcolors_[i], newcolors_[i]);
1124 rc.use_system_colors = syscolorsCB->isChecked();
1126 if (oldrc.use_system_colors != rc.use_system_colors)
1127 guiApp->colorCache().clear();
1131 void PrefColors::updateRC(LyXRC const & rc)
1133 for (size_type i = 0; i < lcolors_.size(); ++i) {
1134 QColor color = QColor(guiApp->colorCache().get(lcolors_[i], false));
1135 QPixmap coloritem(32, 32);
1136 coloritem.fill(color);
1137 lyxObjectsLW->item(int(i))->setIcon(QIcon(coloritem));
1138 newcolors_[i] = curcolors_[i] = color.name();
1140 syscolorsCB->setChecked(rc.use_system_colors);
1141 changeLyxObjectsSelection();
1143 setDisabledResets();
1147 void PrefColors::changeColor()
1149 int const row = lyxObjectsLW->currentRow();
1155 QString const color = newcolors_[size_t(row)];
1156 QColor const c = QColorDialog::getColor(QColor(color), qApp->focusWidget());
1158 if (setColor(row, c, color)) {
1159 setDisabledResets();
1166 void PrefColors::resetColor()
1168 int const row = lyxObjectsLW->currentRow();
1174 QString const color = newcolors_[size_t(row)];
1175 QColor const c = getDefaultColorByRow(row);
1177 if (setColor(row, c, color)) {
1178 setDisabledResets();
1185 void PrefColors::resetAllColor()
1187 bool isChanged = false;
1189 colorResetAllPB->setDisabled(true);
1191 for (int irow = 0, count = lyxObjectsLW->count(); irow < count; ++irow) {
1192 QString const color = newcolors_[size_t(irow)];
1193 QColor const c = getDefaultColorByRow(irow);
1195 if (setColor(irow, c, color))
1200 setDisabledResets();
1207 bool PrefColors::setColor(int const row, QColor const & new_color,
1208 QString const & old_color)
1210 if (new_color.isValid() && new_color.name() != old_color) {
1211 newcolors_[size_t(row)] = new_color.name();
1212 QPixmap coloritem(32, 32);
1213 coloritem.fill(new_color);
1214 lyxObjectsLW->item(row)->setIcon(QIcon(coloritem));
1221 void PrefColors::setDisabledResets()
1223 int const row = lyxObjectsLW->currentRow();
1224 // set disable reset buttons ...
1226 colorResetPB->setDisabled(isDefaultColor(row, newcolors_[size_t(row)]));
1228 colorResetAllPB->setDisabled(true);
1230 // ... in between process qt events to give quicker visual feedback to the user ...
1231 guiApp->processEvents();
1233 // ... set disable Reset All button
1234 for (int irow = 0, count = lyxObjectsLW->count(); irow < count; ++irow) {
1235 if (!isDefaultColor(irow, newcolors_[size_t(irow)])) {
1236 colorResetAllPB->setDisabled(false);
1237 // the break condition might hide performance issues
1238 // if a non-default color is at the top of the list
1245 bool PrefColors::isDefaultColor(int const row, QString const & color)
1247 return color == getDefaultColorByRow(row).name();
1251 QColor PrefColors::getDefaultColorByRow(int const row)
1253 ColorSet const defaultcolor;
1254 return defaultcolor.getX11HexName(lcolors_[size_t(row)],
1255 guiApp->colorCache().isDarkMode()).c_str();
1259 void PrefColors::changeSysColor()
1261 for (int row = 0 ; row < lyxObjectsLW->count() ; ++row) {
1262 // skip colors that are taken from system palette
1263 bool const disable = syscolorsCB->isChecked()
1264 && guiApp->colorCache().isSystem(lcolors_[size_t(row)]);
1266 QListWidgetItem * const item = lyxObjectsLW->item(row);
1267 Qt::ItemFlags const flags = item->flags();
1270 item->setFlags(flags & ~Qt::ItemIsEnabled);
1272 item->setFlags(flags | Qt::ItemIsEnabled);
1277 void PrefColors::changeLyxObjectsSelection()
1279 int currentRow = lyxObjectsLW->currentRow();
1280 colorChangePB->setDisabled(currentRow < 0);
1283 colorResetPB->setDisabled(true);
1285 colorResetPB->setDisabled(
1286 isDefaultColor(currentRow, newcolors_[size_t(currentRow)]));
1290 /////////////////////////////////////////////////////////////////////
1294 /////////////////////////////////////////////////////////////////////
1296 PrefDisplay::PrefDisplay(GuiPreferences * form)
1297 : PrefModule(catLookAndFeel, N_("Display"), form)
1300 connect(displayGraphicsCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1301 connect(instantPreviewCO, SIGNAL(activated(int)), this, SIGNAL(changed()));
1302 connect(previewSizeSB, SIGNAL(valueChanged(double)), this, SIGNAL(changed()));
1303 connect(paragraphMarkerCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1304 connect(ctAdditionsUnderlinedCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1308 void PrefDisplay::on_instantPreviewCO_currentIndexChanged(int index)
1310 previewSizeSB->setEnabled(index != 0);
1314 void PrefDisplay::applyRC(LyXRC & rc) const
1316 switch (instantPreviewCO->currentIndex()) {
1318 rc.preview = LyXRC::PREVIEW_OFF;
1321 rc.preview = LyXRC::PREVIEW_NO_MATH;
1324 rc.preview = LyXRC::PREVIEW_ON;
1328 rc.display_graphics = displayGraphicsCB->isChecked();
1329 rc.preview_scale_factor = previewSizeSB->value();
1330 rc.paragraph_markers = paragraphMarkerCB->isChecked();
1331 rc.ct_additions_underlined = ctAdditionsUnderlinedCB->isChecked();
1333 // FIXME!! The graphics cache no longer has a changeDisplay method.
1335 if (old_value != rc.display_graphics) {
1336 graphics::GCache & gc = graphics::GCache::get();
1343 void PrefDisplay::updateRC(LyXRC const & rc)
1345 switch (rc.preview) {
1346 case LyXRC::PREVIEW_OFF:
1347 instantPreviewCO->setCurrentIndex(0);
1349 case LyXRC::PREVIEW_NO_MATH :
1350 instantPreviewCO->setCurrentIndex(1);
1352 case LyXRC::PREVIEW_ON :
1353 instantPreviewCO->setCurrentIndex(2);
1357 displayGraphicsCB->setChecked(rc.display_graphics);
1358 previewSizeSB->setValue(rc.preview_scale_factor);
1359 paragraphMarkerCB->setChecked(rc.paragraph_markers);
1360 ctAdditionsUnderlinedCB->setChecked(rc.ct_additions_underlined);
1361 previewSizeSB->setEnabled(
1363 && rc.preview != LyXRC::PREVIEW_OFF);
1367 /////////////////////////////////////////////////////////////////////
1371 /////////////////////////////////////////////////////////////////////
1373 PrefPaths::PrefPaths(GuiPreferences * form)
1374 : PrefModule(QString(), N_("Paths"), form)
1378 connect(workingDirPB, SIGNAL(clicked()), this, SLOT(selectWorkingdir()));
1379 connect(workingDirED, SIGNAL(textChanged(QString)),
1380 this, SIGNAL(changed()));
1382 connect(templateDirPB, SIGNAL(clicked()), this, SLOT(selectTemplatedir()));
1383 connect(templateDirED, SIGNAL(textChanged(QString)),
1384 this, SIGNAL(changed()));
1386 connect(exampleDirPB, SIGNAL(clicked()), this, SLOT(selectExampledir()));
1387 connect(exampleDirED, SIGNAL(textChanged(QString)),
1388 this, SIGNAL(changed()));
1390 connect(backupDirPB, SIGNAL(clicked()), this, SLOT(selectBackupdir()));
1391 connect(backupDirED, SIGNAL(textChanged(QString)),
1392 this, SIGNAL(changed()));
1394 connect(lyxserverDirPB, SIGNAL(clicked()), this, SLOT(selectLyxPipe()));
1395 connect(lyxserverDirED, SIGNAL(textChanged(QString)),
1396 this, SIGNAL(changed()));
1398 connect(thesaurusDirPB, SIGNAL(clicked()), this, SLOT(selectThesaurusdir()));
1399 connect(thesaurusDirED, SIGNAL(textChanged(QString)),
1400 this, SIGNAL(changed()));
1402 connect(tempDirPB, SIGNAL(clicked()), this, SLOT(selectTempdir()));
1403 connect(tempDirED, SIGNAL(textChanged(QString)),
1404 this, SIGNAL(changed()));
1406 #if defined(USE_HUNSPELL)
1407 connect(hunspellDirPB, SIGNAL(clicked()), this, SLOT(selectHunspelldir()));
1408 connect(hunspellDirED, SIGNAL(textChanged(QString)),
1409 this, SIGNAL(changed()));
1411 hunspellDirPB->setEnabled(false);
1412 hunspellDirED->setEnabled(false);
1415 connect(pathPrefixED, SIGNAL(textChanged(QString)),
1416 this, SIGNAL(changed()));
1418 connect(texinputsPrefixED, SIGNAL(textChanged(QString)),
1419 this, SIGNAL(changed()));
1421 pathPrefixED->setValidator(new NoNewLineValidator(pathPrefixED));
1422 texinputsPrefixED->setValidator(new NoNewLineValidator(texinputsPrefixED));
1426 void PrefPaths::applyRC(LyXRC & rc) const
1428 rc.document_path = internal_path(fromqstr(workingDirED->text()));
1429 rc.example_path = internal_path(fromqstr(exampleDirED->text()));
1430 rc.template_path = internal_path(fromqstr(templateDirED->text()));
1431 rc.backupdir_path = internal_path(fromqstr(backupDirED->text()));
1432 rc.tempdir_path = internal_path(fromqstr(tempDirED->text()));
1433 rc.thesaurusdir_path = internal_path(fromqstr(thesaurusDirED->text()));
1434 rc.hunspelldir_path = internal_path(fromqstr(hunspellDirED->text()));
1435 rc.path_prefix = internal_path_list(fromqstr(pathPrefixED->text()));
1436 rc.texinputs_prefix = internal_path_list(fromqstr(texinputsPrefixED->text()));
1437 // FIXME: should be a checkbox only
1438 rc.lyxpipes = internal_path(fromqstr(lyxserverDirED->text()));
1442 void PrefPaths::updateRC(LyXRC const & rc)
1444 workingDirED->setText(toqstr(external_path(rc.document_path)));
1445 exampleDirED->setText(toqstr(external_path(rc.example_path)));
1446 templateDirED->setText(toqstr(external_path(rc.template_path)));
1447 backupDirED->setText(toqstr(external_path(rc.backupdir_path)));
1448 tempDirED->setText(toqstr(external_path(rc.tempdir_path)));
1449 thesaurusDirED->setText(toqstr(external_path(rc.thesaurusdir_path)));
1450 hunspellDirED->setText(toqstr(external_path(rc.hunspelldir_path)));
1451 pathPrefixED->setText(toqstr(external_path_list(rc.path_prefix)));
1452 texinputsPrefixED->setText(toqstr(external_path_list(rc.texinputs_prefix)));
1453 // FIXME: should be a checkbox only
1454 lyxserverDirED->setText(toqstr(external_path(rc.lyxpipes)));
1458 void PrefPaths::selectExampledir()
1460 QString file = browseDir(internalPath(exampleDirED->text()),
1461 qt_("Select directory for example files"));
1462 if (!file.isEmpty())
1463 exampleDirED->setText(file);
1467 void PrefPaths::selectTemplatedir()
1469 QString file = browseDir(internalPath(templateDirED->text()),
1470 qt_("Select a document templates directory"));
1471 if (!file.isEmpty())
1472 templateDirED->setText(file);
1476 void PrefPaths::selectTempdir()
1478 QString file = browseDir(internalPath(tempDirED->text()),
1479 qt_("Select a temporary directory"));
1480 if (!file.isEmpty())
1481 tempDirED->setText(file);
1485 void PrefPaths::selectBackupdir()
1487 QString file = browseDir(internalPath(backupDirED->text()),
1488 qt_("Select a backups directory"));
1489 if (!file.isEmpty())
1490 backupDirED->setText(file);
1494 void PrefPaths::selectWorkingdir()
1496 QString file = browseDir(internalPath(workingDirED->text()),
1497 qt_("Select a document directory"));
1498 if (!file.isEmpty())
1499 workingDirED->setText(file);
1503 void PrefPaths::selectThesaurusdir()
1505 QString file = browseDir(internalPath(thesaurusDirED->text()),
1506 qt_("Set the path to the thesaurus dictionaries"));
1507 if (!file.isEmpty())
1508 thesaurusDirED->setText(file);
1512 void PrefPaths::selectHunspelldir()
1514 QString file = browseDir(internalPath(hunspellDirED->text()),
1515 qt_("Set the path to the Hunspell dictionaries"));
1516 if (!file.isEmpty())
1517 hunspellDirED->setText(file);
1521 void PrefPaths::selectLyxPipe()
1523 QString file = form_->browse(internalPath(lyxserverDirED->text()),
1524 qt_("Give a filename for the LyX server pipe"));
1525 if (!file.isEmpty())
1526 lyxserverDirED->setText(file);
1530 /////////////////////////////////////////////////////////////////////
1534 /////////////////////////////////////////////////////////////////////
1536 PrefSpellchecker::PrefSpellchecker(GuiPreferences * form)
1537 : PrefModule(catLanguage, N_("Spellchecker"), form)
1541 // FIXME: this check should test the target platform (darwin)
1542 #if defined(USE_MACOSX_PACKAGING)
1543 spellcheckerCB->addItem(qt_("Native"), QString("native"));
1544 #define CONNECT_APPLESPELL
1546 #undef CONNECT_APPLESPELL
1548 #if defined(USE_ASPELL)
1549 spellcheckerCB->addItem(qt_("Aspell"), QString("aspell"));
1551 #if defined(USE_ENCHANT)
1552 spellcheckerCB->addItem(qt_("Enchant"), QString("enchant"));
1554 #if defined(USE_HUNSPELL)
1555 spellcheckerCB->addItem(qt_("Hunspell"), QString("hunspell"));
1558 #if defined(CONNECT_APPLESPELL) || defined(USE_ASPELL) || defined(USE_ENCHANT) || defined(USE_HUNSPELL)
1559 connect(spellcheckerCB, SIGNAL(currentIndexChanged(int)),
1560 this, SIGNAL(changed()));
1561 connect(altLanguageED, SIGNAL(textChanged(QString)),
1562 this, SIGNAL(changed()));
1563 connect(escapeCharactersED, SIGNAL(textChanged(QString)),
1564 this, SIGNAL(changed()));
1565 connect(compoundWordCB, SIGNAL(clicked()),
1566 this, SIGNAL(changed()));
1567 connect(spellcheckContinuouslyCB, SIGNAL(clicked()),
1568 this, SIGNAL(changed()));
1569 connect(spellcheckNotesCB, SIGNAL(clicked()),
1570 this, SIGNAL(changed()));
1572 altLanguageED->setValidator(new NoNewLineValidator(altLanguageED));
1573 escapeCharactersED->setValidator(new NoNewLineValidator(escapeCharactersED));
1575 spellcheckerCB->setEnabled(false);
1576 altLanguageED->setEnabled(false);
1577 escapeCharactersED->setEnabled(false);
1578 compoundWordCB->setEnabled(false);
1579 spellcheckContinuouslyCB->setEnabled(false);
1580 spellcheckNotesCB->setEnabled(false);
1585 void PrefSpellchecker::applyRC(LyXRC & rc) const
1587 string const speller = fromqstr(spellcheckerCB->
1588 itemData(spellcheckerCB->currentIndex()).toString());
1589 if (!speller.empty())
1590 rc.spellchecker = speller;
1591 rc.spellchecker_alt_lang = fromqstr(altLanguageED->text());
1592 rc.spellchecker_esc_chars = fromqstr(escapeCharactersED->text());
1593 rc.spellchecker_accept_compound = compoundWordCB->isChecked();
1594 rc.spellcheck_continuously = spellcheckContinuouslyCB->isChecked();
1595 rc.spellcheck_notes = spellcheckNotesCB->isChecked();
1599 void PrefSpellchecker::updateRC(LyXRC const & rc)
1601 spellcheckerCB->setCurrentIndex(
1602 spellcheckerCB->findData(toqstr(rc.spellchecker)));
1603 altLanguageED->setText(toqstr(rc.spellchecker_alt_lang));
1604 escapeCharactersED->setText(toqstr(rc.spellchecker_esc_chars));
1605 compoundWordCB->setChecked(rc.spellchecker_accept_compound);
1606 spellcheckContinuouslyCB->setChecked(rc.spellcheck_continuously);
1607 spellcheckNotesCB->setChecked(rc.spellcheck_notes);
1611 void PrefSpellchecker::on_spellcheckerCB_currentIndexChanged(int index)
1613 QString spellchecker = spellcheckerCB->itemData(index).toString();
1615 compoundWordCB->setEnabled(spellchecker == QString("aspell"));
1620 /////////////////////////////////////////////////////////////////////
1624 /////////////////////////////////////////////////////////////////////
1627 PrefConverters::PrefConverters(GuiPreferences * form)
1628 : PrefModule(catFiles, N_("Converters"), form)
1632 connect(converterNewPB, SIGNAL(clicked()),
1633 this, SLOT(updateConverter()));
1634 connect(converterRemovePB, SIGNAL(clicked()),
1635 this, SLOT(removeConverter()));
1636 connect(converterModifyPB, SIGNAL(clicked()),
1637 this, SLOT(updateConverter()));
1638 connect(convertersLW, SIGNAL(currentRowChanged(int)),
1639 this, SLOT(switchConverter()));
1640 connect(converterFromCO, SIGNAL(activated(QString)),
1641 this, SLOT(changeConverter()));
1642 connect(converterToCO, SIGNAL(activated(QString)),
1643 this, SLOT(changeConverter()));
1644 connect(converterED, SIGNAL(textEdited(QString)),
1645 this, SLOT(changeConverter()));
1646 connect(converterFlagED, SIGNAL(textEdited(QString)),
1647 this, SLOT(changeConverter()));
1648 connect(converterNewPB, SIGNAL(clicked()),
1649 this, SIGNAL(changed()));
1650 connect(converterRemovePB, SIGNAL(clicked()),
1651 this, SIGNAL(changed()));
1652 connect(converterModifyPB, SIGNAL(clicked()),
1653 this, SIGNAL(changed()));
1654 connect(maxAgeLE, SIGNAL(textEdited(QString)),
1655 this, SIGNAL(changed()));
1656 connect(needauthForbiddenCB, SIGNAL(toggled(bool)),
1657 this, SIGNAL(changed()));
1659 converterED->setValidator(new NoNewLineValidator(converterED));
1660 converterFlagED->setValidator(new NoNewLineValidator(converterFlagED));
1661 maxAgeLE->setValidator(new QDoubleValidator(0, HUGE_VAL, 6, maxAgeLE));
1662 //converterDefGB->setFocusProxy(convertersLW);
1666 void PrefConverters::applyRC(LyXRC & rc) const
1668 rc.use_converter_cache = cacheCB->isChecked();
1669 rc.use_converter_needauth_forbidden = needauthForbiddenCB->isChecked();
1670 rc.use_converter_needauth = needauthCB->isChecked();
1671 rc.converter_cache_maxage = int(widgetToDouble(maxAgeLE) * 86400.0);
1675 static void setCheckboxBlockSignals(QCheckBox *cb, bool checked) {
1676 cb->blockSignals(true);
1677 cb->setChecked(checked);
1678 cb->blockSignals(false);
1682 void PrefConverters::updateRC(LyXRC const & rc)
1684 cacheCB->setChecked(rc.use_converter_cache);
1685 needauthForbiddenCB->setChecked(rc.use_converter_needauth_forbidden);
1686 setCheckboxBlockSignals(needauthCB, rc.use_converter_needauth);
1688 doubleToWidget(maxAgeLE, (double(rc.converter_cache_maxage) / 86400.0), 'g', 6);
1693 void PrefConverters::updateGui()
1695 QString const pattern("%1 -> %2");
1696 form_->formats().sort();
1697 form_->converters().update(form_->formats());
1698 // save current selection
1701 .arg(converterFromCO->currentText())
1702 .arg(converterToCO->currentText());
1704 converterFromCO->clear();
1705 converterToCO->clear();
1707 for (Format const & f : form_->formats()) {
1708 QString const name = toqstr(translateIfPossible(f.prettyname()));
1709 converterFromCO->addItem(name);
1710 converterToCO->addItem(name);
1713 // currentRowChanged(int) is also triggered when updating the listwidget
1714 // block signals to avoid unnecessary calls to switchConverter()
1715 convertersLW->blockSignals(true);
1716 convertersLW->clear();
1718 for (Converter const & c : form_->converters()) {
1719 QString const name =
1721 .arg(toqstr(translateIfPossible(c.From()->prettyname())))
1722 .arg(toqstr(translateIfPossible(c.To()->prettyname())));
1723 int type = form_->converters().getNumber(c.From()->name(),
1725 new QListWidgetItem(name, convertersLW, type);
1727 convertersLW->sortItems(Qt::AscendingOrder);
1728 convertersLW->blockSignals(false);
1730 // restore selection
1731 if (current != pattern.arg(QString()).arg(QString())) {
1732 QList<QListWidgetItem *> const item =
1733 convertersLW->findItems(current, Qt::MatchExactly);
1734 if (!item.isEmpty())
1735 convertersLW->setCurrentItem(item.at(0));
1738 // select first element if restoring failed
1739 if (convertersLW->currentRow() == -1)
1740 convertersLW->setCurrentRow(0);
1746 void PrefConverters::switchConverter()
1748 int const cnr = convertersLW->currentItem()->type();
1749 Converter const & c(form_->converters().get(cnr));
1750 converterFromCO->setCurrentIndex(form_->formats().getNumber(c.from()));
1751 converterToCO->setCurrentIndex(form_->formats().getNumber(c.to()));
1752 converterED->setText(toqstr(c.command()));
1753 converterFlagED->setText(toqstr(c.flags()));
1759 void PrefConverters::changeConverter()
1765 void PrefConverters::updateButtons()
1767 if (form_->formats().empty())
1769 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1770 Format const & to = form_->formats().get(converterToCO->currentIndex());
1771 int const sel = form_->converters().getNumber(from.name(), to.name());
1772 bool const known = sel >= 0;
1773 bool const valid = !(converterED->text().isEmpty()
1774 || from.name() == to.name());
1779 if (convertersLW->count() > 0) {
1780 int const cnr = convertersLW->currentItem()->type();
1781 Converter const & c = form_->converters().get(cnr);
1782 old_command = c.command();
1783 old_flag = c.flags();
1786 string const new_command = fromqstr(converterED->text());
1787 string const new_flag = fromqstr(converterFlagED->text());
1789 bool modified = (old_command != new_command || old_flag != new_flag);
1791 converterModifyPB->setEnabled(valid && known && modified);
1792 converterNewPB->setEnabled(valid && !known);
1793 converterRemovePB->setEnabled(known);
1795 maxAgeLE->setEnabled(cacheCB->isChecked());
1796 maxAgeLA->setEnabled(cacheCB->isChecked());
1801 // specify unique from/to or it doesn't appear. This is really bad UI
1802 // this is why we can use the same function for both new and modify
1803 void PrefConverters::updateConverter()
1805 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1806 Format const & to = form_->formats().get(converterToCO->currentIndex());
1807 string const flags = fromqstr(converterFlagED->text());
1808 string const command = fromqstr(converterED->text());
1810 Converter const * old =
1811 form_->converters().getConverter(from.name(), to.name());
1812 form_->converters().add(from.name(), to.name(), command, flags);
1815 form_->converters().updateLast(form_->formats());
1819 // Remove all files created by this converter from the cache, since
1820 // the modified converter might create different files.
1821 ConverterCache::get().remove_all(from.name(), to.name());
1825 void PrefConverters::removeConverter()
1827 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1828 Format const & to = form_->formats().get(converterToCO->currentIndex());
1829 form_->converters().erase(from.name(), to.name());
1833 // Remove all files created by this converter from the cache, since
1834 // a possible new converter might create different files.
1835 ConverterCache::get().remove_all(from.name(), to.name());
1839 void PrefConverters::on_cacheCB_stateChanged(int state)
1841 maxAgeLE->setEnabled(state == Qt::Checked);
1842 maxAgeLA->setEnabled(state == Qt::Checked);
1847 void PrefConverters::on_needauthForbiddenCB_toggled(bool checked)
1849 needauthCB->setEnabled(!checked);
1853 void PrefConverters::on_needauthCB_toggled(bool checked)
1860 int ret = frontend::Alert::prompt(
1861 _("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!"),
1862 0, 0, _("&No"), _("&Yes"));
1866 setCheckboxBlockSignals(needauthCB, true);
1870 /////////////////////////////////////////////////////////////////////
1874 /////////////////////////////////////////////////////////////////////
1876 class FormatValidator : public QValidator
1879 FormatValidator(QWidget *, Formats const & f);
1880 void fixup(QString & input) const override;
1881 QValidator::State validate(QString & input, int & pos) const override;
1883 virtual QString toString(Format const & format) const = 0;
1885 Formats const & formats_;
1889 FormatValidator::FormatValidator(QWidget * parent, Formats const & f)
1890 : QValidator(parent), formats_(f)
1895 void FormatValidator::fixup(QString & input) const
1897 Formats::const_iterator cit = formats_.begin();
1898 Formats::const_iterator end = formats_.end();
1899 for (; cit != end; ++cit) {
1900 QString const name = toString(*cit);
1901 if (distance(formats_.begin(), cit) == nr()) {
1909 QValidator::State FormatValidator::validate(QString & input, int & /*pos*/) const
1911 Formats::const_iterator cit = formats_.begin();
1912 Formats::const_iterator end = formats_.end();
1913 bool unknown = true;
1914 for (; unknown && cit != end; ++cit) {
1915 QString const name = toString(*cit);
1916 if (distance(formats_.begin(), cit) != nr())
1917 unknown = name != input;
1920 if (unknown && !input.isEmpty())
1921 return QValidator::Acceptable;
1923 return QValidator::Intermediate;
1927 int FormatValidator::nr() const
1929 QComboBox * p = qobject_cast<QComboBox *>(parent());
1930 return p->itemData(p->currentIndex()).toInt();
1934 /////////////////////////////////////////////////////////////////////
1936 // FormatNameValidator
1938 /////////////////////////////////////////////////////////////////////
1940 class FormatNameValidator : public FormatValidator
1943 FormatNameValidator(QWidget * parent, Formats const & f)
1944 : FormatValidator(parent, f)
1947 QString toString(Format const & format) const override
1949 return toqstr(format.name());
1954 /////////////////////////////////////////////////////////////////////
1956 // FormatPrettynameValidator
1958 /////////////////////////////////////////////////////////////////////
1960 class FormatPrettynameValidator : public FormatValidator
1963 FormatPrettynameValidator(QWidget * parent, Formats const & f)
1964 : FormatValidator(parent, f)
1967 QString toString(Format const & format) const override
1969 return toqstr(translateIfPossible(format.prettyname()));
1974 /////////////////////////////////////////////////////////////////////
1978 /////////////////////////////////////////////////////////////////////
1980 PrefFileformats::PrefFileformats(GuiPreferences * form)
1981 : PrefModule(catFiles, N_("File Formats"), form)
1985 formatED->setValidator(new FormatNameValidator(formatsCB, form_->formats()));
1986 formatsCB->setValidator(new FormatPrettynameValidator(formatsCB, form_->formats()));
1987 extensionsED->setValidator(new NoNewLineValidator(extensionsED));
1988 shortcutED->setValidator(new NoNewLineValidator(shortcutED));
1989 editorED->setValidator(new NoNewLineValidator(editorED));
1990 viewerED->setValidator(new NoNewLineValidator(viewerED));
1991 copierED->setValidator(new NoNewLineValidator(copierED));
1993 connect(documentCB, SIGNAL(clicked()),
1994 this, SLOT(setFlags()));
1995 connect(vectorCB, SIGNAL(clicked()),
1996 this, SLOT(setFlags()));
1997 connect(exportMenuCB, SIGNAL(clicked()),
1998 this, SLOT(setFlags()));
1999 connect(formatsCB->lineEdit(), SIGNAL(editingFinished()),
2000 this, SLOT(updatePrettyname()));
2001 connect(formatsCB->lineEdit(), SIGNAL(textEdited(QString)),
2002 this, SIGNAL(changed()));
2003 connect(defaultFormatCB, SIGNAL(activated(QString)),
2004 this, SIGNAL(changed()));
2005 connect(defaultOTFFormatCB, SIGNAL(activated(QString)),
2006 this, SIGNAL(changed()));
2007 connect(defaultPlatexFormatCB, SIGNAL(activated(QString)),
2008 this, SIGNAL(changed()));
2009 connect(viewerCO, SIGNAL(activated(int)),
2010 this, SIGNAL(changed()));
2011 connect(editorCO, SIGNAL(activated(int)),
2012 this, SIGNAL(changed()));
2018 string const l10n_shortcut(docstring const & prettyname, string const & shortcut)
2020 if (shortcut.empty())
2023 string l10n_format =
2024 to_utf8(_(to_utf8(prettyname) + '|' + shortcut));
2025 return split(l10n_format, '|');
2031 void PrefFileformats::applyRC(LyXRC & rc) const
2033 QString const default_format = defaultFormatCB->itemData(
2034 defaultFormatCB->currentIndex()).toString();
2035 rc.default_view_format = fromqstr(default_format);
2036 QString const default_otf_format = defaultOTFFormatCB->itemData(
2037 defaultOTFFormatCB->currentIndex()).toString();
2038 rc.default_otf_view_format = fromqstr(default_otf_format);
2039 QString const default_platex_format = defaultPlatexFormatCB->itemData(
2040 defaultPlatexFormatCB->currentIndex()).toString();
2041 rc.default_platex_view_format = fromqstr(default_platex_format);
2045 void PrefFileformats::updateRC(LyXRC const & rc)
2047 viewer_alternatives = rc.viewer_alternatives;
2048 editor_alternatives = rc.editor_alternatives;
2049 bool const init = defaultFormatCB->currentText().isEmpty();
2053 defaultFormatCB->findData(toqstr(rc.default_view_format));
2054 defaultFormatCB->setCurrentIndex(pos);
2055 pos = defaultOTFFormatCB->findData(toqstr(rc.default_otf_view_format));
2056 defaultOTFFormatCB->setCurrentIndex(pos);
2057 defaultOTFFormatCB->setCurrentIndex(pos);
2058 pos = defaultPlatexFormatCB->findData(toqstr(rc.default_platex_view_format));
2059 defaultPlatexFormatCB->setCurrentIndex(pos);
2060 defaultPlatexFormatCB->setCurrentIndex(pos);
2065 void PrefFileformats::updateView()
2067 QString const current = formatsCB->currentText();
2068 QString const current_def = defaultFormatCB->currentText();
2069 QString const current_def_otf = defaultOTFFormatCB->currentText();
2070 QString const current_def_platex = defaultPlatexFormatCB->currentText();
2072 // update comboboxes with formats
2073 formatsCB->blockSignals(true);
2074 defaultFormatCB->blockSignals(true);
2075 defaultOTFFormatCB->blockSignals(true);
2076 defaultPlatexFormatCB->blockSignals(true);
2078 defaultFormatCB->clear();
2079 defaultOTFFormatCB->clear();
2080 defaultPlatexFormatCB->clear();
2081 form_->formats().sort();
2082 for (Format const & f : form_->formats()) {
2083 QString const prettyname = toqstr(translateIfPossible(f.prettyname()));
2084 formatsCB->addItem(prettyname,
2085 QVariant(form_->formats().getNumber(f.name())));
2086 if (f.viewer().empty())
2088 if (form_->converters().isReachable("xhtml", f.name())
2089 || form_->converters().isReachable("dviluatex", f.name())
2090 || form_->converters().isReachable("luatex", f.name())
2091 || form_->converters().isReachable("xetex", f.name())) {
2092 defaultFormatCB->addItem(prettyname,
2093 QVariant(toqstr(f.name())));
2094 defaultOTFFormatCB->addItem(prettyname,
2095 QVariant(toqstr(f.name())));
2097 if (form_->converters().isReachable("latex", f.name())
2098 || form_->converters().isReachable("pdflatex", f.name()))
2099 defaultFormatCB->addItem(prettyname,
2100 QVariant(toqstr(f.name())));
2101 if (form_->converters().isReachable("platex", f.name()))
2102 defaultPlatexFormatCB->addItem(prettyname,
2103 QVariant(toqstr(f.name())));
2107 // restore selections
2108 int item = formatsCB->findText(current, Qt::MatchExactly);
2109 formatsCB->setCurrentIndex(item < 0 ? 0 : item);
2110 on_formatsCB_currentIndexChanged(item < 0 ? 0 : item);
2111 item = defaultFormatCB->findText(current_def, Qt::MatchExactly);
2112 defaultFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2113 item = defaultOTFFormatCB->findText(current_def_otf, Qt::MatchExactly);
2114 defaultOTFFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2115 item = defaultPlatexFormatCB->findText(current_def_platex, Qt::MatchExactly);
2116 defaultPlatexFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2117 formatsCB->blockSignals(false);
2118 defaultFormatCB->blockSignals(false);
2119 defaultOTFFormatCB->blockSignals(false);
2120 defaultPlatexFormatCB->blockSignals(false);
2124 void PrefFileformats::on_formatsCB_currentIndexChanged(int i)
2126 if (form_->formats().empty())
2128 int const nr = formatsCB->itemData(i).toInt();
2129 Format const f = form_->formats().get(nr);
2131 formatED->setText(toqstr(f.name()));
2132 copierED->setText(toqstr(form_->movers().command(f.name())));
2133 extensionsED->setText(toqstr(f.extensions()));
2134 mimeED->setText(toqstr(f.mime()));
2135 shortcutED->setText(
2136 toqstr(l10n_shortcut(f.prettyname(), f.shortcut())));
2137 documentCB->setChecked((f.documentFormat()));
2138 vectorCB->setChecked((f.vectorFormat()));
2139 exportMenuCB->setChecked((f.inExportMenu()));
2140 exportMenuCB->setEnabled((f.documentFormat()));
2146 void PrefFileformats::setFlags()
2148 int flags = Format::none;
2149 if (documentCB->isChecked())
2150 flags |= Format::document;
2151 if (vectorCB->isChecked())
2152 flags |= Format::vector;
2153 if (exportMenuCB->isChecked())
2154 flags |= Format::export_menu;
2155 currentFormat().setFlags(flags);
2156 exportMenuCB->setEnabled(documentCB->isChecked());
2161 void PrefFileformats::on_copierED_textEdited(const QString & s)
2163 string const fmt = fromqstr(formatED->text());
2164 form_->movers().set(fmt, fromqstr(s));
2169 void PrefFileformats::on_extensionsED_textEdited(const QString & s)
2171 currentFormat().setExtensions(fromqstr(s));
2176 void PrefFileformats::on_viewerED_textEdited(const QString & s)
2178 currentFormat().setViewer(fromqstr(s));
2183 void PrefFileformats::on_editorED_textEdited(const QString & s)
2185 currentFormat().setEditor(fromqstr(s));
2190 void PrefFileformats::on_mimeED_textEdited(const QString & s)
2192 currentFormat().setMime(fromqstr(s));
2197 void PrefFileformats::on_shortcutED_textEdited(const QString & s)
2199 string const new_shortcut = fromqstr(s);
2200 if (new_shortcut == l10n_shortcut(currentFormat().prettyname(),
2201 currentFormat().shortcut()))
2203 currentFormat().setShortcut(new_shortcut);
2208 void PrefFileformats::on_formatED_editingFinished()
2210 string const newname = fromqstr(formatED->displayText());
2211 string const oldname = currentFormat().name();
2212 if (newname == oldname)
2214 if (form_->converters().formatIsUsed(oldname)) {
2215 Alert::error(_("Format in use"),
2216 _("You cannot change a format's short name "
2217 "if the format is used by a converter. "
2218 "Please remove the converter first."));
2223 currentFormat().setName(newname);
2228 void PrefFileformats::on_formatED_textChanged(const QString &)
2230 QString t = formatED->text();
2232 bool valid = formatED->validator()->validate(t, p) == QValidator::Acceptable;
2233 setValid(formatLA, valid);
2237 void PrefFileformats::on_formatsCB_editTextChanged(const QString &)
2239 QString t = formatsCB->currentText();
2241 bool valid = formatsCB->validator()->validate(t, p) == QValidator::Acceptable;
2242 setValid(formatsLA, valid);
2246 void PrefFileformats::updatePrettyname()
2248 QString const newname = formatsCB->currentText();
2249 if (newname == toqstr(translateIfPossible(currentFormat().prettyname())))
2252 currentFormat().setPrettyname(qstring_to_ucs4(newname));
2260 void updateComboBox(LyXRC::Alternatives const & alts,
2261 string const & fmt, QComboBox * combo)
2263 LyXRC::Alternatives::const_iterator it =
2265 if (it != alts.end()) {
2266 LyXRC::CommandSet const & cmds = it->second;
2267 LyXRC::CommandSet::const_iterator sit =
2269 LyXRC::CommandSet::const_iterator const sen =
2271 for (; sit != sen; ++sit) {
2272 QString const qcmd = toqstr(*sit);
2273 combo->addItem(qcmd, qcmd);
2280 void PrefFileformats::updateViewers()
2282 Format const f = currentFormat();
2283 viewerCO->blockSignals(true);
2285 viewerCO->addItem(qt_("None"), QString());
2286 updateComboBox(viewer_alternatives, f.name(), viewerCO);
2287 viewerCO->addItem(qt_("Custom"), QString("custom viewer"));
2288 viewerCO->blockSignals(false);
2290 int pos = viewerCO->findData(toqstr(f.viewer()));
2293 viewerED->setEnabled(false);
2294 viewerCO->setCurrentIndex(pos);
2296 viewerED->setEnabled(true);
2297 viewerED->setText(toqstr(f.viewer()));
2298 viewerCO->setCurrentIndex(viewerCO->findData(toqstr("custom viewer")));
2303 void PrefFileformats::updateEditors()
2305 Format const f = currentFormat();
2306 editorCO->blockSignals(true);
2308 editorCO->addItem(qt_("None"), QString());
2309 updateComboBox(editor_alternatives, f.name(), editorCO);
2310 editorCO->addItem(qt_("Custom"), QString("custom editor"));
2311 editorCO->blockSignals(false);
2313 int pos = editorCO->findData(toqstr(f.editor()));
2316 editorED->setEnabled(false);
2317 editorCO->setCurrentIndex(pos);
2319 editorED->setEnabled(true);
2320 editorED->setText(toqstr(f.editor()));
2321 editorCO->setCurrentIndex(editorCO->findData(toqstr("custom editor")));
2326 void PrefFileformats::on_viewerCO_currentIndexChanged(int i)
2328 bool const custom = viewerCO->itemData(i).toString() == "custom viewer";
2329 viewerED->setEnabled(custom);
2331 currentFormat().setViewer(fromqstr(viewerCO->itemData(i).toString()));
2335 void PrefFileformats::on_editorCO_currentIndexChanged(int i)
2337 bool const custom = editorCO->itemData(i).toString() == "custom editor";
2338 editorED->setEnabled(custom);
2340 currentFormat().setEditor(fromqstr(editorCO->itemData(i).toString()));
2344 Format & PrefFileformats::currentFormat()
2346 int const i = formatsCB->currentIndex();
2347 int const nr = formatsCB->itemData(i).toInt();
2348 return form_->formats().get(nr);
2352 void PrefFileformats::on_formatNewPB_clicked()
2354 form_->formats().add("", "", docstring(), "", "", "", "", Format::none);
2356 formatsCB->setCurrentIndex(0);
2357 formatsCB->setFocus(Qt::OtherFocusReason);
2361 void PrefFileformats::on_formatRemovePB_clicked()
2363 int const i = formatsCB->currentIndex();
2364 int const nr = formatsCB->itemData(i).toInt();
2365 string const current_text = form_->formats().get(nr).name();
2366 if (form_->converters().formatIsUsed(current_text)) {
2367 Alert::error(_("Format in use"),
2368 _("Cannot remove a Format used by a Converter. "
2369 "Remove the converter first."));
2373 form_->formats().erase(current_text);
2376 on_formatsCB_editTextChanged(formatsCB->currentText());
2381 /////////////////////////////////////////////////////////////////////
2385 /////////////////////////////////////////////////////////////////////
2387 PrefLanguage::PrefLanguage(GuiPreferences * form)
2388 : PrefModule(catLanguage, N_("Language"), form)
2392 connect(visualCursorRB, SIGNAL(clicked()),
2393 this, SIGNAL(changed()));
2394 connect(logicalCursorRB, SIGNAL(clicked()),
2395 this, SIGNAL(changed()));
2396 connect(markForeignCB, SIGNAL(clicked()),
2397 this, SIGNAL(changed()));
2398 connect(respectOSkbdCB, SIGNAL(clicked()),
2399 this, SIGNAL(changed()));
2400 connect(explicitDocLangBeginCB, SIGNAL(clicked()),
2401 this, SIGNAL(changed()));
2402 connect(explicitDocLangEndCB, SIGNAL(clicked()),
2403 this, SIGNAL(changed()));
2404 connect(languagePackageCO, SIGNAL(activated(int)),
2405 this, SIGNAL(changed()));
2406 connect(languagePackageED, SIGNAL(textChanged(QString)),
2407 this, SIGNAL(changed()));
2408 connect(globalCB, SIGNAL(clicked()),
2409 this, SIGNAL(changed()));
2410 connect(startCommandED, SIGNAL(textChanged(QString)),
2411 this, SIGNAL(changed()));
2412 connect(endCommandED, SIGNAL(textChanged(QString)),
2413 this, SIGNAL(changed()));
2414 connect(uiLanguageCO, SIGNAL(activated(int)),
2415 this, SIGNAL(changed()));
2416 connect(defaultDecimalSepED, SIGNAL(textChanged(QString)),
2417 this, SIGNAL(changed()));
2418 connect(defaultDecimalSepCO, SIGNAL(activated(int)),
2419 this, SIGNAL(changed()));
2420 connect(defaultLengthUnitCO, SIGNAL(activated(int)),
2421 this, SIGNAL(changed()));
2423 languagePackageED->setValidator(new NoNewLineValidator(languagePackageED));
2424 startCommandED->setValidator(new NoNewLineValidator(startCommandED));
2425 endCommandED->setValidator(new NoNewLineValidator(endCommandED));
2427 defaultDecimalSepED->setValidator(new QRegExpValidator(QRegExp("\\S"), this));
2428 defaultDecimalSepED->setMaxLength(1);
2430 defaultLengthUnitCO->addItem(lyx::qt_(unit_name_gui[Length::CM]), Length::CM);
2431 defaultLengthUnitCO->addItem(lyx::qt_(unit_name_gui[Length::IN]), Length::IN);
2433 QAbstractItemModel * language_model = guiApp->languageModel();
2434 language_model->sort(0);
2435 uiLanguageCO->blockSignals(true);
2436 uiLanguageCO->clear();
2437 uiLanguageCO->addItem(qt_("Default"), toqstr("auto"));
2438 for (int i = 0; i != language_model->rowCount(); ++i) {
2439 QModelIndex index = language_model->index(i, 0);
2440 // Filter the list based on the available translation and add
2441 // each language code only once
2442 string const name = fromqstr(index.data(Qt::UserRole).toString());
2443 Language const * lang = languages.getLanguage(name);
2446 // never remove the currently selected language
2447 if (name != form->rc().gui_language
2448 && name != lyxrc.gui_language
2449 && (!Messages::available(lang->code())
2450 || !lang->hasGuiSupport()))
2452 uiLanguageCO->addItem(index.data(Qt::DisplayRole).toString(),
2453 index.data(Qt::UserRole).toString());
2455 uiLanguageCO->blockSignals(false);
2459 void PrefLanguage::on_uiLanguageCO_currentIndexChanged(int)
2461 QMessageBox::information(this, qt_("LyX needs to be restarted!"),
2462 qt_("The change of user interface language will be fully "
2463 "effective only after a restart."));
2467 void PrefLanguage::on_languagePackageCO_currentIndexChanged(int i)
2470 languagePackageED->setText(save_langpack_);
2471 else if (!languagePackageED->text().isEmpty()) {
2472 save_langpack_ = languagePackageED->text();
2473 languagePackageED->clear();
2475 languagePackageED->setEnabled(i == 2);
2479 void PrefLanguage::on_defaultDecimalSepCO_currentIndexChanged(int i)
2481 defaultDecimalSepED->setEnabled(i == 1);
2485 void PrefLanguage::applyRC(LyXRC & rc) const
2487 rc.visual_cursor = visualCursorRB->isChecked();
2488 rc.mark_foreign_language = markForeignCB->isChecked();
2489 rc.respect_os_kbd_language = respectOSkbdCB->isChecked();
2490 rc.language_auto_begin = !explicitDocLangBeginCB->isChecked();
2491 rc.language_auto_end = !explicitDocLangEndCB->isChecked();
2492 int const p = languagePackageCO->currentIndex();
2494 rc.language_package_selection = LyXRC::LP_AUTO;
2496 rc.language_package_selection = LyXRC::LP_BABEL;
2498 rc.language_package_selection = LyXRC::LP_CUSTOM;
2500 rc.language_package_selection = LyXRC::LP_NONE;
2501 rc.language_custom_package = fromqstr(languagePackageED->text());
2502 rc.language_global_options = globalCB->isChecked();
2503 rc.language_command_begin = fromqstr(startCommandED->text());
2504 rc.language_command_end = fromqstr(endCommandED->text());
2505 rc.gui_language = fromqstr(
2506 uiLanguageCO->itemData(uiLanguageCO->currentIndex()).toString());
2507 if (defaultDecimalSepCO->currentIndex() == 0)
2508 rc.default_decimal_sep = "locale";
2510 rc.default_decimal_sep = fromqstr(defaultDecimalSepED->text());
2511 rc.default_length_unit = (Length::UNIT) defaultLengthUnitCO->itemData(defaultLengthUnitCO->currentIndex()).toInt();
2515 void PrefLanguage::updateRC(LyXRC const & rc)
2517 if (rc.visual_cursor)
2518 visualCursorRB->setChecked(true);
2520 logicalCursorRB->setChecked(true);
2521 markForeignCB->setChecked(rc.mark_foreign_language);
2522 respectOSkbdCB->setChecked(rc.respect_os_kbd_language);
2523 explicitDocLangBeginCB->setChecked(!rc.language_auto_begin);
2524 explicitDocLangEndCB->setChecked(!rc.language_auto_end);
2525 languagePackageCO->setCurrentIndex(rc.language_package_selection);
2526 if (languagePackageCO->currentIndex() == 2) {
2527 languagePackageED->setText(toqstr(rc.language_custom_package));
2528 languagePackageED->setEnabled(true);
2530 languagePackageED->clear();
2531 save_langpack_ = toqstr(rc.language_custom_package);
2532 languagePackageED->setEnabled(false);
2534 defaultDecimalSepED->setEnabled(defaultDecimalSepCO->currentIndex() == 1);
2535 globalCB->setChecked(rc.language_global_options);
2536 startCommandED->setText(toqstr(rc.language_command_begin));
2537 endCommandED->setText(toqstr(rc.language_command_end));
2538 if (rc.default_decimal_sep == "locale") {
2539 defaultDecimalSepCO->setCurrentIndex(0);
2540 defaultDecimalSepED->clear();
2542 defaultDecimalSepCO->setCurrentIndex(1);
2543 defaultDecimalSepED->setText(toqstr(rc.default_decimal_sep));
2545 int pos = defaultLengthUnitCO->findData(int(rc.default_length_unit));
2546 defaultLengthUnitCO->setCurrentIndex(pos);
2548 pos = uiLanguageCO->findData(toqstr(rc.gui_language));
2549 uiLanguageCO->blockSignals(true);
2550 uiLanguageCO->setCurrentIndex(pos);
2551 uiLanguageCO->blockSignals(false);
2555 /////////////////////////////////////////////////////////////////////
2557 // PrefUserInterface
2559 /////////////////////////////////////////////////////////////////////
2561 PrefUserInterface::PrefUserInterface(GuiPreferences * form)
2562 : PrefModule(catLookAndFeel, N_("User Interface"), form)
2566 connect(uiFilePB, SIGNAL(clicked()),
2567 this, SLOT(selectUi()));
2568 connect(uiFileED, SIGNAL(textChanged(QString)),
2569 this, SIGNAL(changed()));
2570 connect(iconSetCO, SIGNAL(activated(int)),
2571 this, SIGNAL(changed()));
2572 connect(useSystemThemeIconsCB, SIGNAL(clicked()),
2573 this, SIGNAL(changed()));
2574 connect(lastfilesSB, SIGNAL(valueChanged(int)),
2575 this, SIGNAL(changed()));
2576 connect(tooltipCB, SIGNAL(toggled(bool)),
2577 this, SIGNAL(changed()));
2578 lastfilesSB->setMaximum(maxlastfiles);
2580 iconSetCO->addItem(qt_("Default"), QString());
2581 iconSetCO->addItem(qt_("Classic"), "classic");
2582 iconSetCO->addItem(qt_("Oxygen"), "oxygen");
2584 #if (!(defined Q_WS_X11 || defined(QPA_XCB)) || QT_VERSION < 0x040600)
2585 useSystemThemeIconsCB->hide();
2590 void PrefUserInterface::applyRC(LyXRC & rc) const
2592 rc.icon_set = fromqstr(iconSetCO->itemData(
2593 iconSetCO->currentIndex()).toString());
2595 rc.ui_file = internal_path(fromqstr(uiFileED->text()));
2596 rc.use_system_theme_icons = useSystemThemeIconsCB->isChecked();
2597 rc.num_lastfiles = lastfilesSB->value();
2598 rc.use_tooltip = tooltipCB->isChecked();
2602 void PrefUserInterface::updateRC(LyXRC const & rc)
2604 int iconset = iconSetCO->findData(toqstr(rc.icon_set));
2607 iconSetCO->setCurrentIndex(iconset);
2608 useSystemThemeIconsCB->setChecked(rc.use_system_theme_icons);
2609 uiFileED->setText(toqstr(external_path(rc.ui_file)));
2610 lastfilesSB->setValue(rc.num_lastfiles);
2611 tooltipCB->setChecked(rc.use_tooltip);
2615 void PrefUserInterface::selectUi()
2617 QString file = form_->browseUI(internalPath(uiFileED->text()));
2618 if (!file.isEmpty())
2619 uiFileED->setText(file);
2623 /////////////////////////////////////////////////////////////////////
2625 // PrefDocumentHandling
2627 /////////////////////////////////////////////////////////////////////
2629 PrefDocHandling::PrefDocHandling(GuiPreferences * form)
2630 : PrefModule(catLookAndFeel, N_("Document Handling"), form)
2634 connect(autoSaveCB, SIGNAL(toggled(bool)),
2635 autoSaveSB, SLOT(setEnabled(bool)));
2636 connect(autoSaveCB, SIGNAL(toggled(bool)),
2637 TextLabel1, SLOT(setEnabled(bool)));
2638 connect(openDocumentsInTabsCB, SIGNAL(clicked()),
2639 this, SIGNAL(changed()));
2640 connect(singleInstanceCB, SIGNAL(clicked()),
2641 this, SIGNAL(changed()));
2642 connect(singleCloseTabButtonCB, SIGNAL(clicked()),
2643 this, SIGNAL(changed()));
2644 connect(closeLastViewCO, SIGNAL(activated(int)),
2645 this, SIGNAL(changed()));
2646 connect(restoreCursorCB, SIGNAL(clicked()),
2647 this, SIGNAL(changed()));
2648 connect(loadSessionCB, SIGNAL(clicked()),
2649 this, SIGNAL(changed()));
2650 connect(allowGeometrySessionCB, SIGNAL(clicked()),
2651 this, SIGNAL(changed()));
2652 connect(autoSaveSB, SIGNAL(valueChanged(int)),
2653 this, SIGNAL(changed()));
2654 connect(autoSaveCB, SIGNAL(clicked()),
2655 this, SIGNAL(changed()));
2656 connect(backupCB, SIGNAL(clicked()),
2657 this, SIGNAL(changed()));
2658 connect(saveCompressedCB, SIGNAL(clicked()),
2659 this, SIGNAL(changed()));
2660 connect(saveOriginCB, SIGNAL(clicked()),
2661 this, SIGNAL(changed()));
2665 void PrefDocHandling::applyRC(LyXRC & rc) const
2667 rc.use_lastfilepos = restoreCursorCB->isChecked();
2668 rc.load_session = loadSessionCB->isChecked();
2669 rc.allow_geometry_session = allowGeometrySessionCB->isChecked();
2670 rc.autosave = autoSaveCB->isChecked() ? autoSaveSB->value() * 60 : 0;
2671 rc.make_backup = backupCB->isChecked();
2672 rc.save_compressed = saveCompressedCB->isChecked();
2673 rc.save_origin = saveOriginCB->isChecked();
2674 rc.open_buffers_in_tabs = openDocumentsInTabsCB->isChecked();
2675 rc.single_instance = singleInstanceCB->isChecked();
2676 rc.single_close_tab_button = singleCloseTabButtonCB->isChecked();
2678 switch (closeLastViewCO->currentIndex()) {
2680 rc.close_buffer_with_last_view = "yes";
2683 rc.close_buffer_with_last_view = "no";
2686 rc.close_buffer_with_last_view = "ask";
2694 void PrefDocHandling::updateRC(LyXRC const & rc)
2696 restoreCursorCB->setChecked(rc.use_lastfilepos);
2697 loadSessionCB->setChecked(rc.load_session);
2698 allowGeometrySessionCB->setChecked(rc.allow_geometry_session);
2699 // convert to minutes
2700 bool autosave = rc.autosave > 0;
2701 int mins = rc.autosave / 60;
2704 autoSaveSB->setValue(mins);
2705 autoSaveCB->setChecked(autosave);
2706 autoSaveSB->setEnabled(autosave);
2707 backupCB->setChecked(rc.make_backup);
2708 saveCompressedCB->setChecked(rc.save_compressed);
2709 saveOriginCB->setChecked(rc.save_origin);
2710 openDocumentsInTabsCB->setChecked(rc.open_buffers_in_tabs);
2711 singleInstanceCB->setChecked(rc.single_instance && !rc.lyxpipes.empty());
2712 singleInstanceCB->setEnabled(!rc.lyxpipes.empty());
2713 singleCloseTabButtonCB->setChecked(rc.single_close_tab_button);
2714 if (rc.close_buffer_with_last_view == "yes")
2715 closeLastViewCO->setCurrentIndex(0);
2716 else if (rc.close_buffer_with_last_view == "no")
2717 closeLastViewCO->setCurrentIndex(1);
2718 else if (rc.close_buffer_with_last_view == "ask")
2719 closeLastViewCO->setCurrentIndex(2);
2723 void PrefDocHandling::on_clearSessionPB_clicked()
2725 guiApp->clearSession();
2730 /////////////////////////////////////////////////////////////////////
2734 /////////////////////////////////////////////////////////////////////
2736 PrefEdit::PrefEdit(GuiPreferences * form)
2737 : PrefModule(catEditing, N_("Control"), form)
2741 connect(cursorFollowsCB, SIGNAL(clicked()),
2742 this, SIGNAL(changed()));
2743 connect(scrollBelowCB, SIGNAL(clicked()),
2744 this, SIGNAL(changed()));
2745 connect(macLikeCursorMovementCB, SIGNAL(clicked()),
2746 this, SIGNAL(changed()));
2747 connect(copyCTMarkupCB, SIGNAL(clicked()),
2748 this, SIGNAL(changed()));
2749 connect(sortEnvironmentsCB, SIGNAL(clicked()),
2750 this, SIGNAL(changed()));
2751 connect(groupEnvironmentsCB, SIGNAL(clicked()),
2752 this, SIGNAL(changed()));
2753 connect(macroEditStyleCO, SIGNAL(activated(int)),
2754 this, SIGNAL(changed()));
2755 connect(cursorWidthSB, SIGNAL(valueChanged(int)),
2756 this, SIGNAL(changed()));
2757 connect(citationSearchLE, SIGNAL(textChanged(QString)),
2758 this, SIGNAL(changed()));
2759 connect(fullscreenWidthSB, SIGNAL(valueChanged(int)),
2760 this, SIGNAL(changed()));
2761 connect(toggleTabbarCB, SIGNAL(toggled(bool)),
2762 this, SIGNAL(changed()));
2763 connect(toggleMenubarCB, SIGNAL(toggled(bool)),
2764 this, SIGNAL(changed()));
2765 connect(toggleScrollbarCB, SIGNAL(toggled(bool)),
2766 this, SIGNAL(changed()));
2767 connect(toggleStatusbarCB, SIGNAL(toggled(bool)),
2768 this, SIGNAL(changed()));
2769 connect(toggleToolbarsCB, SIGNAL(toggled(bool)),
2770 this, SIGNAL(changed()));
2774 void PrefEdit::on_fullscreenLimitCB_toggled(bool const state)
2776 fullscreenWidthSB->setEnabled(state);
2777 fullscreenWidthLA->setEnabled(state);
2782 void PrefEdit::on_citationSearchCB_toggled(bool const state)
2784 citationSearchLE->setEnabled(state);
2785 citationSearchLA->setEnabled(state);
2790 void PrefEdit::applyRC(LyXRC & rc) const
2792 rc.cursor_follows_scrollbar = cursorFollowsCB->isChecked();
2793 rc.scroll_below_document = scrollBelowCB->isChecked();
2794 rc.mac_like_cursor_movement = macLikeCursorMovementCB->isChecked();
2795 rc.ct_markup_copied = copyCTMarkupCB->isChecked();
2796 rc.sort_layouts = sortEnvironmentsCB->isChecked();
2797 rc.group_layouts = groupEnvironmentsCB->isChecked();
2798 switch (macroEditStyleCO->currentIndex()) {
2799 case 0: rc.macro_edit_style = LyXRC::MACRO_EDIT_INLINE_BOX; break;
2800 case 1: rc.macro_edit_style = LyXRC::MACRO_EDIT_INLINE; break;
2801 case 2: rc.macro_edit_style = LyXRC::MACRO_EDIT_LIST; break;
2803 rc.cursor_width = cursorWidthSB->value();
2804 rc.citation_search = citationSearchCB->isChecked();
2805 rc.citation_search_pattern = fromqstr(citationSearchLE->text());
2806 rc.full_screen_toolbars = toggleToolbarsCB->isChecked();
2807 rc.full_screen_scrollbar = toggleScrollbarCB->isChecked();
2808 rc.full_screen_statusbar = toggleStatusbarCB->isChecked();
2809 rc.full_screen_tabbar = toggleTabbarCB->isChecked();
2810 rc.full_screen_menubar = toggleMenubarCB->isChecked();
2811 rc.full_screen_width = fullscreenWidthSB->value();
2812 rc.full_screen_limit = fullscreenLimitCB->isChecked();
2816 void PrefEdit::updateRC(LyXRC const & rc)
2818 cursorFollowsCB->setChecked(rc.cursor_follows_scrollbar);
2819 scrollBelowCB->setChecked(rc.scroll_below_document);
2820 macLikeCursorMovementCB->setChecked(rc.mac_like_cursor_movement);
2821 copyCTMarkupCB->setChecked(rc.ct_markup_copied);
2822 sortEnvironmentsCB->setChecked(rc.sort_layouts);
2823 groupEnvironmentsCB->setChecked(rc.group_layouts);
2824 macroEditStyleCO->setCurrentIndex(rc.macro_edit_style);
2825 cursorWidthSB->setValue(rc.cursor_width);
2826 citationSearchCB->setChecked(rc.citation_search);
2827 citationSearchLE->setText(toqstr(rc.citation_search_pattern));
2828 citationSearchLE->setEnabled(rc.citation_search);
2829 citationSearchLA->setEnabled(rc.citation_search);
2830 toggleScrollbarCB->setChecked(rc.full_screen_scrollbar);
2831 toggleStatusbarCB->setChecked(rc.full_screen_statusbar);
2832 toggleToolbarsCB->setChecked(rc.full_screen_toolbars);
2833 toggleTabbarCB->setChecked(rc.full_screen_tabbar);
2834 toggleMenubarCB->setChecked(rc.full_screen_menubar);
2835 fullscreenWidthSB->setValue(rc.full_screen_width);
2836 fullscreenLimitCB->setChecked(rc.full_screen_limit);
2837 fullscreenWidthSB->setEnabled(rc.full_screen_limit);
2838 fullscreenWidthLA->setEnabled(rc.full_screen_limit);
2842 /////////////////////////////////////////////////////////////////////
2846 /////////////////////////////////////////////////////////////////////
2849 GuiShortcutDialog::GuiShortcutDialog(QWidget * parent) : QDialog(parent)
2851 Ui::shortcutUi::setupUi(this);
2852 QDialog::setModal(true);
2853 lfunLE->setValidator(new NoNewLineValidator(lfunLE));
2857 PrefShortcuts::PrefShortcuts(GuiPreferences * form)
2858 : PrefModule(catEditing, N_("Shortcuts"), form),
2859 editItem_(nullptr), mathItem_(nullptr), bufferItem_(nullptr), layoutItem_(nullptr),
2860 systemItem_(nullptr)
2864 shortcutsTW->setColumnCount(2);
2865 shortcutsTW->headerItem()->setText(0, qt_("Function"));
2866 shortcutsTW->headerItem()->setText(1, qt_("Shortcut"));
2867 shortcutsTW->setSortingEnabled(true);
2868 // Multi-selection can be annoying.
2869 // shortcutsTW->setSelectionMode(QAbstractItemView::MultiSelection);
2871 connect(bindFilePB, SIGNAL(clicked()),
2872 this, SLOT(selectBind()));
2873 connect(bindFileED, SIGNAL(textChanged(QString)),
2874 this, SIGNAL(changed()));
2876 shortcut_ = new GuiShortcutDialog(this);
2877 shortcut_bc_.setPolicy(ButtonPolicy::OkCancelPolicy);
2878 shortcut_bc_.setOK(shortcut_->buttonBox->button(QDialogButtonBox::Ok));
2879 shortcut_bc_.setCancel(shortcut_->buttonBox->button(QDialogButtonBox::Cancel));
2881 connect(shortcut_->buttonBox, SIGNAL(accepted()),
2882 this, SIGNAL(changed()));
2883 connect(shortcut_->buttonBox, SIGNAL(rejected()),
2884 shortcut_, SLOT(reject()));
2885 connect(shortcut_->clearPB, SIGNAL(clicked()),
2886 this, SLOT(shortcutClearPressed()));
2887 connect(shortcut_->removePB, SIGNAL(clicked()),
2888 this, SLOT(shortcutRemovePressed()));
2889 connect(shortcut_->buttonBox, SIGNAL(accepted()),
2890 this, SLOT(shortcutOkPressed()));
2891 connect(shortcut_->buttonBox, SIGNAL(rejected()),
2892 this, SLOT(shortcutCancelPressed()));
2896 void PrefShortcuts::applyRC(LyXRC & rc) const
2898 rc.bind_file = internal_path(fromqstr(bindFileED->text()));
2899 // write user_bind and user_unbind to .lyx/bind/user.bind
2900 FileName bind_dir(addPath(package().user_support().absFileName(), "bind"));
2901 if (!bind_dir.exists() && !bind_dir.createDirectory(0777)) {
2902 lyxerr << "LyX could not create the user bind directory '"
2903 << bind_dir << "'. All user-defined key bindings will be lost." << endl;
2906 if (!bind_dir.isDirWritable()) {
2907 lyxerr << "LyX could not write to the user bind directory '"
2908 << bind_dir << "'. All user-defined key bindings will be lost." << endl;
2911 FileName user_bind_file(bind_dir.absFileName() + "/user.bind");
2912 user_unbind_.write(user_bind_file.toFilesystemEncoding(), false, true);
2913 user_bind_.write(user_bind_file.toFilesystemEncoding(), true, false);
2914 // immediately apply the keybindings. Why this is not done before?
2915 // The good thing is that the menus are updated automatically.
2916 theTopLevelKeymap().clear();
2917 theTopLevelKeymap().read("site");
2918 theTopLevelKeymap().read(rc.bind_file, nullptr, KeyMap::Fallback);
2919 theTopLevelKeymap().read("user", nullptr, KeyMap::MissingOK);
2923 void PrefShortcuts::updateRC(LyXRC const & rc)
2925 bindFileED->setText(toqstr(external_path(rc.bind_file)));
2927 system_bind_.clear();
2929 user_unbind_.clear();
2930 system_bind_.read("site");
2931 system_bind_.read(rc.bind_file);
2932 // \unbind in user.bind is added to user_unbind_
2933 user_bind_.read("user", &user_unbind_, KeyMap::MissingOK);
2934 updateShortcutsTW();
2938 void PrefShortcuts::updateShortcutsTW()
2940 shortcutsTW->clear();
2942 editItem_ = new QTreeWidgetItem(shortcutsTW);
2943 editItem_->setText(0, qt_("Cursor, Mouse and Editing Functions"));
2944 editItem_->setFlags(editItem_->flags() & ~Qt::ItemIsSelectable);
2946 mathItem_ = new QTreeWidgetItem(shortcutsTW);
2947 mathItem_->setText(0, qt_("Mathematical Symbols"));
2948 mathItem_->setFlags(mathItem_->flags() & ~Qt::ItemIsSelectable);
2950 bufferItem_ = new QTreeWidgetItem(shortcutsTW);
2951 bufferItem_->setText(0, qt_("Document and Window"));
2952 bufferItem_->setFlags(bufferItem_->flags() & ~Qt::ItemIsSelectable);
2954 layoutItem_ = new QTreeWidgetItem(shortcutsTW);
2955 layoutItem_->setText(0, qt_("Font, Layouts and Textclasses"));
2956 layoutItem_->setFlags(layoutItem_->flags() & ~Qt::ItemIsSelectable);
2958 systemItem_ = new QTreeWidgetItem(shortcutsTW);
2959 systemItem_->setText(0, qt_("System and Miscellaneous"));
2960 systemItem_->setFlags(systemItem_->flags() & ~Qt::ItemIsSelectable);
2962 // listBindings(unbound=true) lists all bound and unbound lfuns
2963 // Items in this list is tagged by its source.
2964 KeyMap::BindingList bindinglist = system_bind_.listBindings(true,
2966 KeyMap::BindingList user_bindinglist = user_bind_.listBindings(false,
2968 KeyMap::BindingList user_unbindinglist = user_unbind_.listBindings(false,
2969 KeyMap::UserUnbind);
2970 bindinglist.insert(bindinglist.end(), user_bindinglist.begin(),
2971 user_bindinglist.end());
2972 bindinglist.insert(bindinglist.end(), user_unbindinglist.begin(),
2973 user_unbindinglist.end());
2975 KeyMap::BindingList::const_iterator it = bindinglist.begin();
2976 KeyMap::BindingList::const_iterator it_end = bindinglist.end();
2977 for (; it != it_end; ++it)
2978 insertShortcutItem(it->request, it->sequence, it->tag);
2980 shortcutsTW->sortItems(0, Qt::AscendingOrder);
2981 on_shortcutsTW_itemSelectionChanged();
2982 on_searchLE_textEdited();
2983 shortcutsTW->resizeColumnToContents(0);
2988 KeyMap::ItemType PrefShortcuts::itemType(QTreeWidgetItem & item)
2990 return static_cast<KeyMap::ItemType>(item.data(0, Qt::UserRole).toInt());
2995 bool PrefShortcuts::isAlwaysHidden(QTreeWidgetItem & item)
2997 // Hide rebound system settings that are empty
2998 return itemType(item) == KeyMap::UserUnbind && item.text(1).isEmpty();
3002 void PrefShortcuts::setItemType(QTreeWidgetItem * item, KeyMap::ItemType tag)
3004 item->setData(0, Qt::UserRole, QVariant(tag));
3008 case KeyMap::System:
3010 case KeyMap::UserBind:
3013 case KeyMap::UserUnbind:
3014 font.setStrikeOut(true);
3016 // this item is not displayed now.
3017 case KeyMap::UserExtraUnbind:
3018 font.setStrikeOut(true);
3021 item->setHidden(isAlwaysHidden(*item));
3022 item->setFont(1, font);
3026 QTreeWidgetItem * PrefShortcuts::insertShortcutItem(FuncRequest const & lfun,
3027 KeySequence const & seq, KeyMap::ItemType tag)
3029 FuncCode const action = lfun.action();
3030 string const action_name = lyxaction.getActionName(action);
3031 QString const lfun_name = toqstr(from_utf8(action_name)
3032 + ' ' + lfun.argument());
3033 QString const shortcut = toqstr(seq.print(KeySequence::ForGui));
3035 QTreeWidgetItem * newItem = nullptr;
3036 // for unbind items, try to find an existing item in the system bind list
3037 if (tag == KeyMap::UserUnbind) {
3038 QList<QTreeWidgetItem*> const items = shortcutsTW->findItems(lfun_name,
3039 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 0);
3040 for (auto const & item : items) {
3041 if (item->text(1) == shortcut) {
3046 // if not found, this unbind item is KeyMap::UserExtraUnbind
3047 // Such an item is not displayed to avoid confusion (what is
3048 // unmatched removed?).
3054 switch(lyxaction.getActionType(action)) {
3055 case LyXAction::Hidden:
3057 case LyXAction::Edit:
3058 newItem = new QTreeWidgetItem(editItem_);
3060 case LyXAction::Math:
3061 newItem = new QTreeWidgetItem(mathItem_);
3063 case LyXAction::Buffer:
3064 newItem = new QTreeWidgetItem(bufferItem_);
3066 case LyXAction::Layout:
3067 newItem = new QTreeWidgetItem(layoutItem_);
3069 case LyXAction::System:
3070 newItem = new QTreeWidgetItem(systemItem_);
3073 // this should not happen
3074 newItem = new QTreeWidgetItem(shortcutsTW);
3078 newItem->setText(0, lfun_name);
3079 newItem->setText(1, shortcut);
3080 // record BindFile representation to recover KeySequence when needed.
3081 newItem->setData(1, Qt::UserRole, toqstr(seq.print(KeySequence::BindFile)));
3082 setItemType(newItem, tag);
3087 void PrefShortcuts::on_shortcutsTW_itemSelectionChanged()
3089 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
3090 removePB->setEnabled(!items.isEmpty() && !items[0]->text(1).isEmpty());
3091 modifyPB->setEnabled(!items.isEmpty());
3092 if (items.isEmpty())
3095 if (itemType(*items[0]) == KeyMap::UserUnbind)
3096 removePB->setText(qt_("Res&tore"));
3098 removePB->setText(qt_("Remo&ve"));
3102 void PrefShortcuts::on_shortcutsTW_itemDoubleClicked()
3108 void PrefShortcuts::modifyShortcut()
3110 QTreeWidgetItem * item = shortcutsTW->currentItem();
3111 if (item->flags() & Qt::ItemIsSelectable) {
3112 shortcut_->lfunLE->setText(item->text(0));
3113 save_lfun_ = item->text(0).trimmed();
3114 shortcut_->shortcutWG->setText(item->text(1));
3116 seq.parse(fromqstr(item->data(1, Qt::UserRole).toString()));
3117 shortcut_->shortcutWG->setKeySequence(seq);
3118 shortcut_->shortcutWG->setFocus();
3124 void PrefShortcuts::unhideEmpty(QString const & lfun, bool select)
3126 // list of items that match lfun
3127 QList<QTreeWidgetItem*> items = shortcutsTW->findItems(lfun,
3128 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 0);
3129 for (auto const & item : items) {
3130 if (isAlwaysHidden(*item)) {
3131 setItemType(item, KeyMap::System);
3133 shortcutsTW->setCurrentItem(item);
3140 void PrefShortcuts::removeShortcut()
3142 // it seems that only one item can be selected, but I am
3143 // removing all selected items anyway.
3144 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
3145 for (auto & item : items) {
3146 string shortcut = fromqstr(item->data(1, Qt::UserRole).toString());
3147 string lfun = fromqstr(item->text(0));
3148 FuncRequest const func = lyxaction.lookupFunc(lfun);
3150 switch (itemType(*item)) {
3151 case KeyMap::System: {
3152 // for system bind, we do not touch the item
3153 // but add an user unbind item
3154 user_unbind_.bind(shortcut, func);
3155 setItemType(item, KeyMap::UserUnbind);
3156 removePB->setText(qt_("Res&tore"));
3159 case KeyMap::UserBind: {
3160 // for user_bind, we remove this bind
3161 QTreeWidgetItem * parent = item->parent();
3162 int itemIdx = parent->indexOfChild(item);
3163 parent->takeChild(itemIdx);
3165 shortcutsTW->scrollToItem(parent->child(itemIdx - 1));
3167 shortcutsTW->scrollToItem(parent);
3168 user_bind_.unbind(shortcut, func);
3169 // If this user binding hid an empty system binding, unhide the
3170 // latter and select it.
3171 unhideEmpty(item->text(0), true);
3174 case KeyMap::UserUnbind: {
3175 // for user_unbind, we remove the unbind, and the item
3176 // become KeyMap::System again.
3178 seq.parse(shortcut);
3179 // Ask the user to replace current binding
3180 if (!validateNewShortcut(func, seq, QString()))
3182 user_unbind_.unbind(shortcut, func);
3183 setItemType(item, KeyMap::System);
3184 removePB->setText(qt_("Remo&ve"));
3187 case KeyMap::UserExtraUnbind: {
3188 // for user unbind that is not in system bind file,
3189 // remove this unbind file
3190 QTreeWidgetItem * parent = item->parent();
3191 parent->takeChild(parent->indexOfChild(item));
3192 user_unbind_.unbind(shortcut, func);
3199 void PrefShortcuts::deactivateShortcuts(QList<QTreeWidgetItem*> const & items)
3201 for (auto item : items) {
3202 string shortcut = fromqstr(item->data(1, Qt::UserRole).toString());
3203 string lfun = fromqstr(item->text(0));
3204 FuncRequest const func = lyxaction.lookupFunc(lfun);
3206 switch (itemType(*item)) {
3207 case KeyMap::System:
3208 // for system bind, we do not touch the item
3209 // but add an user unbind item
3210 user_unbind_.bind(shortcut, func);
3211 setItemType(item, KeyMap::UserUnbind);
3214 case KeyMap::UserBind: {
3215 // for user_bind, we remove this bind
3216 QTreeWidgetItem * parent = item->parent();
3217 int itemIdx = parent->indexOfChild(item);
3218 parent->takeChild(itemIdx);
3219 user_bind_.unbind(shortcut, func);
3220 unhideEmpty(item->text(0), false);
3230 void PrefShortcuts::selectBind()
3232 QString file = form_->browsebind(internalPath(bindFileED->text()));
3233 if (!file.isEmpty()) {
3234 bindFileED->setText(file);
3235 system_bind_ = KeyMap();
3236 system_bind_.read(fromqstr(file));
3237 updateShortcutsTW();
3242 void PrefShortcuts::on_modifyPB_pressed()
3248 void PrefShortcuts::on_newPB_pressed()
3250 shortcut_->lfunLE->clear();
3251 shortcut_->shortcutWG->reset();
3252 save_lfun_ = QString();
3257 void PrefShortcuts::on_removePB_pressed()
3264 void PrefShortcuts::on_searchLE_textEdited()
3266 if (searchLE->text().isEmpty()) {
3267 // show all hidden items
3268 QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Hidden);
3270 (*it)->setHidden(isAlwaysHidden(**it));
3271 // close all categories
3272 for (int i = 0; i < shortcutsTW->topLevelItemCount(); ++i)
3273 shortcutsTW->collapseItem(shortcutsTW->topLevelItem(i));
3276 // search both columns
3277 QList<QTreeWidgetItem *> matched = shortcutsTW->findItems(searchLE->text(),
3278 Qt::MatchFlags(Qt::MatchContains | Qt::MatchRecursive), 0);
3279 matched += shortcutsTW->findItems(searchLE->text(),
3280 Qt::MatchFlags(Qt::MatchContains | Qt::MatchRecursive), 1);
3282 // hide everyone (to avoid searching in matched QList repeatedly
3283 QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Selectable);
3285 (*it++)->setHidden(true);
3286 // show matched items
3287 for (auto & item : matched)
3288 if (!isAlwaysHidden(*item)) {
3289 item->setHidden(false);
3291 item->parent()->setExpanded(true);
3296 docstring makeCmdString(FuncRequest const & f)
3298 docstring actionStr = from_ascii(lyxaction.getActionName(f.action()));
3299 if (!f.argument().empty())
3300 actionStr += " " + f.argument();
3305 FuncRequest PrefShortcuts::currentBinding(KeySequence const & k)
3307 FuncRequest res = user_bind_.getBinding(k);
3308 if (res.action() != LFUN_UNKNOWN_ACTION)
3310 res = system_bind_.getBinding(k);
3311 // Check if it is unbound. Note: user_unbind_ can only unbind one
3312 // FuncRequest per key sequence.
3313 if (user_unbind_.getBinding(k) == res)
3314 return FuncRequest::unknown;
3319 bool PrefShortcuts::validateNewShortcut(FuncRequest const & func,
3320 KeySequence const & k,
3321 QString const & lfun_to_modify)
3323 if (func.action() == LFUN_UNKNOWN_ACTION) {
3324 Alert::error(_("Failed to create shortcut"),
3325 _("Unknown or invalid LyX function"));
3329 // It is not currently possible to bind Hidden lfuns such as self-insert. In
3330 // the future, to remove this limitation, see GuiPrefs::insertShortcutItem
3331 // and how it is used in GuiPrefs::shortcutOkPressed.
3332 if (lyxaction.getActionType(func.action()) == LyXAction::Hidden) {
3333 Alert::error(_("Failed to create shortcut"),
3334 _("This LyX function is hidden and cannot be bound."));
3338 if (k.length() == 0) {
3339 Alert::error(_("Failed to create shortcut"),
3340 _("Invalid or empty key sequence"));
3344 FuncRequest oldBinding = currentBinding(k);
3345 if (oldBinding == func)
3346 // nothing to change
3349 // make sure this key isn't already bound---and, if so, prompt user
3350 // (exclude the lfun the user already wants to modify)
3351 docstring const action_string = makeCmdString(oldBinding);
3352 if (oldBinding.action() != LFUN_UNKNOWN_ACTION
3353 && lfun_to_modify != toqstr(action_string)) {
3354 docstring const new_action_string = makeCmdString(func);
3355 docstring const text = bformat(_("Shortcut `%1$s' is already bound to "
3357 "Are you sure you want to unbind the "
3358 "current shortcut and bind it to %3$s?"),
3359 k.print(KeySequence::ForGui), action_string,
3361 int ret = Alert::prompt(_("Redefine shortcut?"),
3362 text, 0, 1, _("&Redefine"), _("&Cancel"));
3365 QString const sequence_text = toqstr(k.print(KeySequence::ForGui));
3366 QList<QTreeWidgetItem*> items = shortcutsTW->findItems(sequence_text,
3367 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 1);
3368 deactivateShortcuts(items);
3374 void PrefShortcuts::shortcutOkPressed()
3376 QString const new_lfun = shortcut_->lfunLE->text();
3377 FuncRequest const func = lyxaction.lookupFunc(fromqstr(new_lfun));
3378 KeySequence k = shortcut_->shortcutWG->getKeySequence();
3380 // save_lfun_ contains the text of the lfun to modify, if the user clicked
3381 // "modify", or is empty if they clicked "new" (which I do not really like)
3382 if (!validateNewShortcut(func, k, save_lfun_))
3385 if (!save_lfun_.isEmpty()) {
3386 // real modification of the lfun's shortcut,
3387 // so remove the previous one
3388 QList<QTreeWidgetItem*> to_modify = shortcutsTW->selectedItems();
3389 deactivateShortcuts(to_modify);
3392 shortcut_->accept();
3394 QTreeWidgetItem * item = insertShortcutItem(func, k, KeyMap::UserBind);
3396 user_bind_.bind(&k, func);
3397 shortcutsTW->sortItems(0, Qt::AscendingOrder);
3398 item->parent()->setExpanded(true);
3399 shortcutsTW->setCurrentItem(item);
3400 shortcutsTW->scrollToItem(item);
3402 Alert::error(_("Failed to create shortcut"),
3403 _("Can not insert shortcut to the list"));
3409 void PrefShortcuts::shortcutCancelPressed()
3411 shortcut_->shortcutWG->reset();
3415 void PrefShortcuts::shortcutClearPressed()
3417 shortcut_->shortcutWG->reset();
3421 void PrefShortcuts::shortcutRemovePressed()
3423 shortcut_->shortcutWG->removeFromSequence();
3427 /////////////////////////////////////////////////////////////////////
3431 /////////////////////////////////////////////////////////////////////
3433 PrefIdentity::PrefIdentity(GuiPreferences * form)
3434 : PrefModule(QString(), N_("Identity"), form)
3438 connect(nameED, SIGNAL(textChanged(QString)),
3439 this, SIGNAL(changed()));
3440 connect(emailED, SIGNAL(textChanged(QString)),
3441 this, SIGNAL(changed()));
3442 connect(initialsED, SIGNAL(textChanged(QString)),
3443 this, SIGNAL(changed()));
3445 nameED->setValidator(new NoNewLineValidator(nameED));
3446 emailED->setValidator(new NoNewLineValidator(emailED));
3447 initialsED->setValidator(new NoNewLineValidator(initialsED));
3451 void PrefIdentity::applyRC(LyXRC & rc) const
3453 rc.user_name = fromqstr(nameED->text());
3454 rc.user_email = fromqstr(emailED->text());
3455 rc.user_initials = fromqstr(initialsED->text());
3459 void PrefIdentity::updateRC(LyXRC const & rc)
3461 nameED->setText(toqstr(rc.user_name));
3462 emailED->setText(toqstr(rc.user_email));
3463 initialsED->setText(toqstr(rc.user_initials));
3468 /////////////////////////////////////////////////////////////////////
3472 /////////////////////////////////////////////////////////////////////
3474 GuiPreferences::GuiPreferences(GuiView & lv)
3475 : GuiDialog(lv, "prefs", qt_("Preferences"))
3479 QDialog::setModal(false);
3481 connect(buttonBox, SIGNAL(clicked(QAbstractButton *)),
3482 this, SLOT(slotButtonBox(QAbstractButton *)));
3484 addModule(new PrefUserInterface(this));
3485 addModule(new PrefDocHandling(this));
3486 addModule(new PrefEdit(this));
3487 addModule(new PrefShortcuts(this));
3488 PrefScreenFonts * screenfonts = new PrefScreenFonts(this);
3489 connect(this, SIGNAL(prefsApplied(LyXRC const &)),
3490 screenfonts, SLOT(updateScreenFontSizes(LyXRC const &)));
3491 addModule(screenfonts);
3492 addModule(new PrefColors(this));
3493 addModule(new PrefDisplay(this));
3494 addModule(new PrefInput(this));
3495 addModule(new PrefCompletion(this));
3497 addModule(new PrefPaths(this));
3499 addModule(new PrefIdentity(this));
3501 addModule(new PrefLanguage(this));
3502 addModule(new PrefSpellchecker(this));
3504 PrefOutput * output = new PrefOutput(this);
3506 addModule(new PrefLatex(this));
3508 PrefConverters * converters = new PrefConverters(this);
3509 PrefFileformats * formats = new PrefFileformats(this);
3510 connect(formats, SIGNAL(formatsChanged()),
3511 converters, SLOT(updateGui()));
3512 addModule(converters);
3515 prefsPS->setCurrentPanel("User Interface");
3516 // FIXME: hack to work around resizing bug in Qt >= 4.2
3517 // bug verified with Qt 4.2.{0-3} (JSpitzm)
3518 #if QT_VERSION >= 0x040200
3519 prefsPS->updateGeometry();
3522 bc().setPolicy(ButtonPolicy::PreferencesPolicy);
3523 bc().setOK(buttonBox->button(QDialogButtonBox::Ok));
3524 bc().setApply(buttonBox->button(QDialogButtonBox::Apply));
3525 bc().setCancel(buttonBox->button(QDialogButtonBox::Cancel));
3526 bc().setRestore(buttonBox->button(QDialogButtonBox::Reset));
3528 guilyxfiles_ = new GuiLyXFiles(lv);
3529 connect(guilyxfiles_, SIGNAL(fileSelected(QString)),
3530 this, SLOT(slotFileSelected(QString)));
3534 void GuiPreferences::addModule(PrefModule * module)
3536 LASSERT(module, return);
3537 if (module->category().isEmpty())
3538 prefsPS->addPanel(module, module->title());
3540 prefsPS->addPanel(module, module->title(), module->category());
3541 connect(module, SIGNAL(changed()), this, SLOT(change_adaptor()));
3542 modules_.push_back(module);
3546 void GuiPreferences::change_adaptor()
3552 void GuiPreferences::applyRC(LyXRC & rc) const
3554 size_t end = modules_.size();
3555 for (size_t i = 0; i != end; ++i)
3556 modules_[i]->applyRC(rc);
3560 void GuiPreferences::updateRC(LyXRC const & rc)
3562 size_t const end = modules_.size();
3563 for (size_t i = 0; i != end; ++i)
3564 modules_[i]->updateRC(rc);
3568 void GuiPreferences::applyView()
3574 bool GuiPreferences::initialiseParams(string const &)
3577 formats_ = theFormats();
3578 converters_ = theConverters();
3579 converters_.update(formats_);
3580 movers_ = theMovers();
3584 // Make sure that the bc is in the INITIAL state
3585 if (bc().policy().buttonStatus(ButtonPolicy::RESTORE))
3592 void GuiPreferences::dispatchParams()
3595 rc_.write(ss, true);
3596 dispatch(FuncRequest(LFUN_LYXRC_APPLY, ss.str()));
3597 // issue prefsApplied signal. This will update the
3598 // localized screen font sizes.
3600 // FIXME: these need lfuns
3602 Author const & author =
3603 Author(from_utf8(rc_.user_name), from_utf8(rc_.user_email),
3604 from_utf8(rc_.user_initials));
3605 theBufferList().recordCurrentAuthor(author);
3607 theFormats() = formats_;
3609 theConverters() = converters_;
3610 theConverters().update(formats_);
3611 theConverters().buildGraph();
3612 theBufferList().invalidateConverterCache();
3614 theMovers() = movers_;
3616 for (string const & color : colors_)
3617 dispatch(FuncRequest(LFUN_SET_COLOR, color));
3621 if (!tempSaveCB->isChecked())
3622 dispatch(FuncRequest(LFUN_PREFERENCES_SAVE));
3626 void GuiPreferences::setColor(ColorCode col, QString const & hex)
3628 colors_.push_back(lcolor.getLyXName(col) + ' ' + fromqstr(hex));
3632 void GuiPreferences::slotFileSelected(QString const file)
3638 QString GuiPreferences::browseLibFile(QString const & dir,
3639 QString const & name, QString const & ext)
3643 guilyxfiles_->passParams(fromqstr(dir));
3644 guilyxfiles_->selectItem(name);
3645 guilyxfiles_->exec();
3647 QString const result = uifile_;
3649 // remove the extension if it is the default one
3650 QString noextresult;
3651 if (getExtension(result) == ext)
3652 noextresult = removeExtension(result);
3654 noextresult = result;
3656 // remove the directory, if it is the default one
3657 QString const file = onlyFileName(noextresult);
3658 if (toqstr(libFileSearch(dir, file, ext).absFileName()) == result)
3665 QString GuiPreferences::browsebind(QString const & file)
3667 return browseLibFile("bind", file, "bind");
3671 QString GuiPreferences::browseUI(QString const & file)
3673 return browseLibFile("ui", file, "ui");
3677 QString GuiPreferences::browsekbmap(QString const & file)
3679 return browseLibFile("kbd", file, "kmap");
3683 QString GuiPreferences::browse(QString const & file,
3684 QString const & title) const
3686 return browseFile(file, title, QStringList(), true);
3690 } // namespace frontend
3693 #include "moc_GuiPrefs.cpp"