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);
2457 // FIXME: restore this when it works (see discussion in #6450).
2458 respectOSkbdCB->hide();
2462 void PrefLanguage::on_uiLanguageCO_currentIndexChanged(int)
2464 QMessageBox::information(this, qt_("LyX needs to be restarted!"),
2465 qt_("The change of user interface language will be fully "
2466 "effective only after a restart."));
2470 void PrefLanguage::on_languagePackageCO_currentIndexChanged(int i)
2473 languagePackageED->setText(save_langpack_);
2474 else if (!languagePackageED->text().isEmpty()) {
2475 save_langpack_ = languagePackageED->text();
2476 languagePackageED->clear();
2478 languagePackageED->setEnabled(i == 2);
2482 void PrefLanguage::on_defaultDecimalSepCO_currentIndexChanged(int i)
2484 defaultDecimalSepED->setEnabled(i == 1);
2488 void PrefLanguage::applyRC(LyXRC & rc) const
2490 rc.visual_cursor = visualCursorRB->isChecked();
2491 rc.mark_foreign_language = markForeignCB->isChecked();
2492 rc.respect_os_kbd_language = respectOSkbdCB->isChecked();
2493 rc.language_auto_begin = !explicitDocLangBeginCB->isChecked();
2494 rc.language_auto_end = !explicitDocLangEndCB->isChecked();
2495 int const p = languagePackageCO->currentIndex();
2497 rc.language_package_selection = LyXRC::LP_AUTO;
2499 rc.language_package_selection = LyXRC::LP_BABEL;
2501 rc.language_package_selection = LyXRC::LP_CUSTOM;
2503 rc.language_package_selection = LyXRC::LP_NONE;
2504 rc.language_custom_package = fromqstr(languagePackageED->text());
2505 rc.language_global_options = globalCB->isChecked();
2506 rc.language_command_begin = fromqstr(startCommandED->text());
2507 rc.language_command_end = fromqstr(endCommandED->text());
2508 rc.gui_language = fromqstr(
2509 uiLanguageCO->itemData(uiLanguageCO->currentIndex()).toString());
2510 if (defaultDecimalSepCO->currentIndex() == 0)
2511 rc.default_decimal_sep = "locale";
2513 rc.default_decimal_sep = fromqstr(defaultDecimalSepED->text());
2514 rc.default_length_unit = (Length::UNIT) defaultLengthUnitCO->itemData(defaultLengthUnitCO->currentIndex()).toInt();
2518 void PrefLanguage::updateRC(LyXRC const & rc)
2520 if (rc.visual_cursor)
2521 visualCursorRB->setChecked(true);
2523 logicalCursorRB->setChecked(true);
2524 markForeignCB->setChecked(rc.mark_foreign_language);
2525 respectOSkbdCB->setChecked(rc.respect_os_kbd_language);
2526 explicitDocLangBeginCB->setChecked(!rc.language_auto_begin);
2527 explicitDocLangEndCB->setChecked(!rc.language_auto_end);
2528 languagePackageCO->setCurrentIndex(rc.language_package_selection);
2529 if (languagePackageCO->currentIndex() == 2) {
2530 languagePackageED->setText(toqstr(rc.language_custom_package));
2531 languagePackageED->setEnabled(true);
2533 languagePackageED->clear();
2534 save_langpack_ = toqstr(rc.language_custom_package);
2535 languagePackageED->setEnabled(false);
2537 defaultDecimalSepED->setEnabled(defaultDecimalSepCO->currentIndex() == 1);
2538 globalCB->setChecked(rc.language_global_options);
2539 startCommandED->setText(toqstr(rc.language_command_begin));
2540 endCommandED->setText(toqstr(rc.language_command_end));
2541 if (rc.default_decimal_sep == "locale") {
2542 defaultDecimalSepCO->setCurrentIndex(0);
2543 defaultDecimalSepED->clear();
2545 defaultDecimalSepCO->setCurrentIndex(1);
2546 defaultDecimalSepED->setText(toqstr(rc.default_decimal_sep));
2548 int pos = defaultLengthUnitCO->findData(int(rc.default_length_unit));
2549 defaultLengthUnitCO->setCurrentIndex(pos);
2551 pos = uiLanguageCO->findData(toqstr(rc.gui_language));
2552 uiLanguageCO->blockSignals(true);
2553 uiLanguageCO->setCurrentIndex(pos);
2554 uiLanguageCO->blockSignals(false);
2558 /////////////////////////////////////////////////////////////////////
2560 // PrefUserInterface
2562 /////////////////////////////////////////////////////////////////////
2564 PrefUserInterface::PrefUserInterface(GuiPreferences * form)
2565 : PrefModule(catLookAndFeel, N_("User Interface"), form)
2569 connect(uiFilePB, SIGNAL(clicked()),
2570 this, SLOT(selectUi()));
2571 connect(uiFileED, SIGNAL(textChanged(QString)),
2572 this, SIGNAL(changed()));
2573 connect(iconSetCO, SIGNAL(activated(int)),
2574 this, SIGNAL(changed()));
2575 connect(useSystemThemeIconsCB, SIGNAL(clicked()),
2576 this, SIGNAL(changed()));
2577 connect(lastfilesSB, SIGNAL(valueChanged(int)),
2578 this, SIGNAL(changed()));
2579 connect(tooltipCB, SIGNAL(toggled(bool)),
2580 this, SIGNAL(changed()));
2581 lastfilesSB->setMaximum(maxlastfiles);
2583 iconSetCO->addItem(qt_("Default"), QString());
2584 iconSetCO->addItem(qt_("Classic"), "classic");
2585 iconSetCO->addItem(qt_("Oxygen"), "oxygen");
2587 #if (!(defined Q_WS_X11 || defined(QPA_XCB)) || QT_VERSION < 0x040600)
2588 useSystemThemeIconsCB->hide();
2593 void PrefUserInterface::applyRC(LyXRC & rc) const
2595 rc.icon_set = fromqstr(iconSetCO->itemData(
2596 iconSetCO->currentIndex()).toString());
2598 rc.ui_file = internal_path(fromqstr(uiFileED->text()));
2599 rc.use_system_theme_icons = useSystemThemeIconsCB->isChecked();
2600 rc.num_lastfiles = lastfilesSB->value();
2601 rc.use_tooltip = tooltipCB->isChecked();
2605 void PrefUserInterface::updateRC(LyXRC const & rc)
2607 int iconset = iconSetCO->findData(toqstr(rc.icon_set));
2610 iconSetCO->setCurrentIndex(iconset);
2611 useSystemThemeIconsCB->setChecked(rc.use_system_theme_icons);
2612 uiFileED->setText(toqstr(external_path(rc.ui_file)));
2613 lastfilesSB->setValue(rc.num_lastfiles);
2614 tooltipCB->setChecked(rc.use_tooltip);
2618 void PrefUserInterface::selectUi()
2620 QString file = form_->browseUI(internalPath(uiFileED->text()));
2621 if (!file.isEmpty())
2622 uiFileED->setText(file);
2626 /////////////////////////////////////////////////////////////////////
2628 // PrefDocumentHandling
2630 /////////////////////////////////////////////////////////////////////
2632 PrefDocHandling::PrefDocHandling(GuiPreferences * form)
2633 : PrefModule(catLookAndFeel, N_("Document Handling"), form)
2637 connect(autoSaveCB, SIGNAL(toggled(bool)),
2638 autoSaveSB, SLOT(setEnabled(bool)));
2639 connect(autoSaveCB, SIGNAL(toggled(bool)),
2640 TextLabel1, SLOT(setEnabled(bool)));
2641 connect(openDocumentsInTabsCB, SIGNAL(clicked()),
2642 this, SIGNAL(changed()));
2643 connect(singleInstanceCB, SIGNAL(clicked()),
2644 this, SIGNAL(changed()));
2645 connect(singleCloseTabButtonCB, SIGNAL(clicked()),
2646 this, SIGNAL(changed()));
2647 connect(closeLastViewCO, SIGNAL(activated(int)),
2648 this, SIGNAL(changed()));
2649 connect(restoreCursorCB, SIGNAL(clicked()),
2650 this, SIGNAL(changed()));
2651 connect(loadSessionCB, SIGNAL(clicked()),
2652 this, SIGNAL(changed()));
2653 connect(allowGeometrySessionCB, SIGNAL(clicked()),
2654 this, SIGNAL(changed()));
2655 connect(autoSaveSB, SIGNAL(valueChanged(int)),
2656 this, SIGNAL(changed()));
2657 connect(autoSaveCB, SIGNAL(clicked()),
2658 this, SIGNAL(changed()));
2659 connect(backupCB, SIGNAL(clicked()),
2660 this, SIGNAL(changed()));
2661 connect(saveCompressedCB, SIGNAL(clicked()),
2662 this, SIGNAL(changed()));
2663 connect(saveOriginCB, SIGNAL(clicked()),
2664 this, SIGNAL(changed()));
2668 void PrefDocHandling::applyRC(LyXRC & rc) const
2670 rc.use_lastfilepos = restoreCursorCB->isChecked();
2671 rc.load_session = loadSessionCB->isChecked();
2672 rc.allow_geometry_session = allowGeometrySessionCB->isChecked();
2673 rc.autosave = autoSaveCB->isChecked() ? autoSaveSB->value() * 60 : 0;
2674 rc.make_backup = backupCB->isChecked();
2675 rc.save_compressed = saveCompressedCB->isChecked();
2676 rc.save_origin = saveOriginCB->isChecked();
2677 rc.open_buffers_in_tabs = openDocumentsInTabsCB->isChecked();
2678 rc.single_instance = singleInstanceCB->isChecked();
2679 rc.single_close_tab_button = singleCloseTabButtonCB->isChecked();
2681 switch (closeLastViewCO->currentIndex()) {
2683 rc.close_buffer_with_last_view = "yes";
2686 rc.close_buffer_with_last_view = "no";
2689 rc.close_buffer_with_last_view = "ask";
2697 void PrefDocHandling::updateRC(LyXRC const & rc)
2699 restoreCursorCB->setChecked(rc.use_lastfilepos);
2700 loadSessionCB->setChecked(rc.load_session);
2701 allowGeometrySessionCB->setChecked(rc.allow_geometry_session);
2702 // convert to minutes
2703 bool autosave = rc.autosave > 0;
2704 int mins = rc.autosave / 60;
2707 autoSaveSB->setValue(mins);
2708 autoSaveCB->setChecked(autosave);
2709 autoSaveSB->setEnabled(autosave);
2710 backupCB->setChecked(rc.make_backup);
2711 saveCompressedCB->setChecked(rc.save_compressed);
2712 saveOriginCB->setChecked(rc.save_origin);
2713 openDocumentsInTabsCB->setChecked(rc.open_buffers_in_tabs);
2714 singleInstanceCB->setChecked(rc.single_instance && !rc.lyxpipes.empty());
2715 singleInstanceCB->setEnabled(!rc.lyxpipes.empty());
2716 singleCloseTabButtonCB->setChecked(rc.single_close_tab_button);
2717 if (rc.close_buffer_with_last_view == "yes")
2718 closeLastViewCO->setCurrentIndex(0);
2719 else if (rc.close_buffer_with_last_view == "no")
2720 closeLastViewCO->setCurrentIndex(1);
2721 else if (rc.close_buffer_with_last_view == "ask")
2722 closeLastViewCO->setCurrentIndex(2);
2726 void PrefDocHandling::on_clearSessionPB_clicked()
2728 guiApp->clearSession();
2733 /////////////////////////////////////////////////////////////////////
2737 /////////////////////////////////////////////////////////////////////
2739 PrefEdit::PrefEdit(GuiPreferences * form)
2740 : PrefModule(catEditing, N_("Control"), form)
2744 connect(cursorFollowsCB, SIGNAL(clicked()),
2745 this, SIGNAL(changed()));
2746 connect(scrollBelowCB, SIGNAL(clicked()),
2747 this, SIGNAL(changed()));
2748 connect(macLikeCursorMovementCB, SIGNAL(clicked()),
2749 this, SIGNAL(changed()));
2750 connect(copyCTMarkupCB, SIGNAL(clicked()),
2751 this, SIGNAL(changed()));
2752 connect(sortEnvironmentsCB, SIGNAL(clicked()),
2753 this, SIGNAL(changed()));
2754 connect(groupEnvironmentsCB, SIGNAL(clicked()),
2755 this, SIGNAL(changed()));
2756 connect(macroEditStyleCO, SIGNAL(activated(int)),
2757 this, SIGNAL(changed()));
2758 connect(cursorWidthSB, SIGNAL(valueChanged(int)),
2759 this, SIGNAL(changed()));
2760 connect(citationSearchLE, SIGNAL(textChanged(QString)),
2761 this, SIGNAL(changed()));
2762 connect(fullscreenWidthSB, SIGNAL(valueChanged(int)),
2763 this, SIGNAL(changed()));
2764 connect(toggleTabbarCB, SIGNAL(toggled(bool)),
2765 this, SIGNAL(changed()));
2766 connect(toggleMenubarCB, SIGNAL(toggled(bool)),
2767 this, SIGNAL(changed()));
2768 connect(toggleScrollbarCB, SIGNAL(toggled(bool)),
2769 this, SIGNAL(changed()));
2770 connect(toggleStatusbarCB, SIGNAL(toggled(bool)),
2771 this, SIGNAL(changed()));
2772 connect(toggleToolbarsCB, SIGNAL(toggled(bool)),
2773 this, SIGNAL(changed()));
2777 void PrefEdit::on_fullscreenLimitCB_toggled(bool const state)
2779 fullscreenWidthSB->setEnabled(state);
2780 fullscreenWidthLA->setEnabled(state);
2785 void PrefEdit::on_citationSearchCB_toggled(bool const state)
2787 citationSearchLE->setEnabled(state);
2788 citationSearchLA->setEnabled(state);
2793 void PrefEdit::applyRC(LyXRC & rc) const
2795 rc.cursor_follows_scrollbar = cursorFollowsCB->isChecked();
2796 rc.scroll_below_document = scrollBelowCB->isChecked();
2797 rc.mac_like_cursor_movement = macLikeCursorMovementCB->isChecked();
2798 rc.ct_markup_copied = copyCTMarkupCB->isChecked();
2799 rc.sort_layouts = sortEnvironmentsCB->isChecked();
2800 rc.group_layouts = groupEnvironmentsCB->isChecked();
2801 switch (macroEditStyleCO->currentIndex()) {
2802 case 0: rc.macro_edit_style = LyXRC::MACRO_EDIT_INLINE_BOX; break;
2803 case 1: rc.macro_edit_style = LyXRC::MACRO_EDIT_INLINE; break;
2804 case 2: rc.macro_edit_style = LyXRC::MACRO_EDIT_LIST; break;
2806 rc.cursor_width = cursorWidthSB->value();
2807 rc.citation_search = citationSearchCB->isChecked();
2808 rc.citation_search_pattern = fromqstr(citationSearchLE->text());
2809 rc.full_screen_toolbars = toggleToolbarsCB->isChecked();
2810 rc.full_screen_scrollbar = toggleScrollbarCB->isChecked();
2811 rc.full_screen_statusbar = toggleStatusbarCB->isChecked();
2812 rc.full_screen_tabbar = toggleTabbarCB->isChecked();
2813 rc.full_screen_menubar = toggleMenubarCB->isChecked();
2814 rc.full_screen_width = fullscreenWidthSB->value();
2815 rc.full_screen_limit = fullscreenLimitCB->isChecked();
2819 void PrefEdit::updateRC(LyXRC const & rc)
2821 cursorFollowsCB->setChecked(rc.cursor_follows_scrollbar);
2822 scrollBelowCB->setChecked(rc.scroll_below_document);
2823 macLikeCursorMovementCB->setChecked(rc.mac_like_cursor_movement);
2824 copyCTMarkupCB->setChecked(rc.ct_markup_copied);
2825 sortEnvironmentsCB->setChecked(rc.sort_layouts);
2826 groupEnvironmentsCB->setChecked(rc.group_layouts);
2827 macroEditStyleCO->setCurrentIndex(rc.macro_edit_style);
2828 cursorWidthSB->setValue(rc.cursor_width);
2829 citationSearchCB->setChecked(rc.citation_search);
2830 citationSearchLE->setText(toqstr(rc.citation_search_pattern));
2831 citationSearchLE->setEnabled(rc.citation_search);
2832 citationSearchLA->setEnabled(rc.citation_search);
2833 toggleScrollbarCB->setChecked(rc.full_screen_scrollbar);
2834 toggleStatusbarCB->setChecked(rc.full_screen_statusbar);
2835 toggleToolbarsCB->setChecked(rc.full_screen_toolbars);
2836 toggleTabbarCB->setChecked(rc.full_screen_tabbar);
2837 toggleMenubarCB->setChecked(rc.full_screen_menubar);
2838 fullscreenWidthSB->setValue(rc.full_screen_width);
2839 fullscreenLimitCB->setChecked(rc.full_screen_limit);
2840 fullscreenWidthSB->setEnabled(rc.full_screen_limit);
2841 fullscreenWidthLA->setEnabled(rc.full_screen_limit);
2845 /////////////////////////////////////////////////////////////////////
2849 /////////////////////////////////////////////////////////////////////
2852 GuiShortcutDialog::GuiShortcutDialog(QWidget * parent) : QDialog(parent)
2854 Ui::shortcutUi::setupUi(this);
2855 QDialog::setModal(true);
2856 lfunLE->setValidator(new NoNewLineValidator(lfunLE));
2860 PrefShortcuts::PrefShortcuts(GuiPreferences * form)
2861 : PrefModule(catEditing, N_("Shortcuts"), form),
2862 editItem_(nullptr), mathItem_(nullptr), bufferItem_(nullptr), layoutItem_(nullptr),
2863 systemItem_(nullptr)
2867 shortcutsTW->setColumnCount(2);
2868 shortcutsTW->headerItem()->setText(0, qt_("Function"));
2869 shortcutsTW->headerItem()->setText(1, qt_("Shortcut"));
2870 shortcutsTW->setSortingEnabled(true);
2871 // Multi-selection can be annoying.
2872 // shortcutsTW->setSelectionMode(QAbstractItemView::MultiSelection);
2874 connect(bindFilePB, SIGNAL(clicked()),
2875 this, SLOT(selectBind()));
2876 connect(bindFileED, SIGNAL(textChanged(QString)),
2877 this, SIGNAL(changed()));
2879 shortcut_ = new GuiShortcutDialog(this);
2880 shortcut_bc_.setPolicy(ButtonPolicy::OkCancelPolicy);
2881 shortcut_bc_.setOK(shortcut_->buttonBox->button(QDialogButtonBox::Ok));
2882 shortcut_bc_.setCancel(shortcut_->buttonBox->button(QDialogButtonBox::Cancel));
2884 connect(shortcut_->buttonBox, SIGNAL(accepted()),
2885 this, SIGNAL(changed()));
2886 connect(shortcut_->buttonBox, SIGNAL(rejected()),
2887 shortcut_, SLOT(reject()));
2888 connect(shortcut_->clearPB, SIGNAL(clicked()),
2889 this, SLOT(shortcutClearPressed()));
2890 connect(shortcut_->removePB, SIGNAL(clicked()),
2891 this, SLOT(shortcutRemovePressed()));
2892 connect(shortcut_->buttonBox, SIGNAL(accepted()),
2893 this, SLOT(shortcutOkPressed()));
2894 connect(shortcut_->buttonBox, SIGNAL(rejected()),
2895 this, SLOT(shortcutCancelPressed()));
2899 void PrefShortcuts::applyRC(LyXRC & rc) const
2901 rc.bind_file = internal_path(fromqstr(bindFileED->text()));
2902 // write user_bind and user_unbind to .lyx/bind/user.bind
2903 FileName bind_dir(addPath(package().user_support().absFileName(), "bind"));
2904 if (!bind_dir.exists() && !bind_dir.createDirectory(0777)) {
2905 lyxerr << "LyX could not create the user bind directory '"
2906 << bind_dir << "'. All user-defined key bindings will be lost." << endl;
2909 if (!bind_dir.isDirWritable()) {
2910 lyxerr << "LyX could not write to the user bind directory '"
2911 << bind_dir << "'. All user-defined key bindings will be lost." << endl;
2914 FileName user_bind_file(bind_dir.absFileName() + "/user.bind");
2915 user_unbind_.write(user_bind_file.toFilesystemEncoding(), false, true);
2916 user_bind_.write(user_bind_file.toFilesystemEncoding(), true, false);
2917 // immediately apply the keybindings. Why this is not done before?
2918 // The good thing is that the menus are updated automatically.
2919 theTopLevelKeymap().clear();
2920 theTopLevelKeymap().read("site");
2921 theTopLevelKeymap().read(rc.bind_file, nullptr, KeyMap::Fallback);
2922 theTopLevelKeymap().read("user", nullptr, KeyMap::MissingOK);
2926 void PrefShortcuts::updateRC(LyXRC const & rc)
2928 bindFileED->setText(toqstr(external_path(rc.bind_file)));
2930 system_bind_.clear();
2932 user_unbind_.clear();
2933 system_bind_.read("site");
2934 system_bind_.read(rc.bind_file);
2935 // \unbind in user.bind is added to user_unbind_
2936 user_bind_.read("user", &user_unbind_, KeyMap::MissingOK);
2937 updateShortcutsTW();
2941 void PrefShortcuts::updateShortcutsTW()
2943 shortcutsTW->clear();
2945 editItem_ = new QTreeWidgetItem(shortcutsTW);
2946 editItem_->setText(0, qt_("Cursor, Mouse and Editing Functions"));
2947 editItem_->setFlags(editItem_->flags() & ~Qt::ItemIsSelectable);
2949 mathItem_ = new QTreeWidgetItem(shortcutsTW);
2950 mathItem_->setText(0, qt_("Mathematical Symbols"));
2951 mathItem_->setFlags(mathItem_->flags() & ~Qt::ItemIsSelectable);
2953 bufferItem_ = new QTreeWidgetItem(shortcutsTW);
2954 bufferItem_->setText(0, qt_("Document and Window"));
2955 bufferItem_->setFlags(bufferItem_->flags() & ~Qt::ItemIsSelectable);
2957 layoutItem_ = new QTreeWidgetItem(shortcutsTW);
2958 layoutItem_->setText(0, qt_("Font, Layouts and Textclasses"));
2959 layoutItem_->setFlags(layoutItem_->flags() & ~Qt::ItemIsSelectable);
2961 systemItem_ = new QTreeWidgetItem(shortcutsTW);
2962 systemItem_->setText(0, qt_("System and Miscellaneous"));
2963 systemItem_->setFlags(systemItem_->flags() & ~Qt::ItemIsSelectable);
2965 // listBindings(unbound=true) lists all bound and unbound lfuns
2966 // Items in this list is tagged by its source.
2967 KeyMap::BindingList bindinglist = system_bind_.listBindings(true,
2969 KeyMap::BindingList user_bindinglist = user_bind_.listBindings(false,
2971 KeyMap::BindingList user_unbindinglist = user_unbind_.listBindings(false,
2972 KeyMap::UserUnbind);
2973 bindinglist.insert(bindinglist.end(), user_bindinglist.begin(),
2974 user_bindinglist.end());
2975 bindinglist.insert(bindinglist.end(), user_unbindinglist.begin(),
2976 user_unbindinglist.end());
2978 KeyMap::BindingList::const_iterator it = bindinglist.begin();
2979 KeyMap::BindingList::const_iterator it_end = bindinglist.end();
2980 for (; it != it_end; ++it)
2981 insertShortcutItem(it->request, it->sequence, it->tag);
2983 shortcutsTW->sortItems(0, Qt::AscendingOrder);
2984 on_shortcutsTW_itemSelectionChanged();
2985 on_searchLE_textEdited();
2986 shortcutsTW->resizeColumnToContents(0);
2991 KeyMap::ItemType PrefShortcuts::itemType(QTreeWidgetItem & item)
2993 return static_cast<KeyMap::ItemType>(item.data(0, Qt::UserRole).toInt());
2998 bool PrefShortcuts::isAlwaysHidden(QTreeWidgetItem & item)
3000 // Hide rebound system settings that are empty
3001 return itemType(item) == KeyMap::UserUnbind && item.text(1).isEmpty();
3005 void PrefShortcuts::setItemType(QTreeWidgetItem * item, KeyMap::ItemType tag)
3007 item->setData(0, Qt::UserRole, QVariant(tag));
3011 case KeyMap::System:
3013 case KeyMap::UserBind:
3016 case KeyMap::UserUnbind:
3017 font.setStrikeOut(true);
3019 // this item is not displayed now.
3020 case KeyMap::UserExtraUnbind:
3021 font.setStrikeOut(true);
3024 item->setHidden(isAlwaysHidden(*item));
3025 item->setFont(1, font);
3029 QTreeWidgetItem * PrefShortcuts::insertShortcutItem(FuncRequest const & lfun,
3030 KeySequence const & seq, KeyMap::ItemType tag)
3032 FuncCode const action = lfun.action();
3033 string const action_name = lyxaction.getActionName(action);
3034 QString const lfun_name = toqstr(from_utf8(action_name)
3035 + ' ' + lfun.argument());
3036 QString const shortcut = toqstr(seq.print(KeySequence::ForGui));
3038 QTreeWidgetItem * newItem = nullptr;
3039 // for unbind items, try to find an existing item in the system bind list
3040 if (tag == KeyMap::UserUnbind) {
3041 QList<QTreeWidgetItem*> const items = shortcutsTW->findItems(lfun_name,
3042 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 0);
3043 for (auto const & item : items) {
3044 if (item->text(1) == shortcut) {
3049 // if not found, this unbind item is KeyMap::UserExtraUnbind
3050 // Such an item is not displayed to avoid confusion (what is
3051 // unmatched removed?).
3057 switch(lyxaction.getActionType(action)) {
3058 case LyXAction::Hidden:
3060 case LyXAction::Edit:
3061 newItem = new QTreeWidgetItem(editItem_);
3063 case LyXAction::Math:
3064 newItem = new QTreeWidgetItem(mathItem_);
3066 case LyXAction::Buffer:
3067 newItem = new QTreeWidgetItem(bufferItem_);
3069 case LyXAction::Layout:
3070 newItem = new QTreeWidgetItem(layoutItem_);
3072 case LyXAction::System:
3073 newItem = new QTreeWidgetItem(systemItem_);
3076 // this should not happen
3077 newItem = new QTreeWidgetItem(shortcutsTW);
3081 newItem->setText(0, lfun_name);
3082 newItem->setText(1, shortcut);
3083 // record BindFile representation to recover KeySequence when needed.
3084 newItem->setData(1, Qt::UserRole, toqstr(seq.print(KeySequence::BindFile)));
3085 setItemType(newItem, tag);
3090 void PrefShortcuts::on_shortcutsTW_itemSelectionChanged()
3092 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
3093 removePB->setEnabled(!items.isEmpty() && !items[0]->text(1).isEmpty());
3094 modifyPB->setEnabled(!items.isEmpty());
3095 if (items.isEmpty())
3098 if (itemType(*items[0]) == KeyMap::UserUnbind)
3099 removePB->setText(qt_("Res&tore"));
3101 removePB->setText(qt_("Remo&ve"));
3105 void PrefShortcuts::on_shortcutsTW_itemDoubleClicked()
3111 void PrefShortcuts::modifyShortcut()
3113 QTreeWidgetItem * item = shortcutsTW->currentItem();
3114 if (item->flags() & Qt::ItemIsSelectable) {
3115 shortcut_->lfunLE->setText(item->text(0));
3116 save_lfun_ = item->text(0).trimmed();
3117 shortcut_->shortcutWG->setText(item->text(1));
3119 seq.parse(fromqstr(item->data(1, Qt::UserRole).toString()));
3120 shortcut_->shortcutWG->setKeySequence(seq);
3121 shortcut_->shortcutWG->setFocus();
3127 void PrefShortcuts::unhideEmpty(QString const & lfun, bool select)
3129 // list of items that match lfun
3130 QList<QTreeWidgetItem*> items = shortcutsTW->findItems(lfun,
3131 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 0);
3132 for (auto const & item : items) {
3133 if (isAlwaysHidden(*item)) {
3134 setItemType(item, KeyMap::System);
3136 shortcutsTW->setCurrentItem(item);
3143 void PrefShortcuts::removeShortcut()
3145 // it seems that only one item can be selected, but I am
3146 // removing all selected items anyway.
3147 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
3148 for (auto & item : items) {
3149 string shortcut = fromqstr(item->data(1, Qt::UserRole).toString());
3150 string lfun = fromqstr(item->text(0));
3151 FuncRequest const func = lyxaction.lookupFunc(lfun);
3153 switch (itemType(*item)) {
3154 case KeyMap::System: {
3155 // for system bind, we do not touch the item
3156 // but add an user unbind item
3157 user_unbind_.bind(shortcut, func);
3158 setItemType(item, KeyMap::UserUnbind);
3159 removePB->setText(qt_("Res&tore"));
3162 case KeyMap::UserBind: {
3163 // for user_bind, we remove this bind
3164 QTreeWidgetItem * parent = item->parent();
3165 int itemIdx = parent->indexOfChild(item);
3166 parent->takeChild(itemIdx);
3168 shortcutsTW->scrollToItem(parent->child(itemIdx - 1));
3170 shortcutsTW->scrollToItem(parent);
3171 user_bind_.unbind(shortcut, func);
3172 // If this user binding hid an empty system binding, unhide the
3173 // latter and select it.
3174 unhideEmpty(item->text(0), true);
3177 case KeyMap::UserUnbind: {
3178 // for user_unbind, we remove the unbind, and the item
3179 // become KeyMap::System again.
3181 seq.parse(shortcut);
3182 // Ask the user to replace current binding
3183 if (!validateNewShortcut(func, seq, QString()))
3185 user_unbind_.unbind(shortcut, func);
3186 setItemType(item, KeyMap::System);
3187 removePB->setText(qt_("Remo&ve"));
3190 case KeyMap::UserExtraUnbind: {
3191 // for user unbind that is not in system bind file,
3192 // remove this unbind file
3193 QTreeWidgetItem * parent = item->parent();
3194 parent->takeChild(parent->indexOfChild(item));
3195 user_unbind_.unbind(shortcut, func);
3202 void PrefShortcuts::deactivateShortcuts(QList<QTreeWidgetItem*> const & items)
3204 for (auto item : items) {
3205 string shortcut = fromqstr(item->data(1, Qt::UserRole).toString());
3206 string lfun = fromqstr(item->text(0));
3207 FuncRequest const func = lyxaction.lookupFunc(lfun);
3209 switch (itemType(*item)) {
3210 case KeyMap::System:
3211 // for system bind, we do not touch the item
3212 // but add an user unbind item
3213 user_unbind_.bind(shortcut, func);
3214 setItemType(item, KeyMap::UserUnbind);
3217 case KeyMap::UserBind: {
3218 // for user_bind, we remove this bind
3219 QTreeWidgetItem * parent = item->parent();
3220 int itemIdx = parent->indexOfChild(item);
3221 parent->takeChild(itemIdx);
3222 user_bind_.unbind(shortcut, func);
3223 unhideEmpty(item->text(0), false);
3233 void PrefShortcuts::selectBind()
3235 QString file = form_->browsebind(internalPath(bindFileED->text()));
3236 if (!file.isEmpty()) {
3237 bindFileED->setText(file);
3238 system_bind_ = KeyMap();
3239 system_bind_.read(fromqstr(file));
3240 updateShortcutsTW();
3245 void PrefShortcuts::on_modifyPB_pressed()
3251 void PrefShortcuts::on_newPB_pressed()
3253 shortcut_->lfunLE->clear();
3254 shortcut_->shortcutWG->reset();
3255 save_lfun_ = QString();
3260 void PrefShortcuts::on_removePB_pressed()
3267 void PrefShortcuts::on_searchLE_textEdited()
3269 if (searchLE->text().isEmpty()) {
3270 // show all hidden items
3271 QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Hidden);
3273 (*it)->setHidden(isAlwaysHidden(**it));
3274 // close all categories
3275 for (int i = 0; i < shortcutsTW->topLevelItemCount(); ++i)
3276 shortcutsTW->collapseItem(shortcutsTW->topLevelItem(i));
3279 // search both columns
3280 QList<QTreeWidgetItem *> matched = shortcutsTW->findItems(searchLE->text(),
3281 Qt::MatchFlags(Qt::MatchContains | Qt::MatchRecursive), 0);
3282 matched += shortcutsTW->findItems(searchLE->text(),
3283 Qt::MatchFlags(Qt::MatchContains | Qt::MatchRecursive), 1);
3285 // hide everyone (to avoid searching in matched QList repeatedly
3286 QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Selectable);
3288 (*it++)->setHidden(true);
3289 // show matched items
3290 for (auto & item : matched)
3291 if (!isAlwaysHidden(*item)) {
3292 item->setHidden(false);
3294 item->parent()->setExpanded(true);
3299 docstring makeCmdString(FuncRequest const & f)
3301 docstring actionStr = from_ascii(lyxaction.getActionName(f.action()));
3302 if (!f.argument().empty())
3303 actionStr += " " + f.argument();
3308 FuncRequest PrefShortcuts::currentBinding(KeySequence const & k)
3310 FuncRequest res = user_bind_.getBinding(k);
3311 if (res.action() != LFUN_UNKNOWN_ACTION)
3313 res = system_bind_.getBinding(k);
3314 // Check if it is unbound. Note: user_unbind_ can only unbind one
3315 // FuncRequest per key sequence.
3316 if (user_unbind_.getBinding(k) == res)
3317 return FuncRequest::unknown;
3322 bool PrefShortcuts::validateNewShortcut(FuncRequest const & func,
3323 KeySequence const & k,
3324 QString const & lfun_to_modify)
3326 if (func.action() == LFUN_UNKNOWN_ACTION) {
3327 Alert::error(_("Failed to create shortcut"),
3328 _("Unknown or invalid LyX function"));
3332 // It is not currently possible to bind Hidden lfuns such as self-insert. In
3333 // the future, to remove this limitation, see GuiPrefs::insertShortcutItem
3334 // and how it is used in GuiPrefs::shortcutOkPressed.
3335 if (lyxaction.getActionType(func.action()) == LyXAction::Hidden) {
3336 Alert::error(_("Failed to create shortcut"),
3337 _("This LyX function is hidden and cannot be bound."));
3341 if (k.length() == 0) {
3342 Alert::error(_("Failed to create shortcut"),
3343 _("Invalid or empty key sequence"));
3347 FuncRequest oldBinding = currentBinding(k);
3348 if (oldBinding == func)
3349 // nothing to change
3352 // make sure this key isn't already bound---and, if so, prompt user
3353 // (exclude the lfun the user already wants to modify)
3354 docstring const action_string = makeCmdString(oldBinding);
3355 if (oldBinding.action() != LFUN_UNKNOWN_ACTION
3356 && lfun_to_modify != toqstr(action_string)) {
3357 docstring const new_action_string = makeCmdString(func);
3358 docstring const text = bformat(_("Shortcut `%1$s' is already bound to "
3360 "Are you sure you want to unbind the "
3361 "current shortcut and bind it to %3$s?"),
3362 k.print(KeySequence::ForGui), action_string,
3364 int ret = Alert::prompt(_("Redefine shortcut?"),
3365 text, 0, 1, _("&Redefine"), _("&Cancel"));
3368 QString const sequence_text = toqstr(k.print(KeySequence::ForGui));
3369 QList<QTreeWidgetItem*> items = shortcutsTW->findItems(sequence_text,
3370 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 1);
3371 deactivateShortcuts(items);
3377 void PrefShortcuts::shortcutOkPressed()
3379 QString const new_lfun = shortcut_->lfunLE->text();
3380 FuncRequest const func = lyxaction.lookupFunc(fromqstr(new_lfun));
3381 KeySequence k = shortcut_->shortcutWG->getKeySequence();
3383 // save_lfun_ contains the text of the lfun to modify, if the user clicked
3384 // "modify", or is empty if they clicked "new" (which I do not really like)
3385 if (!validateNewShortcut(func, k, save_lfun_))
3388 if (!save_lfun_.isEmpty()) {
3389 // real modification of the lfun's shortcut,
3390 // so remove the previous one
3391 QList<QTreeWidgetItem*> to_modify = shortcutsTW->selectedItems();
3392 deactivateShortcuts(to_modify);
3395 shortcut_->accept();
3397 QTreeWidgetItem * item = insertShortcutItem(func, k, KeyMap::UserBind);
3399 user_bind_.bind(&k, func);
3400 shortcutsTW->sortItems(0, Qt::AscendingOrder);
3401 item->parent()->setExpanded(true);
3402 shortcutsTW->setCurrentItem(item);
3403 shortcutsTW->scrollToItem(item);
3405 Alert::error(_("Failed to create shortcut"),
3406 _("Can not insert shortcut to the list"));
3412 void PrefShortcuts::shortcutCancelPressed()
3414 shortcut_->shortcutWG->reset();
3418 void PrefShortcuts::shortcutClearPressed()
3420 shortcut_->shortcutWG->reset();
3424 void PrefShortcuts::shortcutRemovePressed()
3426 shortcut_->shortcutWG->removeFromSequence();
3430 /////////////////////////////////////////////////////////////////////
3434 /////////////////////////////////////////////////////////////////////
3436 PrefIdentity::PrefIdentity(GuiPreferences * form)
3437 : PrefModule(QString(), N_("Identity"), form)
3441 connect(nameED, SIGNAL(textChanged(QString)),
3442 this, SIGNAL(changed()));
3443 connect(emailED, SIGNAL(textChanged(QString)),
3444 this, SIGNAL(changed()));
3445 connect(initialsED, SIGNAL(textChanged(QString)),
3446 this, SIGNAL(changed()));
3448 nameED->setValidator(new NoNewLineValidator(nameED));
3449 emailED->setValidator(new NoNewLineValidator(emailED));
3450 initialsED->setValidator(new NoNewLineValidator(initialsED));
3454 void PrefIdentity::applyRC(LyXRC & rc) const
3456 rc.user_name = fromqstr(nameED->text());
3457 rc.user_email = fromqstr(emailED->text());
3458 rc.user_initials = fromqstr(initialsED->text());
3462 void PrefIdentity::updateRC(LyXRC const & rc)
3464 nameED->setText(toqstr(rc.user_name));
3465 emailED->setText(toqstr(rc.user_email));
3466 initialsED->setText(toqstr(rc.user_initials));
3471 /////////////////////////////////////////////////////////////////////
3475 /////////////////////////////////////////////////////////////////////
3477 GuiPreferences::GuiPreferences(GuiView & lv)
3478 : GuiDialog(lv, "prefs", qt_("Preferences"))
3482 QDialog::setModal(false);
3484 connect(buttonBox, SIGNAL(clicked(QAbstractButton *)),
3485 this, SLOT(slotButtonBox(QAbstractButton *)));
3487 addModule(new PrefUserInterface(this));
3488 addModule(new PrefDocHandling(this));
3489 addModule(new PrefEdit(this));
3490 addModule(new PrefShortcuts(this));
3491 PrefScreenFonts * screenfonts = new PrefScreenFonts(this);
3492 connect(this, SIGNAL(prefsApplied(LyXRC const &)),
3493 screenfonts, SLOT(updateScreenFontSizes(LyXRC const &)));
3494 addModule(screenfonts);
3495 addModule(new PrefColors(this));
3496 addModule(new PrefDisplay(this));
3497 addModule(new PrefInput(this));
3498 addModule(new PrefCompletion(this));
3500 addModule(new PrefPaths(this));
3502 addModule(new PrefIdentity(this));
3504 addModule(new PrefLanguage(this));
3505 addModule(new PrefSpellchecker(this));
3507 PrefOutput * output = new PrefOutput(this);
3509 addModule(new PrefLatex(this));
3511 PrefConverters * converters = new PrefConverters(this);
3512 PrefFileformats * formats = new PrefFileformats(this);
3513 connect(formats, SIGNAL(formatsChanged()),
3514 converters, SLOT(updateGui()));
3515 addModule(converters);
3518 prefsPS->setCurrentPanel("User Interface");
3519 // FIXME: hack to work around resizing bug in Qt >= 4.2
3520 // bug verified with Qt 4.2.{0-3} (JSpitzm)
3521 #if QT_VERSION >= 0x040200
3522 prefsPS->updateGeometry();
3525 bc().setPolicy(ButtonPolicy::PreferencesPolicy);
3526 bc().setOK(buttonBox->button(QDialogButtonBox::Ok));
3527 bc().setApply(buttonBox->button(QDialogButtonBox::Apply));
3528 bc().setCancel(buttonBox->button(QDialogButtonBox::Cancel));
3529 bc().setRestore(buttonBox->button(QDialogButtonBox::Reset));
3531 guilyxfiles_ = new GuiLyXFiles(lv);
3532 connect(guilyxfiles_, SIGNAL(fileSelected(QString)),
3533 this, SLOT(slotFileSelected(QString)));
3537 void GuiPreferences::addModule(PrefModule * module)
3539 LASSERT(module, return);
3540 if (module->category().isEmpty())
3541 prefsPS->addPanel(module, module->title());
3543 prefsPS->addPanel(module, module->title(), module->category());
3544 connect(module, SIGNAL(changed()), this, SLOT(change_adaptor()));
3545 modules_.push_back(module);
3549 void GuiPreferences::change_adaptor()
3555 void GuiPreferences::applyRC(LyXRC & rc) const
3557 size_t end = modules_.size();
3558 for (size_t i = 0; i != end; ++i)
3559 modules_[i]->applyRC(rc);
3563 void GuiPreferences::updateRC(LyXRC const & rc)
3565 size_t const end = modules_.size();
3566 for (size_t i = 0; i != end; ++i)
3567 modules_[i]->updateRC(rc);
3571 void GuiPreferences::applyView()
3577 bool GuiPreferences::initialiseParams(string const &)
3580 formats_ = theFormats();
3581 converters_ = theConverters();
3582 converters_.update(formats_);
3583 movers_ = theMovers();
3587 // Make sure that the bc is in the INITIAL state
3588 if (bc().policy().buttonStatus(ButtonPolicy::RESTORE))
3595 void GuiPreferences::dispatchParams()
3598 rc_.write(ss, true);
3599 dispatch(FuncRequest(LFUN_LYXRC_APPLY, ss.str()));
3600 // issue prefsApplied signal. This will update the
3601 // localized screen font sizes.
3603 // FIXME: these need lfuns
3605 Author const & author =
3606 Author(from_utf8(rc_.user_name), from_utf8(rc_.user_email),
3607 from_utf8(rc_.user_initials));
3608 theBufferList().recordCurrentAuthor(author);
3610 theFormats() = formats_;
3612 theConverters() = converters_;
3613 theConverters().update(formats_);
3614 theConverters().buildGraph();
3615 theBufferList().invalidateConverterCache();
3617 theMovers() = movers_;
3619 for (string const & color : colors_)
3620 dispatch(FuncRequest(LFUN_SET_COLOR, color));
3624 if (!tempSaveCB->isChecked())
3625 dispatch(FuncRequest(LFUN_PREFERENCES_SAVE));
3629 void GuiPreferences::setColor(ColorCode col, QString const & hex)
3631 colors_.push_back(lcolor.getLyXName(col) + ' ' + fromqstr(hex));
3635 void GuiPreferences::slotFileSelected(QString const file)
3641 QString GuiPreferences::browseLibFile(QString const & dir,
3642 QString const & name, QString const & ext)
3646 guilyxfiles_->passParams(fromqstr(dir));
3647 guilyxfiles_->selectItem(name);
3648 guilyxfiles_->exec();
3650 QString const result = uifile_;
3652 // remove the extension if it is the default one
3653 QString noextresult;
3654 if (getExtension(result) == ext)
3655 noextresult = removeExtension(result);
3657 noextresult = result;
3659 // remove the directory, if it is the default one
3660 QString const file = onlyFileName(noextresult);
3661 if (toqstr(libFileSearch(dir, file, ext).absFileName()) == result)
3668 QString GuiPreferences::browsebind(QString const & file)
3670 return browseLibFile("bind", file, "bind");
3674 QString GuiPreferences::browseUI(QString const & file)
3676 return browseLibFile("ui", file, "ui");
3680 QString GuiPreferences::browsekbmap(QString const & file)
3682 return browseLibFile("kbd", file, "kmap");
3686 QString GuiPreferences::browse(QString const & file,
3687 QString const & title) const
3689 return browseFile(file, title, QStringList(), true);
3693 } // namespace frontend
3696 #include "moc_GuiPrefs.cpp"