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 "LengthCombo.h"
37 #include "LyXAction.h"
39 #include "PanelStack.h"
41 #include "SpellChecker.h"
43 #include "support/debug.h"
44 #include "support/FileName.h"
45 #include "support/filetools.h"
46 #include "support/gettext.h"
47 #include "support/lassert.h"
48 #include "support/lstrings.h"
49 #include "support/Messages.h"
50 #include "support/os.h"
51 #include "support/Package.h"
53 #include "frontends/alert.h"
54 #include "frontends/Application.h"
55 #include "frontends/FontLoader.h"
57 #include <QAbstractItemModel>
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;
83 /////////////////////////////////////////////////////////////////////
87 /////////////////////////////////////////////////////////////////////
91 QString const catLookAndFeel = N_("Look & Feel");
92 QString const catEditing = N_("Editing");
93 QString const catLanguage = N_("Language Settings");
94 QString const catOutput = N_("Output");
95 QString const catFiles = N_("File Handling");
97 static void parseFontName(QString const & mangled0,
98 string & name, string & foundry)
100 string mangled = fromqstr(mangled0);
101 size_t const idx = mangled.find('[');
102 if (idx == string::npos || idx == 0) {
106 name = mangled.substr(0, idx - 1);
107 foundry = mangled.substr(idx + 1, mangled.size() - idx - 2);
112 static void setComboxFont(QComboBox * cb, string const & family,
113 string const & foundry)
115 QString fontname = toqstr(family);
116 if (!foundry.empty())
117 fontname += " [" + toqstr(foundry) + ']';
119 for (int i = 0; i != cb->count(); ++i) {
120 if (cb->itemText(i) == fontname) {
121 cb->setCurrentIndex(i);
126 // Try matching without foundry name
128 // We count in reverse in order to prefer the Xft foundry
129 for (int i = cb->count(); --i >= 0;) {
130 string name, fnt_foundry;
131 parseFontName(cb->itemText(i), name, fnt_foundry);
132 if (compare_ascii_no_case(name, family) == 0) {
133 cb->setCurrentIndex(i);
138 // family alone can contain e.g. "Helvetica [Adobe]"
139 string tmpname, tmpfoundry;
140 parseFontName(toqstr(family), tmpname, tmpfoundry);
142 // We count in reverse in order to prefer the Xft foundry
143 for (int i = cb->count(); --i >= 0; ) {
144 string name, fnt_foundry;
145 parseFontName(cb->itemText(i), name, fnt_foundry);
146 if (compare_ascii_no_case(name, fnt_foundry) == 0) {
147 cb->setCurrentIndex(i);
152 // Bleh, default fonts, and the names couldn't be found. Hack
157 QString const font_family = toqstr(family);
158 if (font_family == guiApp->romanFontName()) {
159 font.setStyleHint(QFont::Serif);
160 font.setFamily(font_family);
161 } else if (font_family == guiApp->sansFontName()) {
162 font.setStyleHint(QFont::SansSerif);
163 font.setFamily(font_family);
164 } else if (font_family == guiApp->typewriterFontName()) {
165 font.setStyleHint(QFont::TypeWriter);
166 font.setFamily(font_family);
168 LYXERR0("FAILED to find the default font: '"
169 << foundry << "', '" << family << '\'');
173 QFontInfo info(font);
174 string default_font_name, dummyfoundry;
175 parseFontName(info.family(), default_font_name, dummyfoundry);
176 LYXERR0("Apparent font is " << default_font_name);
178 for (int i = 0; i < cb->count(); ++i) {
179 LYXERR0("Looking at " << cb->itemText(i));
180 if (compare_ascii_no_case(fromqstr(cb->itemText(i)),
181 default_font_name) == 0) {
182 cb->setCurrentIndex(i);
187 LYXERR0("FAILED to find the font: '"
188 << foundry << "', '" << family << '\'');
192 /////////////////////////////////////////////////////////////////////
196 /////////////////////////////////////////////////////////////////////
198 PrefOutput::PrefOutput(GuiPreferences * form)
199 : PrefModule(catOutput, N_("General[[settings]]"), form)
203 dviCB->setValidator(new NoNewLineValidator(dviCB));
204 pdfCB->setValidator(new NoNewLineValidator(pdfCB));
206 connect(plaintextLinelengthSB, SIGNAL(valueChanged(int)),
207 this, SIGNAL(changed()));
208 connect(overwriteCO, SIGNAL(activated(int)),
209 this, SIGNAL(changed()));
210 connect(dviCB, SIGNAL(editTextChanged(QString)),
211 this, SIGNAL(changed()));
212 connect(pdfCB, SIGNAL(editTextChanged(QString)),
213 this, SIGNAL(changed()));
214 connect(printerPaperTypeED, SIGNAL(textChanged(QString)),
215 this, SIGNAL(changed()));
216 connect(printerLandscapeED, SIGNAL(textChanged(QString)),
217 this, SIGNAL(changed()));
218 connect(printerPaperSizeED, SIGNAL(textChanged(QString)),
219 this, SIGNAL(changed()));
221 printerPaperTypeED->setValidator(new NoNewLineValidator(printerPaperTypeED));
222 printerLandscapeED->setValidator(new NoNewLineValidator(printerLandscapeED));
223 printerPaperSizeED->setValidator(new NoNewLineValidator(printerPaperSizeED));
226 dviCB->addItem("xdvi -sourceposition '$$n:\\ $$t' $$o");
227 dviCB->addItem("yap -1 -s \"$$n $$t\" $$o");
228 dviCB->addItem("okular --unique \"$$o#src:$$n $$f\"");
229 dviCB->addItem("synctex view -i $$n:0:$$t -o $$o -x \"evince -i %{page+1} $$o\"");
231 pdfCB->addItem("CMCDDE SUMATRA control [ForwardSearch(\\\"$$o\\\",\\\"$$t\\\",$$n,0,0,1)]");
232 pdfCB->addItem("SumatraPDF -reuse-instance \"$$o\" -forward-search \"$$t\" $$n");
233 pdfCB->addItem("synctex view -i $$n:0:$$t -o $$o -x \"xpdf -raise -remote $$t.tmp $$o %{page+1}\"");
234 pdfCB->addItem("okular --unique \"$$o#src:$$n $$f\"");
235 pdfCB->addItem("qpdfview --unique \"$$o#src:$$f:$$n:0\"");
236 pdfCB->addItem("synctex view -i $$n:0:$$t -o $$o -x \"evince -i %{page+1} $$o\"");
237 pdfCB->addItem("/Applications/Skim.app/Contents/SharedSupport/displayline $$n $$o $$t");
241 void PrefOutput::applyRC(LyXRC & rc) const
243 rc.plaintext_linelen = plaintextLinelengthSB->value();
244 rc.forward_search_dvi = fromqstr(dviCB->currentText());
245 rc.forward_search_pdf = fromqstr(pdfCB->currentText());
247 switch (overwriteCO->currentIndex()) {
249 rc.export_overwrite = NO_FILES;
252 rc.export_overwrite = MAIN_FILE;
255 rc.export_overwrite = ALL_FILES;
259 rc.print_paper_flag = fromqstr(printerPaperTypeED->text());
260 rc.print_landscape_flag = fromqstr(printerLandscapeED->text());
261 rc.print_paper_dimension_flag = fromqstr(printerPaperSizeED->text());
265 void PrefOutput::updateRC(LyXRC const & rc)
267 plaintextLinelengthSB->setValue(rc.plaintext_linelen);
268 dviCB->setEditText(toqstr(rc.forward_search_dvi));
269 pdfCB->setEditText(toqstr(rc.forward_search_pdf));
271 switch (rc.export_overwrite) {
273 overwriteCO->setCurrentIndex(0);
276 overwriteCO->setCurrentIndex(1);
279 overwriteCO->setCurrentIndex(2);
283 printerPaperTypeED->setText(toqstr(rc.print_paper_flag));
284 printerLandscapeED->setText(toqstr(rc.print_landscape_flag));
285 printerPaperSizeED->setText(toqstr(rc.print_paper_dimension_flag));
289 /////////////////////////////////////////////////////////////////////
293 /////////////////////////////////////////////////////////////////////
295 PrefInput::PrefInput(GuiPreferences * form)
296 : PrefModule(catEditing, N_("Keyboard/Mouse"), form)
300 connect(keymapCB, SIGNAL(clicked()),
301 this, SIGNAL(changed()));
302 connect(firstKeymapED, SIGNAL(textChanged(QString)),
303 this, SIGNAL(changed()));
304 connect(secondKeymapED, SIGNAL(textChanged(QString)),
305 this, SIGNAL(changed()));
306 connect(mouseWheelSpeedSB, SIGNAL(valueChanged(double)),
307 this, SIGNAL(changed()));
308 connect(scrollzoomEnableCB, SIGNAL(clicked()),
309 this, SIGNAL(changed()));
310 connect(scrollzoomValueCO, SIGNAL(activated(int)),
311 this, SIGNAL(changed()));
312 connect(dontswapCB, SIGNAL(toggled(bool)),
313 this, SIGNAL(changed()));
314 connect(mmPasteCB, SIGNAL(toggled(bool)),
315 this, SIGNAL(changed()));
317 // reveal checkbox for switching Ctrl and Meta on Mac:
319 dontswapCB->setVisible(true);
321 dontswapCB->setVisible(false);
326 void PrefInput::applyRC(LyXRC & rc) const
328 // FIXME: can derive CB from the two EDs
329 rc.use_kbmap = keymapCB->isChecked();
330 rc.primary_kbmap = internal_path(fromqstr(firstKeymapED->text()));
331 rc.secondary_kbmap = internal_path(fromqstr(secondKeymapED->text()));
332 rc.mouse_wheel_speed = mouseWheelSpeedSB->value();
333 if (scrollzoomEnableCB->isChecked()) {
334 switch (scrollzoomValueCO->currentIndex()) {
336 rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_CTRL;
339 rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_SHIFT;
342 rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_ALT;
346 rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_OFF;
348 rc.mac_dontswap_ctrl_meta = dontswapCB->isChecked();
349 rc.mouse_middlebutton_paste = mmPasteCB->isChecked();
353 void PrefInput::updateRC(LyXRC const & rc)
355 // FIXME: can derive CB from the two EDs
356 keymapCB->setChecked(rc.use_kbmap);
357 firstKeymapED->setText(toqstr(external_path(rc.primary_kbmap)));
358 secondKeymapED->setText(toqstr(external_path(rc.secondary_kbmap)));
359 mouseWheelSpeedSB->setValue(rc.mouse_wheel_speed);
360 switch (rc.scroll_wheel_zoom) {
361 case LyXRC::SCROLL_WHEEL_ZOOM_OFF:
362 scrollzoomEnableCB->setChecked(false);
364 case LyXRC::SCROLL_WHEEL_ZOOM_CTRL:
365 scrollzoomEnableCB->setChecked(true);
366 scrollzoomValueCO->setCurrentIndex(0);
368 case LyXRC::SCROLL_WHEEL_ZOOM_SHIFT:
369 scrollzoomEnableCB->setChecked(true);
370 scrollzoomValueCO->setCurrentIndex(1);
372 case LyXRC::SCROLL_WHEEL_ZOOM_ALT:
373 scrollzoomEnableCB->setChecked(true);
374 scrollzoomValueCO->setCurrentIndex(2);
377 dontswapCB->setChecked(rc.mac_dontswap_ctrl_meta);
378 mmPasteCB->setChecked(rc.mouse_middlebutton_paste);
382 QString PrefInput::testKeymap(QString const & keymap)
384 return form_->browsekbmap(internalPath(keymap));
388 void PrefInput::on_firstKeymapPB_clicked(bool)
390 QString const file = testKeymap(firstKeymapED->text());
392 firstKeymapED->setText(file);
396 void PrefInput::on_secondKeymapPB_clicked(bool)
398 QString const file = testKeymap(secondKeymapED->text());
400 secondKeymapED->setText(file);
404 void PrefInput::on_keymapCB_toggled(bool keymap)
406 firstKeymapLA->setEnabled(keymap);
407 secondKeymapLA->setEnabled(keymap);
408 firstKeymapED->setEnabled(keymap);
409 secondKeymapED->setEnabled(keymap);
410 firstKeymapPB->setEnabled(keymap);
411 secondKeymapPB->setEnabled(keymap);
415 void PrefInput::on_scrollzoomEnableCB_toggled(bool enabled)
417 scrollzoomValueCO->setEnabled(enabled);
421 /////////////////////////////////////////////////////////////////////
425 /////////////////////////////////////////////////////////////////////
427 PrefCompletion::PrefCompletion(GuiPreferences * form)
428 : PrefModule(catEditing, N_("Input Completion"), form)
432 connect(inlineDelaySB, SIGNAL(valueChanged(double)),
433 this, SIGNAL(changed()));
434 connect(inlineMathCB, SIGNAL(clicked()),
435 this, SIGNAL(changed()));
436 connect(inlineTextCB, SIGNAL(clicked()),
437 this, SIGNAL(changed()));
438 connect(inlineDotsCB, SIGNAL(clicked()),
439 this, SIGNAL(changed()));
440 connect(popupDelaySB, SIGNAL(valueChanged(double)),
441 this, SIGNAL(changed()));
442 connect(popupMathCB, SIGNAL(clicked()),
443 this, SIGNAL(changed()));
444 connect(autocorrectionCB, SIGNAL(clicked()),
445 this, SIGNAL(changed()));
446 connect(popupTextCB, SIGNAL(clicked()),
447 this, SIGNAL(changed()));
448 connect(popupAfterCompleteCB, SIGNAL(clicked()),
449 this, SIGNAL(changed()));
450 connect(cursorTextCB, SIGNAL(clicked()),
451 this, SIGNAL(changed()));
452 connect(minlengthSB, SIGNAL(valueChanged(int)),
453 this, SIGNAL(changed()));
457 void PrefCompletion::on_inlineTextCB_clicked()
463 void PrefCompletion::on_popupTextCB_clicked()
469 void PrefCompletion::enableCB()
471 cursorTextCB->setEnabled(
472 popupTextCB->isChecked() || inlineTextCB->isChecked());
476 void PrefCompletion::applyRC(LyXRC & rc) const
478 rc.completion_inline_delay = inlineDelaySB->value();
479 rc.completion_inline_math = inlineMathCB->isChecked();
480 rc.completion_inline_text = inlineTextCB->isChecked();
481 rc.completion_inline_dots = inlineDotsCB->isChecked() ? 13 : -1;
482 rc.completion_popup_delay = popupDelaySB->value();
483 rc.completion_popup_math = popupMathCB->isChecked();
484 rc.autocorrection_math = autocorrectionCB->isChecked();
485 rc.completion_popup_text = popupTextCB->isChecked();
486 rc.completion_cursor_text = cursorTextCB->isChecked();
487 rc.completion_popup_after_complete =
488 popupAfterCompleteCB->isChecked();
489 rc.completion_minlength = minlengthSB->value();
493 void PrefCompletion::updateRC(LyXRC const & rc)
495 inlineDelaySB->setValue(rc.completion_inline_delay);
496 inlineMathCB->setChecked(rc.completion_inline_math);
497 inlineTextCB->setChecked(rc.completion_inline_text);
498 inlineDotsCB->setChecked(rc.completion_inline_dots != -1);
499 popupDelaySB->setValue(rc.completion_popup_delay);
500 popupMathCB->setChecked(rc.completion_popup_math);
501 autocorrectionCB->setChecked(rc.autocorrection_math);
502 popupTextCB->setChecked(rc.completion_popup_text);
503 cursorTextCB->setChecked(rc.completion_cursor_text);
504 popupAfterCompleteCB->setChecked(rc.completion_popup_after_complete);
506 minlengthSB->setValue(rc.completion_minlength);
511 /////////////////////////////////////////////////////////////////////
515 /////////////////////////////////////////////////////////////////////
517 PrefLatex::PrefLatex(GuiPreferences * form)
518 : PrefModule(catOutput, N_("LaTeX"), form)
522 latexDviPaperED->setValidator(new NoNewLineValidator(latexDviPaperED));
523 latexBibtexED->setValidator(new NoNewLineValidator(latexBibtexED));
524 latexJBibtexED->setValidator(new NoNewLineValidator(latexJBibtexED));
525 latexIndexED->setValidator(new NoNewLineValidator(latexIndexED));
526 latexJIndexED->setValidator(new NoNewLineValidator(latexJIndexED));
527 latexNomenclED->setValidator(new NoNewLineValidator(latexNomenclED));
528 latexChecktexED->setValidator(new NoNewLineValidator(latexChecktexED));
530 connect(latexChecktexED, SIGNAL(textChanged(QString)),
531 this, SIGNAL(changed()));
532 connect(latexBibtexCO, SIGNAL(activated(int)),
533 this, SIGNAL(changed()));
534 connect(latexBibtexED, SIGNAL(textChanged(QString)),
535 this, SIGNAL(changed()));
536 connect(latexJBibtexCO, SIGNAL(activated(int)),
537 this, SIGNAL(changed()));
538 connect(latexJBibtexED, SIGNAL(textChanged(QString)),
539 this, SIGNAL(changed()));
540 connect(latexIndexCO, SIGNAL(activated(int)),
541 this, SIGNAL(changed()));
542 connect(latexIndexED, SIGNAL(textChanged(QString)),
543 this, SIGNAL(changed()));
544 connect(latexJIndexED, SIGNAL(textChanged(QString)),
545 this, SIGNAL(changed()));
546 connect(latexAutoresetCB, SIGNAL(clicked()),
547 this, SIGNAL(changed()));
548 connect(latexDviPaperED, SIGNAL(textChanged(QString)),
549 this, SIGNAL(changed()));
550 connect(latexNomenclED, SIGNAL(textChanged(QString)),
551 this, SIGNAL(changed()));
553 #if defined(__CYGWIN__) || defined(_WIN32)
554 pathCB->setVisible(true);
555 connect(pathCB, SIGNAL(clicked()),
556 this, SIGNAL(changed()));
558 pathCB->setVisible(false);
563 void PrefLatex::on_latexBibtexCO_activated(int n)
565 QString const bibtex = latexBibtexCO->itemData(n).toString();
566 if (bibtex.isEmpty()) {
567 latexBibtexED->clear();
568 latexBibtexOptionsLA->setText(qt_("C&ommand:"));
571 for (LyXRC::CommandSet::const_iterator it = bibtex_alternatives.begin();
572 it != bibtex_alternatives.end(); ++it) {
573 QString const bib = toqstr(*it);
574 int ind = bib.indexOf(" ");
575 QString sel_command = bib.left(ind);
576 QString sel_options = ind < 0 ? QString() : bib.mid(ind + 1);
577 if (bibtex == sel_command) {
579 latexBibtexED->clear();
581 latexBibtexED->setText(sel_options.trimmed());
584 latexBibtexOptionsLA->setText(qt_("&Options:"));
588 void PrefLatex::on_latexJBibtexCO_activated(int n)
590 QString const jbibtex = latexJBibtexCO->itemData(n).toString();
591 if (jbibtex.isEmpty()) {
592 latexJBibtexED->clear();
593 latexJBibtexOptionsLA->setText(qt_("Co&mmand:"));
596 for (LyXRC::CommandSet::const_iterator it = jbibtex_alternatives.begin();
597 it != jbibtex_alternatives.end(); ++it) {
598 QString const bib = toqstr(*it);
599 int ind = bib.indexOf(" ");
600 QString sel_command = bib.left(ind);
601 QString sel_options = ind < 0 ? QString() : bib.mid(ind + 1);
602 if (jbibtex == sel_command) {
604 latexJBibtexED->clear();
606 latexJBibtexED->setText(sel_options.trimmed());
609 latexJBibtexOptionsLA->setText(qt_("Opt&ions:"));
613 void PrefLatex::on_latexIndexCO_activated(int n)
615 QString const index = latexIndexCO->itemData(n).toString();
616 if (index.isEmpty()) {
617 latexIndexED->clear();
618 latexIndexOptionsLA->setText(qt_("Co&mmand:"));
621 for (LyXRC::CommandSet::const_iterator it = index_alternatives.begin();
622 it != index_alternatives.end(); ++it) {
623 QString const idx = toqstr(*it);
624 int ind = idx.indexOf(" ");
625 QString sel_command = idx.left(ind);
626 QString sel_options = ind < 0 ? QString() : idx.mid(ind + 1);
627 if (index == sel_command) {
629 latexIndexED->clear();
631 latexIndexED->setText(sel_options.trimmed());
634 latexIndexOptionsLA->setText(qt_("Op&tions:"));
638 void PrefLatex::applyRC(LyXRC & rc) const
640 // If bibtex is not empty, bibopt contains the options, otherwise
641 // it is a customized bibtex command with options.
642 QString const bibtex = latexBibtexCO->itemData(
643 latexBibtexCO->currentIndex()).toString();
644 QString const bibopt = latexBibtexED->text();
645 if (bibtex.isEmpty())
646 rc.bibtex_command = fromqstr(bibopt);
647 else if (bibopt.isEmpty())
648 rc.bibtex_command = fromqstr(bibtex);
650 rc.bibtex_command = fromqstr(bibtex) + " " + fromqstr(bibopt);
652 // If jbibtex is not empty, jbibopt contains the options, otherwise
653 // it is a customized bibtex command with options.
654 QString const jbibtex = latexJBibtexCO->itemData(
655 latexJBibtexCO->currentIndex()).toString();
656 QString const jbibopt = latexJBibtexED->text();
657 if (jbibtex.isEmpty())
658 rc.jbibtex_command = fromqstr(jbibopt);
659 else if (jbibopt.isEmpty())
660 rc.jbibtex_command = fromqstr(jbibtex);
662 rc.jbibtex_command = fromqstr(jbibtex) + " " + fromqstr(jbibopt);
664 // If index is not empty, idxopt contains the options, otherwise
665 // it is a customized index command with options.
666 QString const index = latexIndexCO->itemData(
667 latexIndexCO->currentIndex()).toString();
668 QString const idxopt = latexIndexED->text();
670 rc.index_command = fromqstr(idxopt);
671 else if (idxopt.isEmpty())
672 rc.index_command = fromqstr(index);
674 rc.index_command = fromqstr(index) + " " + fromqstr(idxopt);
676 rc.chktex_command = fromqstr(latexChecktexED->text());
677 rc.jindex_command = fromqstr(latexJIndexED->text());
678 rc.nomencl_command = fromqstr(latexNomenclED->text());
679 rc.auto_reset_options = latexAutoresetCB->isChecked();
680 rc.view_dvi_paper_option = fromqstr(latexDviPaperED->text());
681 #if defined(__CYGWIN__) || defined(_WIN32)
682 rc.windows_style_tex_paths = pathCB->isChecked();
687 void PrefLatex::updateRC(LyXRC const & rc)
689 latexBibtexCO->clear();
691 latexBibtexCO->addItem(qt_("Automatic"), "automatic");
692 latexBibtexCO->addItem(qt_("Custom"), QString());
693 for (LyXRC::CommandSet::const_iterator it = rc.bibtex_alternatives.begin();
694 it != rc.bibtex_alternatives.end(); ++it) {
695 QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
696 latexBibtexCO->addItem(command, command);
699 bibtex_alternatives = rc.bibtex_alternatives;
701 QString const bib = toqstr(rc.bibtex_command);
702 int ind = bib.indexOf(" ");
703 QString sel_command = bib.left(ind);
704 QString sel_options = ind < 0 ? QString() : bib.mid(ind + 1);
706 int pos = latexBibtexCO->findData(sel_command);
708 latexBibtexCO->setCurrentIndex(pos);
709 latexBibtexED->setText(sel_options.trimmed());
710 latexBibtexOptionsLA->setText(qt_("&Options:"));
712 latexBibtexED->setText(toqstr(rc.bibtex_command));
713 latexBibtexCO->setCurrentIndex(0);
714 latexBibtexOptionsLA->setText(qt_("C&ommand:"));
717 latexJBibtexCO->clear();
719 latexJBibtexCO->addItem(qt_("Automatic"), "automatic");
720 latexJBibtexCO->addItem(qt_("Custom"), QString());
721 for (LyXRC::CommandSet::const_iterator it = rc.jbibtex_alternatives.begin();
722 it != rc.jbibtex_alternatives.end(); ++it) {
723 QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
724 latexJBibtexCO->addItem(command, command);
727 jbibtex_alternatives = rc.jbibtex_alternatives;
729 QString const jbib = toqstr(rc.jbibtex_command);
730 ind = jbib.indexOf(" ");
731 sel_command = jbib.left(ind);
732 sel_options = ind < 0 ? QString() : jbib.mid(ind + 1);
734 pos = latexJBibtexCO->findData(sel_command);
736 latexJBibtexCO->setCurrentIndex(pos);
737 latexJBibtexED->setText(sel_options.trimmed());
738 latexJBibtexOptionsLA->setText(qt_("Opt&ions:"));
740 latexJBibtexED->setText(toqstr(rc.bibtex_command));
741 latexJBibtexCO->setCurrentIndex(0);
742 latexJBibtexOptionsLA->setText(qt_("Co&mmand:"));
745 latexIndexCO->clear();
747 latexIndexCO->addItem(qt_("Custom"), QString());
748 for (LyXRC::CommandSet::const_iterator it = rc.index_alternatives.begin();
749 it != rc.index_alternatives.end(); ++it) {
750 QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
751 latexIndexCO->addItem(command, command);
754 index_alternatives = rc.index_alternatives;
756 QString const idx = toqstr(rc.index_command);
757 ind = idx.indexOf(" ");
758 sel_command = idx.left(ind);
759 sel_options = ind < 0 ? QString() : idx.mid(ind + 1);
761 pos = latexIndexCO->findData(sel_command);
763 latexIndexCO->setCurrentIndex(pos);
764 latexIndexED->setText(sel_options.trimmed());
765 latexIndexOptionsLA->setText(qt_("Op&tions:"));
767 latexIndexED->setText(toqstr(rc.index_command));
768 latexIndexCO->setCurrentIndex(0);
769 latexIndexOptionsLA->setText(qt_("Co&mmand:"));
772 latexChecktexED->setText(toqstr(rc.chktex_command));
773 latexJIndexED->setText(toqstr(rc.jindex_command));
774 latexNomenclED->setText(toqstr(rc.nomencl_command));
775 latexAutoresetCB->setChecked(rc.auto_reset_options);
776 latexDviPaperED->setText(toqstr(rc.view_dvi_paper_option));
777 #if defined(__CYGWIN__) || defined(_WIN32)
778 pathCB->setChecked(rc.windows_style_tex_paths);
783 /////////////////////////////////////////////////////////////////////
787 /////////////////////////////////////////////////////////////////////
789 PrefScreenFonts::PrefScreenFonts(GuiPreferences * form)
790 : PrefModule(catLookAndFeel, N_("Screen Fonts"), form)
794 #if QT_VERSION < 0x050e00
795 connect(screenRomanCO, SIGNAL(activated(QString)),
796 this, SLOT(selectRoman(QString)));
797 connect(screenSansCO, SIGNAL(activated(QString)),
798 this, SLOT(selectSans(QString)));
799 connect(screenTypewriterCO, SIGNAL(activated(QString)),
800 this, SLOT(selectTypewriter(QString)));
802 connect(screenRomanCO, SIGNAL(textActivated(QString)),
803 this, SLOT(selectRoman(QString)));
804 connect(screenSansCO, SIGNAL(textActivated(QString)),
805 this, SLOT(selectSans(QString)));
806 connect(screenTypewriterCO, SIGNAL(textActivated(QString)),
807 this, SLOT(selectTypewriter(QString)));
810 #if QT_VERSION >= 0x060000
811 const QStringList families(QFontDatabase::families());
813 QFontDatabase fontdb;
814 const QStringList families(fontdb.families());
816 for (auto const & family : families) {
817 screenRomanCO->addItem(family);
818 screenSansCO->addItem(family);
819 screenTypewriterCO->addItem(family);
821 #if QT_VERSION < 0x050e00
822 connect(screenRomanCO, SIGNAL(activated(QString)),
823 this, SIGNAL(changed()));
824 connect(screenSansCO, SIGNAL(activated(QString)),
825 this, SIGNAL(changed()));
826 connect(screenTypewriterCO, SIGNAL(activated(QString)),
827 this, SIGNAL(changed()));
829 connect(screenRomanCO, SIGNAL(textActivated(QString)),
830 this, SIGNAL(changed()));
831 connect(screenSansCO, SIGNAL(textActivated(QString)),
832 this, SIGNAL(changed()));
833 connect(screenTypewriterCO, SIGNAL(textActivated(QString)),
834 this, SIGNAL(changed()));
836 connect(screenZoomSB, SIGNAL(valueChanged(int)),
837 this, SIGNAL(changed()));
838 connect(screenTinyED, SIGNAL(textChanged(QString)),
839 this, SIGNAL(changed()));
840 connect(screenSmallestED, SIGNAL(textChanged(QString)),
841 this, SIGNAL(changed()));
842 connect(screenSmallerED, SIGNAL(textChanged(QString)),
843 this, SIGNAL(changed()));
844 connect(screenSmallED, SIGNAL(textChanged(QString)),
845 this, SIGNAL(changed()));
846 connect(screenNormalED, SIGNAL(textChanged(QString)),
847 this, SIGNAL(changed()));
848 connect(screenLargeED, SIGNAL(textChanged(QString)),
849 this, SIGNAL(changed()));
850 connect(screenLargerED, SIGNAL(textChanged(QString)),
851 this, SIGNAL(changed()));
852 connect(screenLargestED, SIGNAL(textChanged(QString)),
853 this, SIGNAL(changed()));
854 connect(screenHugeED, SIGNAL(textChanged(QString)),
855 this, SIGNAL(changed()));
856 connect(screenHugerED, SIGNAL(textChanged(QString)),
857 this, SIGNAL(changed()));
859 screenTinyED->setValidator(new QDoubleValidator(screenTinyED));
860 screenSmallestED->setValidator(new QDoubleValidator(screenSmallestED));
861 screenSmallerED->setValidator(new QDoubleValidator(screenSmallerED));
862 screenSmallED->setValidator(new QDoubleValidator(screenSmallED));
863 screenNormalED->setValidator(new QDoubleValidator(screenNormalED));
864 screenLargeED->setValidator(new QDoubleValidator(screenLargeED));
865 screenLargerED->setValidator(new QDoubleValidator(screenLargerED));
866 screenLargestED->setValidator(new QDoubleValidator(screenLargestED));
867 screenHugeED->setValidator(new QDoubleValidator(screenHugeED));
868 screenHugerED->setValidator(new QDoubleValidator(screenHugerED));
872 void PrefScreenFonts::applyRC(LyXRC & rc) const
874 LyXRC const oldrc = rc;
876 parseFontName(screenRomanCO->currentText(),
877 rc.roman_font_name, rc.roman_font_foundry);
878 parseFontName(screenSansCO->currentText(),
879 rc.sans_font_name, rc.sans_font_foundry);
880 parseFontName(screenTypewriterCO->currentText(),
881 rc.typewriter_font_name, rc.typewriter_font_foundry);
883 rc.defaultZoom = screenZoomSB->value();
884 rc.font_sizes[TINY_SIZE] = widgetToDoubleStr(screenTinyED);
885 rc.font_sizes[SCRIPT_SIZE] = widgetToDoubleStr(screenSmallestED);
886 rc.font_sizes[FOOTNOTE_SIZE] = widgetToDoubleStr(screenSmallerED);
887 rc.font_sizes[SMALL_SIZE] = widgetToDoubleStr(screenSmallED);
888 rc.font_sizes[NORMAL_SIZE] = widgetToDoubleStr(screenNormalED);
889 rc.font_sizes[LARGE_SIZE] = widgetToDoubleStr(screenLargeED);
890 rc.font_sizes[LARGER_SIZE] = widgetToDoubleStr(screenLargerED);
891 rc.font_sizes[LARGEST_SIZE] = widgetToDoubleStr(screenLargestED);
892 rc.font_sizes[HUGE_SIZE] = widgetToDoubleStr(screenHugeED);
893 rc.font_sizes[HUGER_SIZE] = widgetToDoubleStr(screenHugerED);
897 void PrefScreenFonts::updateRC(LyXRC const & rc)
899 setComboxFont(screenRomanCO, rc.roman_font_name,
900 rc.roman_font_foundry);
901 setComboxFont(screenSansCO, rc.sans_font_name,
902 rc.sans_font_foundry);
903 setComboxFont(screenTypewriterCO, rc.typewriter_font_name,
904 rc.typewriter_font_foundry);
906 selectRoman(screenRomanCO->currentText());
907 selectSans(screenSansCO->currentText());
908 selectTypewriter(screenTypewriterCO->currentText());
910 screenZoomSB->setValue(rc.defaultZoom);
911 updateScreenFontSizes(rc);
915 void PrefScreenFonts::updateScreenFontSizes(LyXRC const & rc)
917 doubleToWidget(screenTinyED, rc.font_sizes[TINY_SIZE]);
918 doubleToWidget(screenSmallestED, rc.font_sizes[SCRIPT_SIZE]);
919 doubleToWidget(screenSmallerED, rc.font_sizes[FOOTNOTE_SIZE]);
920 doubleToWidget(screenSmallED, rc.font_sizes[SMALL_SIZE]);
921 doubleToWidget(screenNormalED, rc.font_sizes[NORMAL_SIZE]);
922 doubleToWidget(screenLargeED, rc.font_sizes[LARGE_SIZE]);
923 doubleToWidget(screenLargerED, rc.font_sizes[LARGER_SIZE]);
924 doubleToWidget(screenLargestED, rc.font_sizes[LARGEST_SIZE]);
925 doubleToWidget(screenHugeED, rc.font_sizes[HUGE_SIZE]);
926 doubleToWidget(screenHugerED, rc.font_sizes[HUGER_SIZE]);
930 void PrefScreenFonts::selectRoman(const QString & name)
932 screenRomanFE->set(QFont(name), name);
936 void PrefScreenFonts::selectSans(const QString & name)
938 screenSansFE->set(QFont(name), name);
942 void PrefScreenFonts::selectTypewriter(const QString & name)
944 screenTypewriterFE->set(QFont(name), name);
948 /////////////////////////////////////////////////////////////////////
952 /////////////////////////////////////////////////////////////////////
955 PrefColors::PrefColors(GuiPreferences * form)
956 : PrefModule(catLookAndFeel, N_("Colors"), form)
960 // FIXME: all of this initialization should be put into the controller.
961 // See http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg113301.html
962 // for some discussion of why that is not trivial.
963 QPixmap icon(32, 32);
964 for (int i = 0; i < Color_ignore; ++i) {
965 ColorCode lc = static_cast<ColorCode>(i);
972 || lc == Color_darkgray
975 || lc == Color_lightgray
977 || lc == Color_magenta
979 || lc == Color_orange
981 || lc == Color_purple
984 || lc == Color_violet
985 || lc == Color_yellow
986 || lc == Color_inherit
987 || lc == Color_ignore)
989 lcolors_.push_back(lc);
991 sort(lcolors_.begin(), lcolors_.end(), ColorSorter);
992 vector<ColorCode>::const_iterator cit = lcolors_.begin();
993 vector<ColorCode>::const_iterator const end = lcolors_.end();
994 for (; cit != end; ++cit) {
995 (void) new QListWidgetItem(QIcon(icon),
996 toqstr(lcolor.getGUIName(*cit)), lyxObjectsLW);
998 curcolors_.resize(lcolors_.size());
999 newcolors_.resize(lcolors_.size());
1000 // End initialization
1002 connect(colorChangePB, SIGNAL(clicked()),
1003 this, SLOT(changeColor()));
1004 connect(colorResetPB, SIGNAL(clicked()),
1005 this, SLOT(resetColor()));
1006 connect(colorResetAllPB, SIGNAL(clicked()),
1007 this, SLOT(resetAllColor()));
1008 connect(lyxObjectsLW, SIGNAL(itemSelectionChanged()),
1009 this, SLOT(changeLyxObjectsSelection()));
1010 connect(lyxObjectsLW, SIGNAL(itemActivated(QListWidgetItem*)),
1011 this, SLOT(changeColor()));
1012 connect(syscolorsCB, SIGNAL(toggled(bool)),
1013 this, SIGNAL(changed()));
1014 connect(syscolorsCB, SIGNAL(toggled(bool)),
1015 this, SLOT(changeSysColor()));
1019 void PrefColors::applyRC(LyXRC & rc) const
1023 for (unsigned int i = 0; i < lcolors_.size(); ++i)
1024 if (curcolors_[i] != newcolors_[i])
1025 form_->setColor(lcolors_[i], newcolors_[i]);
1026 rc.use_system_colors = syscolorsCB->isChecked();
1028 if (oldrc.use_system_colors != rc.use_system_colors)
1029 guiApp->colorCache().clear();
1033 void PrefColors::updateRC(LyXRC const & rc)
1035 for (size_type i = 0; i < lcolors_.size(); ++i) {
1036 QColor color = guiApp->colorCache().get(lcolors_[i], false);
1037 QPixmap coloritem(32, 32);
1038 coloritem.fill(color);
1039 lyxObjectsLW->item(int(i))->setIcon(QIcon(coloritem));
1040 newcolors_[i] = curcolors_[i] = color.name();
1042 syscolorsCB->setChecked(rc.use_system_colors);
1043 changeLyxObjectsSelection();
1045 setDisabledResets();
1049 void PrefColors::changeColor()
1051 int const row = lyxObjectsLW->currentRow();
1057 QString const color = newcolors_[size_t(row)];
1058 QColor const c = form_->getColor(QColor(color));
1060 if (setColor(row, c, color)) {
1061 setDisabledResets();
1068 void PrefColors::resetColor()
1070 int const row = lyxObjectsLW->currentRow();
1076 QString const color = newcolors_[size_t(row)];
1077 QColor const c = getDefaultColorByRow(row);
1079 if (setColor(row, c, color)) {
1080 setDisabledResets();
1087 void PrefColors::resetAllColor()
1089 bool isChanged = false;
1091 colorResetAllPB->setDisabled(true);
1093 for (int irow = 0, count = lyxObjectsLW->count(); irow < count; ++irow) {
1094 QString const color = newcolors_[size_t(irow)];
1095 QColor const c = getDefaultColorByRow(irow);
1097 if (setColor(irow, c, color))
1102 setDisabledResets();
1109 bool PrefColors::setColor(int const row, QColor const & new_color,
1110 QString const & old_color)
1112 if (new_color.isValid() && new_color.name() != old_color) {
1113 newcolors_[size_t(row)] = new_color.name();
1114 QPixmap coloritem(32, 32);
1115 coloritem.fill(new_color);
1116 lyxObjectsLW->item(row)->setIcon(QIcon(coloritem));
1123 void PrefColors::setDisabledResets()
1125 int const row = lyxObjectsLW->currentRow();
1126 // set disable reset buttons ...
1128 colorResetPB->setDisabled(isDefaultColor(row, newcolors_[size_t(row)]));
1130 colorResetAllPB->setDisabled(true);
1132 // ... in between process qt events to give quicker visual feedback to the user ...
1133 guiApp->processEvents();
1135 // ... set disable Reset All button
1136 for (int irow = 0, count = lyxObjectsLW->count(); irow < count; ++irow) {
1137 if (!isDefaultColor(irow, newcolors_[size_t(irow)])) {
1138 colorResetAllPB->setDisabled(false);
1139 // the break condition might hide performance issues
1140 // if a non-default color is at the top of the list
1147 bool PrefColors::isDefaultColor(int const row, QString const & color)
1149 return color == getDefaultColorByRow(row).name();
1153 QColor PrefColors::getDefaultColorByRow(int const row)
1155 ColorSet const defaultcolor;
1156 return defaultcolor.getX11HexName(lcolors_[size_t(row)],
1157 guiApp->colorCache().isDarkMode()).c_str();
1161 void PrefColors::changeSysColor()
1163 for (int row = 0 ; row < lyxObjectsLW->count() ; ++row) {
1164 // skip colors that are taken from system palette
1165 bool const disable = syscolorsCB->isChecked()
1166 && guiApp->colorCache().isSystem(lcolors_[size_t(row)]);
1168 QListWidgetItem * const item = lyxObjectsLW->item(row);
1169 Qt::ItemFlags const flags = item->flags();
1172 item->setFlags(flags & ~Qt::ItemIsEnabled);
1174 item->setFlags(flags | Qt::ItemIsEnabled);
1179 void PrefColors::changeLyxObjectsSelection()
1181 int currentRow = lyxObjectsLW->currentRow();
1182 colorChangePB->setDisabled(currentRow < 0);
1185 colorResetPB->setDisabled(true);
1187 colorResetPB->setDisabled(
1188 isDefaultColor(currentRow, newcolors_[size_t(currentRow)]));
1192 /////////////////////////////////////////////////////////////////////
1196 /////////////////////////////////////////////////////////////////////
1198 PrefDisplay::PrefDisplay(GuiPreferences * form)
1199 : PrefModule(catLookAndFeel, N_("Display"), form)
1202 connect(displayGraphicsCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1203 connect(instantPreviewCO, SIGNAL(activated(int)), this, SIGNAL(changed()));
1204 connect(previewSizeSB, SIGNAL(valueChanged(double)), this, SIGNAL(changed()));
1205 connect(paragraphMarkerCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1206 connect(ctAdditionsUnderlinedCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1210 void PrefDisplay::on_instantPreviewCO_currentIndexChanged(int index)
1212 previewSizeSB->setEnabled(index != 0);
1216 void PrefDisplay::applyRC(LyXRC & rc) const
1218 switch (instantPreviewCO->currentIndex()) {
1220 rc.preview = LyXRC::PREVIEW_OFF;
1223 rc.preview = LyXRC::PREVIEW_NO_MATH;
1226 rc.preview = LyXRC::PREVIEW_ON;
1230 rc.display_graphics = displayGraphicsCB->isChecked();
1231 rc.preview_scale_factor = previewSizeSB->value();
1232 rc.paragraph_markers = paragraphMarkerCB->isChecked();
1233 rc.ct_additions_underlined = ctAdditionsUnderlinedCB->isChecked();
1235 // FIXME!! The graphics cache no longer has a changeDisplay method.
1237 if (old_value != rc.display_graphics) {
1238 graphics::GCache & gc = graphics::GCache::get();
1245 void PrefDisplay::updateRC(LyXRC const & rc)
1247 switch (rc.preview) {
1248 case LyXRC::PREVIEW_OFF:
1249 instantPreviewCO->setCurrentIndex(0);
1251 case LyXRC::PREVIEW_NO_MATH :
1252 instantPreviewCO->setCurrentIndex(1);
1254 case LyXRC::PREVIEW_ON :
1255 instantPreviewCO->setCurrentIndex(2);
1259 displayGraphicsCB->setChecked(rc.display_graphics);
1260 previewSizeSB->setValue(rc.preview_scale_factor);
1261 paragraphMarkerCB->setChecked(rc.paragraph_markers);
1262 ctAdditionsUnderlinedCB->setChecked(rc.ct_additions_underlined);
1263 previewSizeSB->setEnabled(
1265 && rc.preview != LyXRC::PREVIEW_OFF);
1269 /////////////////////////////////////////////////////////////////////
1273 /////////////////////////////////////////////////////////////////////
1275 PrefPaths::PrefPaths(GuiPreferences * form)
1276 : PrefModule(QString(), N_("Paths"), form)
1280 connect(workingDirPB, SIGNAL(clicked()), this, SLOT(selectWorkingdir()));
1281 connect(workingDirED, SIGNAL(textChanged(QString)),
1282 this, SIGNAL(changed()));
1284 connect(templateDirPB, SIGNAL(clicked()), this, SLOT(selectTemplatedir()));
1285 connect(templateDirED, SIGNAL(textChanged(QString)),
1286 this, SIGNAL(changed()));
1288 connect(exampleDirPB, SIGNAL(clicked()), this, SLOT(selectExampledir()));
1289 connect(exampleDirED, SIGNAL(textChanged(QString)),
1290 this, SIGNAL(changed()));
1292 connect(backupDirPB, SIGNAL(clicked()), this, SLOT(selectBackupdir()));
1293 connect(backupDirED, SIGNAL(textChanged(QString)),
1294 this, SIGNAL(changed()));
1296 connect(lyxserverDirPB, SIGNAL(clicked()), this, SLOT(selectLyxPipe()));
1297 connect(lyxserverDirED, SIGNAL(textChanged(QString)),
1298 this, SIGNAL(changed()));
1300 connect(thesaurusDirPB, SIGNAL(clicked()), this, SLOT(selectThesaurusdir()));
1301 connect(thesaurusDirED, SIGNAL(textChanged(QString)),
1302 this, SIGNAL(changed()));
1304 connect(tempDirPB, SIGNAL(clicked()), this, SLOT(selectTempdir()));
1305 connect(tempDirED, SIGNAL(textChanged(QString)),
1306 this, SIGNAL(changed()));
1308 #if defined(USE_HUNSPELL)
1309 connect(hunspellDirPB, SIGNAL(clicked()), this, SLOT(selectHunspelldir()));
1310 connect(hunspellDirED, SIGNAL(textChanged(QString)),
1311 this, SIGNAL(changed()));
1313 hunspellDirPB->setEnabled(false);
1314 hunspellDirED->setEnabled(false);
1317 connect(pathPrefixED, SIGNAL(textChanged(QString)),
1318 this, SIGNAL(changed()));
1320 connect(texinputsPrefixED, SIGNAL(textChanged(QString)),
1321 this, SIGNAL(changed()));
1323 pathPrefixED->setValidator(new NoNewLineValidator(pathPrefixED));
1324 texinputsPrefixED->setValidator(new NoNewLineValidator(texinputsPrefixED));
1328 void PrefPaths::applyRC(LyXRC & rc) const
1330 rc.document_path = internal_path(fromqstr(workingDirED->text()));
1331 rc.example_path = internal_path(fromqstr(exampleDirED->text()));
1332 rc.template_path = internal_path(fromqstr(templateDirED->text()));
1333 rc.backupdir_path = internal_path(fromqstr(backupDirED->text()));
1334 rc.tempdir_path = internal_path(fromqstr(tempDirED->text()));
1335 rc.thesaurusdir_path = internal_path(fromqstr(thesaurusDirED->text()));
1336 rc.hunspelldir_path = internal_path(fromqstr(hunspellDirED->text()));
1337 rc.path_prefix = internal_path_list(fromqstr(pathPrefixED->text()));
1338 rc.texinputs_prefix = internal_path_list(fromqstr(texinputsPrefixED->text()));
1339 // FIXME: should be a checkbox only
1340 rc.lyxpipes = internal_path(fromqstr(lyxserverDirED->text()));
1344 void PrefPaths::updateRC(LyXRC const & rc)
1346 workingDirED->setText(toqstr(external_path(rc.document_path)));
1347 exampleDirED->setText(toqstr(external_path(rc.example_path)));
1348 templateDirED->setText(toqstr(external_path(rc.template_path)));
1349 backupDirED->setText(toqstr(external_path(rc.backupdir_path)));
1350 tempDirED->setText(toqstr(external_path(rc.tempdir_path)));
1351 thesaurusDirED->setText(toqstr(external_path(rc.thesaurusdir_path)));
1352 hunspellDirED->setText(toqstr(external_path(rc.hunspelldir_path)));
1353 pathPrefixED->setText(toqstr(external_path_list(rc.path_prefix)));
1354 texinputsPrefixED->setText(toqstr(external_path_list(rc.texinputs_prefix)));
1355 // FIXME: should be a checkbox only
1356 lyxserverDirED->setText(toqstr(external_path(rc.lyxpipes)));
1360 void PrefPaths::selectExampledir()
1362 QString file = form_->browseDir(internalPath(exampleDirED->text()),
1363 qt_("Select directory for example files"));
1364 if (!file.isEmpty())
1365 exampleDirED->setText(file);
1369 void PrefPaths::selectTemplatedir()
1371 QString file = form_->browseDir(internalPath(templateDirED->text()),
1372 qt_("Select a document templates directory"));
1373 if (!file.isEmpty())
1374 templateDirED->setText(file);
1378 void PrefPaths::selectTempdir()
1380 QString file = form_->browseDir(internalPath(tempDirED->text()),
1381 qt_("Select a temporary directory"));
1382 if (!file.isEmpty())
1383 tempDirED->setText(file);
1387 void PrefPaths::selectBackupdir()
1389 QString file = form_->browseDir(internalPath(backupDirED->text()),
1390 qt_("Select a backups directory"));
1391 if (!file.isEmpty())
1392 backupDirED->setText(file);
1396 void PrefPaths::selectWorkingdir()
1398 QString file = form_->browseDir(internalPath(workingDirED->text()),
1399 qt_("Select a document directory"));
1400 if (!file.isEmpty())
1401 workingDirED->setText(file);
1405 void PrefPaths::selectThesaurusdir()
1407 QString file = form_->browseDir(internalPath(thesaurusDirED->text()),
1408 qt_("Set the path to the thesaurus dictionaries"));
1409 if (!file.isEmpty())
1410 thesaurusDirED->setText(file);
1414 void PrefPaths::selectHunspelldir()
1416 QString file = form_->browseDir(internalPath(hunspellDirED->text()),
1417 qt_("Set the path to the Hunspell dictionaries"));
1418 if (!file.isEmpty())
1419 hunspellDirED->setText(file);
1423 void PrefPaths::selectLyxPipe()
1425 QString file = form_->browse(internalPath(lyxserverDirED->text()),
1426 qt_("Give a filename for the LyX server pipe"));
1427 if (!file.isEmpty())
1428 lyxserverDirED->setText(file);
1432 /////////////////////////////////////////////////////////////////////
1436 /////////////////////////////////////////////////////////////////////
1438 PrefSpellchecker::PrefSpellchecker(GuiPreferences * form)
1439 : PrefModule(catLanguage, N_("Spellchecker"), form)
1443 // FIXME: this check should test the target platform (darwin)
1444 #if defined(USE_MACOSX_PACKAGING)
1445 spellcheckerCB->addItem(qt_("Native"), QString("native"));
1446 #define CONNECT_APPLESPELL
1448 #undef CONNECT_APPLESPELL
1450 #if defined(USE_ASPELL)
1451 spellcheckerCB->addItem(qt_("Aspell"), QString("aspell"));
1453 #if defined(USE_ENCHANT)
1454 spellcheckerCB->addItem(qt_("Enchant"), QString("enchant"));
1456 #if defined(USE_HUNSPELL)
1457 spellcheckerCB->addItem(qt_("Hunspell"), QString("hunspell"));
1460 #if defined(CONNECT_APPLESPELL) || defined(USE_ASPELL) || defined(USE_ENCHANT) || defined(USE_HUNSPELL)
1461 connect(spellcheckerCB, SIGNAL(currentIndexChanged(int)),
1462 this, SIGNAL(changed()));
1463 connect(altLanguageED, SIGNAL(textChanged(QString)),
1464 this, SIGNAL(changed()));
1465 connect(escapeCharactersED, SIGNAL(textChanged(QString)),
1466 this, SIGNAL(changed()));
1467 connect(compoundWordCB, SIGNAL(clicked()),
1468 this, SIGNAL(changed()));
1469 connect(spellcheckContinuouslyCB, SIGNAL(clicked()),
1470 this, SIGNAL(changed()));
1471 connect(spellcheckNotesCB, SIGNAL(clicked()),
1472 this, SIGNAL(changed()));
1474 altLanguageED->setValidator(new NoNewLineValidator(altLanguageED));
1475 escapeCharactersED->setValidator(new NoNewLineValidator(escapeCharactersED));
1477 spellcheckerCB->setEnabled(false);
1478 altLanguageED->setEnabled(false);
1479 escapeCharactersED->setEnabled(false);
1480 compoundWordCB->setEnabled(false);
1481 spellcheckContinuouslyCB->setEnabled(false);
1482 spellcheckNotesCB->setEnabled(false);
1487 void PrefSpellchecker::applyRC(LyXRC & rc) const
1489 string const speller = fromqstr(spellcheckerCB->
1490 itemData(spellcheckerCB->currentIndex()).toString());
1491 if (!speller.empty())
1492 rc.spellchecker = speller;
1493 rc.spellchecker_alt_lang = fromqstr(altLanguageED->text());
1494 rc.spellchecker_esc_chars = fromqstr(escapeCharactersED->text());
1495 rc.spellchecker_accept_compound = compoundWordCB->isChecked();
1496 rc.spellcheck_continuously = spellcheckContinuouslyCB->isChecked();
1497 rc.spellcheck_notes = spellcheckNotesCB->isChecked();
1501 void PrefSpellchecker::updateRC(LyXRC const & rc)
1503 spellcheckerCB->setCurrentIndex(
1504 spellcheckerCB->findData(toqstr(rc.spellchecker)));
1505 altLanguageED->setText(toqstr(rc.spellchecker_alt_lang));
1506 escapeCharactersED->setText(toqstr(rc.spellchecker_esc_chars));
1507 compoundWordCB->setChecked(rc.spellchecker_accept_compound);
1508 spellcheckContinuouslyCB->setChecked(rc.spellcheck_continuously);
1509 spellcheckNotesCB->setChecked(rc.spellcheck_notes);
1513 void PrefSpellchecker::on_spellcheckerCB_currentIndexChanged(int index)
1515 QString spellchecker = spellcheckerCB->itemData(index).toString();
1517 compoundWordCB->setEnabled(spellchecker == QString("aspell"));
1522 /////////////////////////////////////////////////////////////////////
1526 /////////////////////////////////////////////////////////////////////
1529 PrefConverters::PrefConverters(GuiPreferences * form)
1530 : PrefModule(catFiles, N_("Converters"), form)
1534 connect(converterNewPB, SIGNAL(clicked()),
1535 this, SLOT(updateConverter()));
1536 connect(converterRemovePB, SIGNAL(clicked()),
1537 this, SLOT(removeConverter()));
1538 connect(converterModifyPB, SIGNAL(clicked()),
1539 this, SLOT(updateConverter()));
1540 connect(convertersLW, SIGNAL(currentRowChanged(int)),
1541 this, SLOT(switchConverter()));
1542 #if QT_VERSION < 0x050e00
1543 connect(converterFromCO, SIGNAL(activated(QString)),
1544 this, SLOT(changeConverter()));
1545 connect(converterToCO, SIGNAL(activated(QString)),
1546 this, SLOT(changeConverter()));
1548 connect(converterFromCO, SIGNAL(textActivated(QString)),
1549 this, SLOT(changeConverter()));
1550 connect(converterToCO, SIGNAL(textActivated(QString)),
1551 this, SLOT(changeConverter()));
1553 connect(converterED, SIGNAL(textEdited(QString)),
1554 this, SLOT(changeConverter()));
1555 connect(converterFlagED, SIGNAL(textEdited(QString)),
1556 this, SLOT(changeConverter()));
1557 connect(converterNewPB, SIGNAL(clicked()),
1558 this, SIGNAL(changed()));
1559 connect(converterRemovePB, SIGNAL(clicked()),
1560 this, SIGNAL(changed()));
1561 connect(converterModifyPB, SIGNAL(clicked()),
1562 this, SIGNAL(changed()));
1563 connect(maxAgeLE, SIGNAL(textEdited(QString)),
1564 this, SIGNAL(changed()));
1565 connect(needauthForbiddenCB, SIGNAL(toggled(bool)),
1566 this, SIGNAL(changed()));
1568 converterED->setValidator(new NoNewLineValidator(converterED));
1569 converterFlagED->setValidator(new NoNewLineValidator(converterFlagED));
1570 maxAgeLE->setValidator(new QDoubleValidator(0, HUGE_VAL, 6, maxAgeLE));
1571 //converterDefGB->setFocusProxy(convertersLW);
1575 void PrefConverters::applyRC(LyXRC & rc) const
1577 rc.use_converter_cache = cacheCB->isChecked();
1578 rc.use_converter_needauth_forbidden = needauthForbiddenCB->isChecked();
1579 rc.use_converter_needauth = needauthCB->isChecked();
1580 rc.converter_cache_maxage = int(widgetToDouble(maxAgeLE) * 86400.0);
1584 static void setCheckboxBlockSignals(QCheckBox *cb, bool checked) {
1585 cb->blockSignals(true);
1586 cb->setChecked(checked);
1587 cb->blockSignals(false);
1591 void PrefConverters::updateRC(LyXRC const & rc)
1593 cacheCB->setChecked(rc.use_converter_cache);
1594 needauthForbiddenCB->setChecked(rc.use_converter_needauth_forbidden);
1595 setCheckboxBlockSignals(needauthCB, rc.use_converter_needauth);
1597 doubleToWidget(maxAgeLE, (double(rc.converter_cache_maxage) / 86400.0), 'g', 6);
1602 void PrefConverters::updateGui()
1604 QString const pattern("%1 -> %2");
1605 form_->formats().sort();
1606 form_->converters().update(form_->formats());
1607 // save current selection
1610 .arg(converterFromCO->currentText())
1611 .arg(converterToCO->currentText());
1613 converterFromCO->clear();
1614 converterToCO->clear();
1616 for (Format const & f : form_->formats()) {
1617 QString const name = toqstr(translateIfPossible(f.prettyname()));
1618 converterFromCO->addItem(name);
1619 converterToCO->addItem(name);
1622 // currentRowChanged(int) is also triggered when updating the listwidget
1623 // block signals to avoid unnecessary calls to switchConverter()
1624 convertersLW->blockSignals(true);
1625 convertersLW->clear();
1627 for (Converter const & c : form_->converters()) {
1628 QString const name =
1630 .arg(toqstr(translateIfPossible(c.From()->prettyname())))
1631 .arg(toqstr(translateIfPossible(c.To()->prettyname())));
1632 int type = form_->converters().getNumber(c.From()->name(),
1634 new QListWidgetItem(name, convertersLW, type);
1636 convertersLW->sortItems(Qt::AscendingOrder);
1637 convertersLW->blockSignals(false);
1639 // restore selection
1640 if (current != pattern.arg(QString()).arg(QString())) {
1641 QList<QListWidgetItem *> const item =
1642 convertersLW->findItems(current, Qt::MatchExactly);
1643 if (!item.isEmpty())
1644 convertersLW->setCurrentItem(item.at(0));
1647 // select first element if restoring failed
1648 if (convertersLW->currentRow() == -1)
1649 convertersLW->setCurrentRow(0);
1655 void PrefConverters::switchConverter()
1657 int const cnr = convertersLW->currentItem()->type();
1658 Converter const & c(form_->converters().get(cnr));
1659 converterFromCO->setCurrentIndex(form_->formats().getNumber(c.from()));
1660 converterToCO->setCurrentIndex(form_->formats().getNumber(c.to()));
1661 converterED->setText(toqstr(c.command()));
1662 converterFlagED->setText(toqstr(c.flags()));
1668 void PrefConverters::changeConverter()
1674 void PrefConverters::updateButtons()
1676 if (form_->formats().empty())
1678 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1679 Format const & to = form_->formats().get(converterToCO->currentIndex());
1680 int const sel = form_->converters().getNumber(from.name(), to.name());
1681 bool const known = sel >= 0;
1682 bool const valid = !(converterED->text().isEmpty()
1683 || from.name() == to.name());
1688 if (convertersLW->count() > 0) {
1689 int const cnr = convertersLW->currentItem()->type();
1690 Converter const & c = form_->converters().get(cnr);
1691 old_command = c.command();
1692 old_flag = c.flags();
1695 string const new_command = fromqstr(converterED->text());
1696 string const new_flag = fromqstr(converterFlagED->text());
1698 bool modified = (old_command != new_command || old_flag != new_flag);
1700 converterModifyPB->setEnabled(valid && known && modified);
1701 converterNewPB->setEnabled(valid && !known);
1702 converterRemovePB->setEnabled(known);
1704 maxAgeLE->setEnabled(cacheCB->isChecked());
1705 maxAgeLA->setEnabled(cacheCB->isChecked());
1710 // specify unique from/to or it doesn't appear. This is really bad UI
1711 // this is why we can use the same function for both new and modify
1712 void PrefConverters::updateConverter()
1714 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1715 Format const & to = form_->formats().get(converterToCO->currentIndex());
1716 string const flags = fromqstr(converterFlagED->text());
1717 string const command = fromqstr(converterED->text());
1719 Converter const * old =
1720 form_->converters().getConverter(from.name(), to.name());
1721 form_->converters().add(from.name(), to.name(), command, flags);
1724 form_->converters().updateLast(form_->formats());
1728 // Remove all files created by this converter from the cache, since
1729 // the modified converter might create different files.
1730 ConverterCache::get().remove_all(from.name(), to.name());
1734 void PrefConverters::removeConverter()
1736 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1737 Format const & to = form_->formats().get(converterToCO->currentIndex());
1738 form_->converters().erase(from.name(), to.name());
1742 // Remove all files created by this converter from the cache, since
1743 // a possible new converter might create different files.
1744 ConverterCache::get().remove_all(from.name(), to.name());
1748 void PrefConverters::on_cacheCB_stateChanged(int state)
1750 maxAgeLE->setEnabled(state == Qt::Checked);
1751 maxAgeLA->setEnabled(state == Qt::Checked);
1756 void PrefConverters::on_needauthForbiddenCB_toggled(bool checked)
1758 needauthCB->setEnabled(!checked);
1762 void PrefConverters::on_needauthCB_toggled(bool checked)
1769 int ret = frontend::Alert::prompt(
1770 _("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!"),
1771 0, 0, _("&No"), _("&Yes"));
1775 setCheckboxBlockSignals(needauthCB, true);
1779 /////////////////////////////////////////////////////////////////////
1783 /////////////////////////////////////////////////////////////////////
1785 class FormatValidator : public QValidator
1788 FormatValidator(QWidget *, Formats const & f);
1789 void fixup(QString & input) const override;
1790 QValidator::State validate(QString & input, int & pos) const override;
1792 virtual QString toString(Format const & format) const = 0;
1794 Formats const & formats_;
1798 FormatValidator::FormatValidator(QWidget * parent, Formats const & f)
1799 : QValidator(parent), formats_(f)
1804 void FormatValidator::fixup(QString & input) const
1806 Formats::const_iterator cit = formats_.begin();
1807 Formats::const_iterator end = formats_.end();
1808 for (; cit != end; ++cit) {
1809 QString const name = toString(*cit);
1810 if (distance(formats_.begin(), cit) == nr()) {
1818 QValidator::State FormatValidator::validate(QString & input, int & /*pos*/) const
1820 Formats::const_iterator cit = formats_.begin();
1821 Formats::const_iterator end = formats_.end();
1822 bool unknown = true;
1823 for (; unknown && cit != end; ++cit) {
1824 QString const name = toString(*cit);
1825 if (distance(formats_.begin(), cit) != nr())
1826 unknown = name != input;
1829 if (unknown && !input.isEmpty())
1830 return QValidator::Acceptable;
1832 return QValidator::Intermediate;
1836 int FormatValidator::nr() const
1838 QComboBox * p = qobject_cast<QComboBox *>(parent());
1839 return p->itemData(p->currentIndex()).toInt();
1843 /////////////////////////////////////////////////////////////////////
1845 // FormatNameValidator
1847 /////////////////////////////////////////////////////////////////////
1849 class FormatNameValidator : public FormatValidator
1852 FormatNameValidator(QWidget * parent, Formats const & f)
1853 : FormatValidator(parent, f)
1856 QString toString(Format const & format) const override
1858 return toqstr(format.name());
1863 /////////////////////////////////////////////////////////////////////
1865 // FormatPrettynameValidator
1867 /////////////////////////////////////////////////////////////////////
1869 class FormatPrettynameValidator : public FormatValidator
1872 FormatPrettynameValidator(QWidget * parent, Formats const & f)
1873 : FormatValidator(parent, f)
1876 QString toString(Format const & format) const override
1878 return toqstr(translateIfPossible(format.prettyname()));
1883 /////////////////////////////////////////////////////////////////////
1887 /////////////////////////////////////////////////////////////////////
1889 PrefFileformats::PrefFileformats(GuiPreferences * form)
1890 : PrefModule(catFiles, N_("File Formats"), form)
1894 formatED->setValidator(new FormatNameValidator(formatsCB, form_->formats()));
1895 formatsCB->setValidator(new FormatPrettynameValidator(formatsCB, form_->formats()));
1896 extensionsED->setValidator(new NoNewLineValidator(extensionsED));
1897 shortcutED->setValidator(new NoNewLineValidator(shortcutED));
1898 editorED->setValidator(new NoNewLineValidator(editorED));
1899 viewerED->setValidator(new NoNewLineValidator(viewerED));
1900 copierED->setValidator(new NoNewLineValidator(copierED));
1902 connect(documentCB, SIGNAL(clicked()),
1903 this, SLOT(setFlags()));
1904 connect(vectorCB, SIGNAL(clicked()),
1905 this, SLOT(setFlags()));
1906 connect(exportMenuCB, SIGNAL(clicked()),
1907 this, SLOT(setFlags()));
1908 connect(formatsCB->lineEdit(), SIGNAL(editingFinished()),
1909 this, SLOT(updatePrettyname()));
1910 connect(formatsCB->lineEdit(), SIGNAL(textEdited(QString)),
1911 this, SIGNAL(changed()));
1912 #if QT_VERSION < 0x050e00
1913 connect(defaultFormatCB, SIGNAL(activated(QString)),
1914 this, SIGNAL(changed()));
1915 connect(defaultOTFFormatCB, SIGNAL(activated(QString)),
1916 this, SIGNAL(changed()));
1917 connect(defaultPlatexFormatCB, SIGNAL(activated(QString)),
1918 this, SIGNAL(changed()));
1920 connect(defaultFormatCB, SIGNAL(textActivated(QString)),
1921 this, SIGNAL(changed()));
1922 connect(defaultOTFFormatCB, SIGNAL(textActivated(QString)),
1923 this, SIGNAL(changed()));
1924 connect(defaultPlatexFormatCB, SIGNAL(textActivated(QString)),
1925 this, SIGNAL(changed()));
1927 connect(viewerCO, SIGNAL(activated(int)),
1928 this, SIGNAL(changed()));
1929 connect(editorCO, SIGNAL(activated(int)),
1930 this, SIGNAL(changed()));
1936 string const l10n_shortcut(docstring const & prettyname, string const & shortcut)
1938 if (shortcut.empty())
1941 string l10n_format =
1942 to_utf8(_(to_utf8(prettyname) + '|' + shortcut));
1943 return split(l10n_format, '|');
1949 void PrefFileformats::applyRC(LyXRC & rc) const
1951 QString const default_format = defaultFormatCB->itemData(
1952 defaultFormatCB->currentIndex()).toString();
1953 rc.default_view_format = fromqstr(default_format);
1954 QString const default_otf_format = defaultOTFFormatCB->itemData(
1955 defaultOTFFormatCB->currentIndex()).toString();
1956 rc.default_otf_view_format = fromqstr(default_otf_format);
1957 QString const default_platex_format = defaultPlatexFormatCB->itemData(
1958 defaultPlatexFormatCB->currentIndex()).toString();
1959 rc.default_platex_view_format = fromqstr(default_platex_format);
1963 void PrefFileformats::updateRC(LyXRC const & rc)
1965 viewer_alternatives = rc.viewer_alternatives;
1966 editor_alternatives = rc.editor_alternatives;
1967 bool const init = defaultFormatCB->currentText().isEmpty();
1971 defaultFormatCB->findData(toqstr(rc.default_view_format));
1972 defaultFormatCB->setCurrentIndex(pos);
1973 pos = defaultOTFFormatCB->findData(toqstr(rc.default_otf_view_format));
1974 defaultOTFFormatCB->setCurrentIndex(pos);
1975 defaultOTFFormatCB->setCurrentIndex(pos);
1976 pos = defaultPlatexFormatCB->findData(toqstr(rc.default_platex_view_format));
1977 defaultPlatexFormatCB->setCurrentIndex(pos);
1978 defaultPlatexFormatCB->setCurrentIndex(pos);
1983 void PrefFileformats::updateView()
1985 QString const current = formatsCB->currentText();
1986 QString const current_def = defaultFormatCB->currentText();
1987 QString const current_def_otf = defaultOTFFormatCB->currentText();
1988 QString const current_def_platex = defaultPlatexFormatCB->currentText();
1990 // update comboboxes with formats
1991 formatsCB->blockSignals(true);
1992 defaultFormatCB->blockSignals(true);
1993 defaultOTFFormatCB->blockSignals(true);
1994 defaultPlatexFormatCB->blockSignals(true);
1996 defaultFormatCB->clear();
1997 defaultOTFFormatCB->clear();
1998 defaultPlatexFormatCB->clear();
1999 form_->formats().sort();
2000 for (Format const & f : form_->formats()) {
2001 QString const prettyname = toqstr(translateIfPossible(f.prettyname()));
2002 formatsCB->addItem(prettyname,
2003 QVariant(form_->formats().getNumber(f.name())));
2004 if (f.viewer().empty())
2006 if (form_->converters().isReachable("xhtml", f.name())
2007 || form_->converters().isReachable("dviluatex", f.name())
2008 || form_->converters().isReachable("luatex", f.name())
2009 || form_->converters().isReachable("xetex", f.name())) {
2010 defaultFormatCB->addItem(prettyname,
2011 QVariant(toqstr(f.name())));
2012 defaultOTFFormatCB->addItem(prettyname,
2013 QVariant(toqstr(f.name())));
2015 if (form_->converters().isReachable("latex", f.name())
2016 || form_->converters().isReachable("pdflatex", f.name()))
2017 defaultFormatCB->addItem(prettyname,
2018 QVariant(toqstr(f.name())));
2019 if (form_->converters().isReachable("platex", f.name()))
2020 defaultPlatexFormatCB->addItem(prettyname,
2021 QVariant(toqstr(f.name())));
2025 // restore selections
2026 int item = formatsCB->findText(current, Qt::MatchExactly);
2027 formatsCB->setCurrentIndex(item < 0 ? 0 : item);
2028 on_formatsCB_currentIndexChanged(item < 0 ? 0 : item);
2029 item = defaultFormatCB->findText(current_def, Qt::MatchExactly);
2030 defaultFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2031 item = defaultOTFFormatCB->findText(current_def_otf, Qt::MatchExactly);
2032 defaultOTFFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2033 item = defaultPlatexFormatCB->findText(current_def_platex, Qt::MatchExactly);
2034 defaultPlatexFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2035 formatsCB->blockSignals(false);
2036 defaultFormatCB->blockSignals(false);
2037 defaultOTFFormatCB->blockSignals(false);
2038 defaultPlatexFormatCB->blockSignals(false);
2042 void PrefFileformats::on_formatsCB_currentIndexChanged(int i)
2044 if (form_->formats().empty())
2046 int const nr = formatsCB->itemData(i).toInt();
2047 Format const f = form_->formats().get(nr);
2049 formatED->setText(toqstr(f.name()));
2050 copierED->setText(toqstr(form_->movers().command(f.name())));
2051 extensionsED->setText(toqstr(f.extensions()));
2052 mimeED->setText(toqstr(f.mime()));
2053 shortcutED->setText(
2054 toqstr(l10n_shortcut(f.prettyname(), f.shortcut())));
2055 documentCB->setChecked((f.documentFormat()));
2056 vectorCB->setChecked((f.vectorFormat()));
2057 exportMenuCB->setChecked((f.inExportMenu()));
2058 exportMenuCB->setEnabled((f.documentFormat()));
2064 void PrefFileformats::setFlags()
2066 int flags = Format::none;
2067 if (documentCB->isChecked())
2068 flags |= Format::document;
2069 if (vectorCB->isChecked())
2070 flags |= Format::vector;
2071 if (exportMenuCB->isChecked())
2072 flags |= Format::export_menu;
2073 currentFormat().setFlags(flags);
2074 exportMenuCB->setEnabled(documentCB->isChecked());
2079 void PrefFileformats::on_copierED_textEdited(const QString & s)
2081 string const fmt = fromqstr(formatED->text());
2082 form_->movers().set(fmt, fromqstr(s));
2087 void PrefFileformats::on_extensionsED_textEdited(const QString & s)
2089 currentFormat().setExtensions(fromqstr(s));
2094 void PrefFileformats::on_viewerED_textEdited(const QString & s)
2096 currentFormat().setViewer(fromqstr(s));
2101 void PrefFileformats::on_editorED_textEdited(const QString & s)
2103 currentFormat().setEditor(fromqstr(s));
2108 void PrefFileformats::on_mimeED_textEdited(const QString & s)
2110 currentFormat().setMime(fromqstr(s));
2115 void PrefFileformats::on_shortcutED_textEdited(const QString & s)
2117 string const new_shortcut = fromqstr(s);
2118 if (new_shortcut == l10n_shortcut(currentFormat().prettyname(),
2119 currentFormat().shortcut()))
2121 currentFormat().setShortcut(new_shortcut);
2126 void PrefFileformats::on_formatED_editingFinished()
2128 string const newname = fromqstr(formatED->displayText());
2129 string const oldname = currentFormat().name();
2130 if (newname == oldname)
2132 if (form_->converters().formatIsUsed(oldname)) {
2133 Alert::error(_("Format in use"),
2134 _("You cannot change a format's short name "
2135 "if the format is used by a converter. "
2136 "Please remove the converter first."));
2141 currentFormat().setName(newname);
2146 void PrefFileformats::on_formatED_textChanged(const QString &)
2148 QString t = formatED->text();
2150 bool valid = formatED->validator()->validate(t, p) == QValidator::Acceptable;
2151 setValid(formatLA, valid);
2155 void PrefFileformats::on_formatsCB_editTextChanged(const QString &)
2157 QString t = formatsCB->currentText();
2159 bool valid = formatsCB->validator()->validate(t, p) == QValidator::Acceptable;
2160 setValid(formatsLA, valid);
2164 void PrefFileformats::updatePrettyname()
2166 QString const newname = formatsCB->currentText();
2167 if (newname == toqstr(translateIfPossible(currentFormat().prettyname())))
2170 currentFormat().setPrettyname(qstring_to_ucs4(newname));
2178 void updateComboBox(LyXRC::Alternatives const & alts,
2179 string const & fmt, QComboBox * combo)
2181 LyXRC::Alternatives::const_iterator it =
2183 if (it != alts.end()) {
2184 LyXRC::CommandSet const & cmds = it->second;
2185 LyXRC::CommandSet::const_iterator sit =
2187 LyXRC::CommandSet::const_iterator const sen =
2189 for (; sit != sen; ++sit) {
2190 QString const qcmd = toqstr(*sit);
2191 combo->addItem(qcmd, qcmd);
2198 void PrefFileformats::updateViewers()
2200 Format const f = currentFormat();
2201 viewerCO->blockSignals(true);
2203 viewerCO->addItem(qt_("None"), QString());
2204 if (os::canAutoOpenFile(f.extension(), os::VIEW))
2205 viewerCO->addItem(qt_("System Default"), QString("auto"));
2206 updateComboBox(viewer_alternatives, f.name(), viewerCO);
2207 viewerCO->addItem(qt_("Custom"), QString("custom viewer"));
2208 viewerCO->blockSignals(false);
2210 int pos = viewerCO->findData(toqstr(f.viewer()));
2213 viewerED->setEnabled(false);
2214 viewerCO->setCurrentIndex(pos);
2216 viewerED->setEnabled(true);
2217 viewerED->setText(toqstr(f.viewer()));
2218 viewerCO->setCurrentIndex(viewerCO->findData(toqstr("custom viewer")));
2223 void PrefFileformats::updateEditors()
2225 Format const f = currentFormat();
2226 editorCO->blockSignals(true);
2228 editorCO->addItem(qt_("None"), QString());
2229 if (os::canAutoOpenFile(f.extension(), os::EDIT))
2230 editorCO->addItem(qt_("System Default"), QString("auto"));
2231 updateComboBox(editor_alternatives, f.name(), editorCO);
2232 editorCO->addItem(qt_("Custom"), QString("custom editor"));
2233 editorCO->blockSignals(false);
2235 int pos = editorCO->findData(toqstr(f.editor()));
2238 editorED->setEnabled(false);
2239 editorCO->setCurrentIndex(pos);
2241 editorED->setEnabled(true);
2242 editorED->setText(toqstr(f.editor()));
2243 editorCO->setCurrentIndex(editorCO->findData(toqstr("custom editor")));
2248 void PrefFileformats::on_viewerCO_currentIndexChanged(int i)
2250 bool const custom = viewerCO->itemData(i).toString() == "custom viewer";
2251 viewerED->setEnabled(custom);
2253 currentFormat().setViewer(fromqstr(viewerCO->itemData(i).toString()));
2257 void PrefFileformats::on_editorCO_currentIndexChanged(int i)
2259 bool const custom = editorCO->itemData(i).toString() == "custom editor";
2260 editorED->setEnabled(custom);
2262 currentFormat().setEditor(fromqstr(editorCO->itemData(i).toString()));
2266 Format & PrefFileformats::currentFormat()
2268 int const i = formatsCB->currentIndex();
2269 int const nr = formatsCB->itemData(i).toInt();
2270 return form_->formats().get(nr);
2274 void PrefFileformats::on_formatNewPB_clicked()
2276 form_->formats().add("", "", docstring(), "", "", "", "", Format::none);
2278 formatsCB->setCurrentIndex(0);
2279 formatsCB->setFocus(Qt::OtherFocusReason);
2283 void PrefFileformats::on_formatRemovePB_clicked()
2285 int const i = formatsCB->currentIndex();
2286 int const nr = formatsCB->itemData(i).toInt();
2287 string const current_text = form_->formats().get(nr).name();
2288 if (form_->converters().formatIsUsed(current_text)) {
2289 Alert::error(_("Format in use"),
2290 _("Cannot remove a Format used by a Converter. "
2291 "Remove the converter first."));
2295 form_->formats().erase(current_text);
2298 on_formatsCB_editTextChanged(formatsCB->currentText());
2303 /////////////////////////////////////////////////////////////////////
2307 /////////////////////////////////////////////////////////////////////
2309 PrefLanguage::PrefLanguage(GuiPreferences * form)
2310 : PrefModule(catLanguage, N_("Language"), form)
2314 connect(visualCursorRB, SIGNAL(clicked()),
2315 this, SIGNAL(changed()));
2316 connect(logicalCursorRB, SIGNAL(clicked()),
2317 this, SIGNAL(changed()));
2318 connect(markForeignCB, SIGNAL(clicked()),
2319 this, SIGNAL(changed()));
2320 connect(respectOSkbdCB, SIGNAL(clicked()),
2321 this, SIGNAL(changed()));
2322 connect(explicitDocLangBeginCB, SIGNAL(clicked()),
2323 this, SIGNAL(changed()));
2324 connect(explicitDocLangEndCB, SIGNAL(clicked()),
2325 this, SIGNAL(changed()));
2326 connect(languagePackageCO, SIGNAL(activated(int)),
2327 this, SIGNAL(changed()));
2328 connect(languagePackageED, SIGNAL(textChanged(QString)),
2329 this, SIGNAL(changed()));
2330 connect(globalCB, SIGNAL(clicked()),
2331 this, SIGNAL(changed()));
2332 connect(startCommandED, SIGNAL(textChanged(QString)),
2333 this, SIGNAL(changed()));
2334 connect(endCommandED, SIGNAL(textChanged(QString)),
2335 this, SIGNAL(changed()));
2336 connect(uiLanguageCO, SIGNAL(activated(int)),
2337 this, SIGNAL(changed()));
2338 connect(defaultDecimalSepED, SIGNAL(textChanged(QString)),
2339 this, SIGNAL(changed()));
2340 connect(defaultDecimalSepCO, SIGNAL(activated(int)),
2341 this, SIGNAL(changed()));
2342 connect(defaultLengthUnitCO, SIGNAL(activated(int)),
2343 this, SIGNAL(changed()));
2345 languagePackageED->setValidator(new NoNewLineValidator(languagePackageED));
2346 startCommandED->setValidator(new NoNewLineValidator(startCommandED));
2347 endCommandED->setValidator(new NoNewLineValidator(endCommandED));
2349 defaultDecimalSepED->setValidator(new QRegularExpressionValidator(QRegularExpression("\\S"), this));
2350 defaultDecimalSepED->setMaxLength(1);
2352 defaultLengthUnitCO->addItem(lyx::qt_(unit_name_gui[Length::CM]), Length::CM);
2353 defaultLengthUnitCO->addItem(lyx::qt_(unit_name_gui[Length::IN]), Length::IN);
2355 QAbstractItemModel * language_model = guiApp->languageModel();
2356 language_model->sort(0);
2357 uiLanguageCO->blockSignals(true);
2358 uiLanguageCO->clear();
2359 uiLanguageCO->addItem(qt_("Default"), toqstr("auto"));
2360 for (int i = 0; i != language_model->rowCount(); ++i) {
2361 QModelIndex index = language_model->index(i, 0);
2362 // Filter the list based on the available translation and add
2363 // each language code only once
2364 string const name = fromqstr(index.data(Qt::UserRole).toString());
2365 Language const * lang = languages.getLanguage(name);
2368 // never remove the currently selected language
2369 if (name != form->rc().gui_language
2370 && name != lyxrc.gui_language
2371 && (!Messages::available(lang->code())
2372 || !lang->hasGuiSupport()))
2374 uiLanguageCO->addItem(index.data(Qt::DisplayRole).toString(),
2375 index.data(Qt::UserRole).toString());
2377 uiLanguageCO->blockSignals(false);
2379 // FIXME: restore this when it works (see discussion in #6450).
2380 respectOSkbdCB->hide();
2384 void PrefLanguage::on_uiLanguageCO_currentIndexChanged(int)
2386 QMessageBox::information(this, qt_("LyX needs to be restarted!"),
2387 qt_("The change of user interface language will be fully "
2388 "effective only after a restart."));
2392 void PrefLanguage::on_languagePackageCO_currentIndexChanged(int i)
2395 languagePackageED->setText(save_langpack_);
2396 else if (!languagePackageED->text().isEmpty()) {
2397 save_langpack_ = languagePackageED->text();
2398 languagePackageED->clear();
2400 languagePackageED->setEnabled(i == 2);
2404 void PrefLanguage::on_defaultDecimalSepCO_currentIndexChanged(int i)
2406 defaultDecimalSepED->setEnabled(i == 1);
2410 void PrefLanguage::applyRC(LyXRC & rc) const
2412 rc.visual_cursor = visualCursorRB->isChecked();
2413 rc.mark_foreign_language = markForeignCB->isChecked();
2414 rc.respect_os_kbd_language = respectOSkbdCB->isChecked();
2415 rc.language_auto_begin = !explicitDocLangBeginCB->isChecked();
2416 rc.language_auto_end = !explicitDocLangEndCB->isChecked();
2417 int const p = languagePackageCO->currentIndex();
2419 rc.language_package_selection = LyXRC::LP_AUTO;
2421 rc.language_package_selection = LyXRC::LP_BABEL;
2423 rc.language_package_selection = LyXRC::LP_CUSTOM;
2425 rc.language_package_selection = LyXRC::LP_NONE;
2426 rc.language_custom_package = fromqstr(languagePackageED->text());
2427 rc.language_global_options = globalCB->isChecked();
2428 rc.language_command_begin = fromqstr(startCommandED->text());
2429 rc.language_command_end = fromqstr(endCommandED->text());
2430 rc.gui_language = fromqstr(
2431 uiLanguageCO->itemData(uiLanguageCO->currentIndex()).toString());
2432 if (defaultDecimalSepCO->currentIndex() == 0)
2433 rc.default_decimal_sep = "locale";
2435 rc.default_decimal_sep = fromqstr(defaultDecimalSepED->text());
2436 rc.default_length_unit = (Length::UNIT) defaultLengthUnitCO->itemData(defaultLengthUnitCO->currentIndex()).toInt();
2440 void PrefLanguage::updateRC(LyXRC const & rc)
2442 if (rc.visual_cursor)
2443 visualCursorRB->setChecked(true);
2445 logicalCursorRB->setChecked(true);
2446 markForeignCB->setChecked(rc.mark_foreign_language);
2447 respectOSkbdCB->setChecked(rc.respect_os_kbd_language);
2448 explicitDocLangBeginCB->setChecked(!rc.language_auto_begin);
2449 explicitDocLangEndCB->setChecked(!rc.language_auto_end);
2450 languagePackageCO->setCurrentIndex(rc.language_package_selection);
2451 if (languagePackageCO->currentIndex() == 2) {
2452 languagePackageED->setText(toqstr(rc.language_custom_package));
2453 languagePackageED->setEnabled(true);
2455 languagePackageED->clear();
2456 save_langpack_ = toqstr(rc.language_custom_package);
2457 languagePackageED->setEnabled(false);
2459 defaultDecimalSepED->setEnabled(defaultDecimalSepCO->currentIndex() == 1);
2460 globalCB->setChecked(rc.language_global_options);
2461 startCommandED->setText(toqstr(rc.language_command_begin));
2462 endCommandED->setText(toqstr(rc.language_command_end));
2463 if (rc.default_decimal_sep == "locale") {
2464 defaultDecimalSepCO->setCurrentIndex(0);
2465 defaultDecimalSepED->clear();
2467 defaultDecimalSepCO->setCurrentIndex(1);
2468 defaultDecimalSepED->setText(toqstr(rc.default_decimal_sep));
2470 int pos = defaultLengthUnitCO->findData(int(rc.default_length_unit));
2471 defaultLengthUnitCO->setCurrentIndex(pos);
2473 pos = uiLanguageCO->findData(toqstr(rc.gui_language));
2474 uiLanguageCO->blockSignals(true);
2475 uiLanguageCO->setCurrentIndex(pos);
2476 uiLanguageCO->blockSignals(false);
2480 /////////////////////////////////////////////////////////////////////
2482 // PrefUserInterface
2484 /////////////////////////////////////////////////////////////////////
2486 PrefUserInterface::PrefUserInterface(GuiPreferences * form)
2487 : PrefModule(catLookAndFeel, N_("User Interface"), form)
2491 connect(uiFilePB, SIGNAL(clicked()),
2492 this, SLOT(selectUi()));
2493 connect(uiFileED, SIGNAL(textChanged(QString)),
2494 this, SIGNAL(changed()));
2495 connect(iconSetCO, SIGNAL(activated(int)),
2496 this, SIGNAL(changed()));
2497 connect(useSystemThemeIconsCB, SIGNAL(clicked()),
2498 this, SIGNAL(changed()));
2499 connect(lastfilesSB, SIGNAL(valueChanged(int)),
2500 this, SIGNAL(changed()));
2501 connect(tooltipCB, SIGNAL(toggled(bool)),
2502 this, SIGNAL(changed()));
2503 connect(toggleTabbarCB, SIGNAL(toggled(bool)),
2504 this, SIGNAL(changed()));
2505 connect(toggleMenubarCB, SIGNAL(toggled(bool)),
2506 this, SIGNAL(changed()));
2507 connect(toggleScrollbarCB, SIGNAL(toggled(bool)),
2508 this, SIGNAL(changed()));
2509 connect(toggleStatusbarCB, SIGNAL(toggled(bool)),
2510 this, SIGNAL(changed()));
2511 connect(toggleToolbarsCB, SIGNAL(toggled(bool)),
2512 this, SIGNAL(changed()));
2513 lastfilesSB->setMaximum(maxlastfiles);
2515 iconSetCO->addItem(qt_("Default"), QString());
2516 iconSetCO->addItem(qt_("Classic"), "classic");
2517 iconSetCO->addItem(qt_("Oxygen"), "oxygen");
2519 if (guiApp->platformName() != "xcb"
2520 && !guiApp->platformName().contains("wayland"))
2521 useSystemThemeIconsCB->hide();
2525 void PrefUserInterface::applyRC(LyXRC & rc) const
2527 rc.icon_set = fromqstr(iconSetCO->itemData(
2528 iconSetCO->currentIndex()).toString());
2530 rc.ui_file = internal_path(fromqstr(uiFileED->text()));
2531 rc.use_system_theme_icons = useSystemThemeIconsCB->isChecked();
2532 rc.num_lastfiles = lastfilesSB->value();
2533 rc.use_tooltip = tooltipCB->isChecked();
2534 rc.full_screen_toolbars = toggleToolbarsCB->isChecked();
2535 rc.full_screen_scrollbar = toggleScrollbarCB->isChecked();
2536 rc.full_screen_statusbar = toggleStatusbarCB->isChecked();
2537 rc.full_screen_tabbar = toggleTabbarCB->isChecked();
2538 rc.full_screen_menubar = toggleMenubarCB->isChecked();
2542 void PrefUserInterface::updateRC(LyXRC const & rc)
2544 int iconset = iconSetCO->findData(toqstr(rc.icon_set));
2547 iconSetCO->setCurrentIndex(iconset);
2548 useSystemThemeIconsCB->setChecked(rc.use_system_theme_icons);
2549 uiFileED->setText(toqstr(external_path(rc.ui_file)));
2550 lastfilesSB->setValue(rc.num_lastfiles);
2551 tooltipCB->setChecked(rc.use_tooltip);
2552 toggleScrollbarCB->setChecked(rc.full_screen_scrollbar);
2553 toggleStatusbarCB->setChecked(rc.full_screen_statusbar);
2554 toggleToolbarsCB->setChecked(rc.full_screen_toolbars);
2555 toggleTabbarCB->setChecked(rc.full_screen_tabbar);
2556 toggleMenubarCB->setChecked(rc.full_screen_menubar);
2560 void PrefUserInterface::selectUi()
2562 QString file = form_->browseUI(internalPath(uiFileED->text()));
2563 if (!file.isEmpty())
2564 uiFileED->setText(file);
2568 /////////////////////////////////////////////////////////////////////
2570 // PrefDocumentHandling
2572 /////////////////////////////////////////////////////////////////////
2574 PrefDocHandling::PrefDocHandling(GuiPreferences * form)
2575 : PrefModule(catLookAndFeel, N_("Document Handling"), form)
2579 connect(autoSaveCB, SIGNAL(toggled(bool)),
2580 autoSaveSB, SLOT(setEnabled(bool)));
2581 connect(autoSaveCB, SIGNAL(toggled(bool)),
2582 TextLabel1, SLOT(setEnabled(bool)));
2583 connect(openDocumentsInTabsCB, SIGNAL(clicked()),
2584 this, SIGNAL(changed()));
2585 connect(singleInstanceCB, SIGNAL(clicked()),
2586 this, SIGNAL(changed()));
2587 connect(singleCloseTabButtonCB, SIGNAL(clicked()),
2588 this, SIGNAL(changed()));
2589 connect(closeLastViewCO, SIGNAL(activated(int)),
2590 this, SIGNAL(changed()));
2591 connect(restoreCursorCB, SIGNAL(clicked()),
2592 this, SIGNAL(changed()));
2593 connect(loadSessionCB, SIGNAL(clicked()),
2594 this, SIGNAL(changed()));
2595 connect(allowGeometrySessionCB, SIGNAL(clicked()),
2596 this, SIGNAL(changed()));
2597 connect(autoSaveSB, SIGNAL(valueChanged(int)),
2598 this, SIGNAL(changed()));
2599 connect(autoSaveCB, SIGNAL(clicked()),
2600 this, SIGNAL(changed()));
2601 connect(backupCB, SIGNAL(clicked()),
2602 this, SIGNAL(changed()));
2603 connect(saveCompressedCB, SIGNAL(clicked()),
2604 this, SIGNAL(changed()));
2605 connect(saveOriginCB, SIGNAL(clicked()),
2606 this, SIGNAL(changed()));
2610 void PrefDocHandling::applyRC(LyXRC & rc) const
2612 rc.use_lastfilepos = restoreCursorCB->isChecked();
2613 rc.load_session = loadSessionCB->isChecked();
2614 rc.allow_geometry_session = allowGeometrySessionCB->isChecked();
2615 rc.autosave = autoSaveCB->isChecked() ? autoSaveSB->value() * 60 : 0;
2616 rc.make_backup = backupCB->isChecked();
2617 rc.save_compressed = saveCompressedCB->isChecked();
2618 rc.save_origin = saveOriginCB->isChecked();
2619 rc.open_buffers_in_tabs = openDocumentsInTabsCB->isChecked();
2620 rc.single_instance = singleInstanceCB->isChecked();
2621 rc.single_close_tab_button = singleCloseTabButtonCB->isChecked();
2623 switch (closeLastViewCO->currentIndex()) {
2625 rc.close_buffer_with_last_view = "yes";
2628 rc.close_buffer_with_last_view = "no";
2631 rc.close_buffer_with_last_view = "ask";
2639 void PrefDocHandling::updateRC(LyXRC const & rc)
2641 restoreCursorCB->setChecked(rc.use_lastfilepos);
2642 loadSessionCB->setChecked(rc.load_session);
2643 allowGeometrySessionCB->setChecked(rc.allow_geometry_session);
2644 // convert to minutes
2645 bool autosave = rc.autosave > 0;
2646 int mins = rc.autosave / 60;
2649 autoSaveSB->setValue(mins);
2650 autoSaveCB->setChecked(autosave);
2651 autoSaveSB->setEnabled(autosave);
2652 backupCB->setChecked(rc.make_backup);
2653 saveCompressedCB->setChecked(rc.save_compressed);
2654 saveOriginCB->setChecked(rc.save_origin);
2655 openDocumentsInTabsCB->setChecked(rc.open_buffers_in_tabs);
2656 singleInstanceCB->setChecked(rc.single_instance && !rc.lyxpipes.empty());
2657 singleInstanceCB->setEnabled(!rc.lyxpipes.empty());
2658 singleCloseTabButtonCB->setChecked(rc.single_close_tab_button);
2659 if (rc.close_buffer_with_last_view == "yes")
2660 closeLastViewCO->setCurrentIndex(0);
2661 else if (rc.close_buffer_with_last_view == "no")
2662 closeLastViewCO->setCurrentIndex(1);
2663 else if (rc.close_buffer_with_last_view == "ask")
2664 closeLastViewCO->setCurrentIndex(2);
2665 if (rc.backupdir_path.empty())
2666 backupCB->setToolTip(qt_("If this is checked, a backup of the document is created "
2667 "in the current working directory. "
2668 "The backup file has the same name but the suffix '.lyx~'. "
2669 "Note that these files are hidden by default by some file managers. "
2670 "A dedicated backup directory can be set in the 'Paths' section."));
2672 docstring const tip = bformat(_("If this is checked, a backup of the document is created "
2673 "in the backup directory (%1$s). "
2674 "The backup file has the full original path and name as file name "
2675 "and the suffix \'.lyx~\' (e.g., !mydir!filename.lyx~). "
2676 "Note that these files are hidden by default by some file managers."),
2677 FileName(rc.backupdir_path).absoluteFilePath());
2678 backupCB->setToolTip(toqstr(tip));
2683 void PrefDocHandling::on_clearSessionPB_clicked()
2685 guiApp->clearSession();
2690 /////////////////////////////////////////////////////////////////////
2694 /////////////////////////////////////////////////////////////////////
2696 PrefEdit::PrefEdit(GuiPreferences * form)
2697 : PrefModule(catEditing, N_("Control"), form)
2701 connect(cursorFollowsCB, SIGNAL(clicked()),
2702 this, SIGNAL(changed()));
2703 connect(scrollBelowCB, SIGNAL(clicked()),
2704 this, SIGNAL(changed()));
2705 connect(macLikeCursorMovementCB, SIGNAL(clicked()),
2706 this, SIGNAL(changed()));
2707 connect(copyCTMarkupCB, SIGNAL(clicked()),
2708 this, SIGNAL(changed()));
2709 connect(sortEnvironmentsCB, SIGNAL(clicked()),
2710 this, SIGNAL(changed()));
2711 connect(groupEnvironmentsCB, SIGNAL(clicked()),
2712 this, SIGNAL(changed()));
2713 connect(macroEditStyleCO, SIGNAL(activated(int)),
2714 this, SIGNAL(changed()));
2715 connect(cursorWidthSB, SIGNAL(valueChanged(int)),
2716 this, SIGNAL(changed()));
2717 connect(citationSearchLE, SIGNAL(textChanged(QString)),
2718 this, SIGNAL(changed()));
2719 connect(screenWidthLE, SIGNAL(textChanged(QString)),
2720 this, SIGNAL(changed()));
2721 connect(screenWidthUnitCO, SIGNAL(selectionChanged(lyx::Length::UNIT)),
2722 this, SIGNAL(changed()));
2726 void PrefEdit::on_screenLimitCB_toggled(bool const state)
2728 screenWidthLE->setEnabled(state);
2729 screenWidthUnitCO->setEnabled(state);
2734 void PrefEdit::on_citationSearchCB_toggled(bool const state)
2736 citationSearchLE->setEnabled(state);
2737 citationSearchLA->setEnabled(state);
2742 void PrefEdit::applyRC(LyXRC & rc) const
2744 rc.cursor_follows_scrollbar = cursorFollowsCB->isChecked();
2745 rc.scroll_below_document = scrollBelowCB->isChecked();
2746 rc.mac_like_cursor_movement = macLikeCursorMovementCB->isChecked();
2747 rc.ct_markup_copied = copyCTMarkupCB->isChecked();
2748 rc.sort_layouts = sortEnvironmentsCB->isChecked();
2749 rc.group_layouts = groupEnvironmentsCB->isChecked();
2750 switch (macroEditStyleCO->currentIndex()) {
2751 case 0: rc.macro_edit_style = LyXRC::MACRO_EDIT_INLINE_BOX; break;
2752 case 1: rc.macro_edit_style = LyXRC::MACRO_EDIT_INLINE; break;
2753 case 2: rc.macro_edit_style = LyXRC::MACRO_EDIT_LIST; break;
2755 rc.cursor_width = cursorWidthSB->value();
2756 rc.citation_search = citationSearchCB->isChecked();
2757 rc.citation_search_pattern = fromqstr(citationSearchLE->text());
2758 rc.screen_width = Length(widgetsToLength(screenWidthLE, screenWidthUnitCO));
2759 rc.screen_limit = screenLimitCB->isChecked();
2763 void PrefEdit::updateRC(LyXRC const & rc)
2765 cursorFollowsCB->setChecked(rc.cursor_follows_scrollbar);
2766 scrollBelowCB->setChecked(rc.scroll_below_document);
2767 macLikeCursorMovementCB->setChecked(rc.mac_like_cursor_movement);
2768 copyCTMarkupCB->setChecked(rc.ct_markup_copied);
2769 sortEnvironmentsCB->setChecked(rc.sort_layouts);
2770 groupEnvironmentsCB->setChecked(rc.group_layouts);
2771 macroEditStyleCO->setCurrentIndex(rc.macro_edit_style);
2772 cursorWidthSB->setValue(rc.cursor_width);
2773 citationSearchCB->setChecked(rc.citation_search);
2774 citationSearchLE->setText(toqstr(rc.citation_search_pattern));
2775 citationSearchLE->setEnabled(rc.citation_search);
2776 citationSearchLA->setEnabled(rc.citation_search);
2777 lengthToWidgets(screenWidthLE, screenWidthUnitCO, rc.screen_width, Length::defaultUnit());
2778 screenWidthUnitCO->setEnabled(rc.screen_limit);
2779 screenLimitCB->setChecked(rc.screen_limit);
2780 screenWidthLE->setEnabled(rc.screen_limit);
2784 /////////////////////////////////////////////////////////////////////
2788 /////////////////////////////////////////////////////////////////////
2791 GuiShortcutDialog::GuiShortcutDialog(QWidget * parent) : QDialog(parent)
2793 Ui::shortcutUi::setupUi(this);
2794 QDialog::setModal(true);
2795 lfunLE->setValidator(new NoNewLineValidator(lfunLE));
2796 on_lfunLE_textChanged();
2800 void GuiShortcutDialog::on_lfunLE_textChanged()
2802 QPushButton * ok = buttonBox->button(QDialogButtonBox::Ok);
2803 ok->setEnabled(!lfunLE->text().isEmpty());
2807 PrefShortcuts::PrefShortcuts(GuiPreferences * form)
2808 : PrefModule(catEditing, N_("Shortcuts"), form),
2809 editItem_(nullptr), mathItem_(nullptr), bufferItem_(nullptr), layoutItem_(nullptr),
2810 systemItem_(nullptr)
2814 shortcutsTW->setColumnCount(2);
2815 shortcutsTW->headerItem()->setText(0, qt_("Function"));
2816 shortcutsTW->headerItem()->setText(1, qt_("Shortcut"));
2817 shortcutsTW->setSortingEnabled(true);
2818 // Multi-selection can be annoying.
2819 // shortcutsTW->setSelectionMode(QAbstractItemView::MultiSelection);
2821 connect(bindFilePB, SIGNAL(clicked()),
2822 this, SLOT(selectBind()));
2823 connect(bindFileED, SIGNAL(textChanged(QString)),
2824 this, SIGNAL(changed()));
2826 shortcut_ = new GuiShortcutDialog(this);
2827 shortcut_bc_.setPolicy(ButtonPolicy::OkCancelPolicy);
2828 shortcut_bc_.setOK(shortcut_->buttonBox->button(QDialogButtonBox::Ok));
2829 shortcut_bc_.setCancel(shortcut_->buttonBox->button(QDialogButtonBox::Cancel));
2831 connect(shortcut_->buttonBox, SIGNAL(accepted()),
2832 this, SIGNAL(changed()));
2833 connect(shortcut_->buttonBox, SIGNAL(rejected()),
2834 shortcut_, SLOT(reject()));
2835 connect(shortcut_->clearPB, SIGNAL(clicked()),
2836 this, SLOT(shortcutClearPressed()));
2837 connect(shortcut_->removePB, SIGNAL(clicked()),
2838 this, SLOT(shortcutRemovePressed()));
2839 connect(shortcut_->buttonBox, SIGNAL(accepted()),
2840 this, SLOT(shortcutOkPressed()));
2841 connect(shortcut_->buttonBox, SIGNAL(rejected()),
2842 this, SLOT(shortcutCancelPressed()));
2846 void PrefShortcuts::applyRC(LyXRC & rc) const
2848 rc.bind_file = internal_path(fromqstr(bindFileED->text()));
2849 // write user_bind and user_unbind to .lyx/bind/user.bind
2850 FileName bind_dir(addPath(package().user_support().absFileName(), "bind"));
2851 if (!bind_dir.exists() && !bind_dir.createDirectory(0777)) {
2852 lyxerr << "LyX could not create the user bind directory '"
2853 << bind_dir << "'. All user-defined key bindings will be lost." << endl;
2856 if (!bind_dir.isDirWritable()) {
2857 lyxerr << "LyX could not write to the user bind directory '"
2858 << bind_dir << "'. All user-defined key bindings will be lost." << endl;
2861 FileName user_bind_file(bind_dir.absFileName() + "/user.bind");
2862 user_unbind_.write(user_bind_file.toFilesystemEncoding(), false, true);
2863 user_bind_.write(user_bind_file.toFilesystemEncoding(), true, false);
2864 // immediately apply the keybindings. Why this is not done before?
2865 // The good thing is that the menus are updated automatically.
2866 theTopLevelKeymap().clear();
2867 theTopLevelKeymap().read("site");
2868 theTopLevelKeymap().read(rc.bind_file, nullptr, KeyMap::Fallback);
2869 theTopLevelKeymap().read("user", nullptr, KeyMap::MissingOK);
2873 void PrefShortcuts::updateRC(LyXRC const & rc)
2875 bindFileED->setText(toqstr(external_path(rc.bind_file)));
2877 system_bind_.clear();
2879 user_unbind_.clear();
2880 system_bind_.read("site");
2881 system_bind_.read(rc.bind_file);
2882 // \unbind in user.bind is added to user_unbind_
2883 user_bind_.read("user", &user_unbind_, KeyMap::MissingOK);
2884 updateShortcutsTW();
2888 void PrefShortcuts::updateShortcutsTW()
2890 shortcutsTW->clear();
2892 editItem_ = new QTreeWidgetItem(shortcutsTW);
2893 editItem_->setText(0, qt_("Cursor, Mouse and Editing Functions"));
2894 editItem_->setFlags(editItem_->flags() & ~Qt::ItemIsSelectable);
2896 mathItem_ = new QTreeWidgetItem(shortcutsTW);
2897 mathItem_->setText(0, qt_("Mathematical Symbols"));
2898 mathItem_->setFlags(mathItem_->flags() & ~Qt::ItemIsSelectable);
2900 bufferItem_ = new QTreeWidgetItem(shortcutsTW);
2901 bufferItem_->setText(0, qt_("Document and Window"));
2902 bufferItem_->setFlags(bufferItem_->flags() & ~Qt::ItemIsSelectable);
2904 layoutItem_ = new QTreeWidgetItem(shortcutsTW);
2905 layoutItem_->setText(0, qt_("Font, Layouts and Textclasses"));
2906 layoutItem_->setFlags(layoutItem_->flags() & ~Qt::ItemIsSelectable);
2908 systemItem_ = new QTreeWidgetItem(shortcutsTW);
2909 systemItem_->setText(0, qt_("System and Miscellaneous"));
2910 systemItem_->setFlags(systemItem_->flags() & ~Qt::ItemIsSelectable);
2912 // listBindings(unbound=true) lists all bound and unbound lfuns
2913 // Items in this list is tagged by its source.
2914 KeyMap::BindingList bindinglist = system_bind_.listBindings(true,
2916 KeyMap::BindingList user_bindinglist = user_bind_.listBindings(false,
2918 KeyMap::BindingList user_unbindinglist = user_unbind_.listBindings(false,
2919 KeyMap::UserUnbind);
2920 bindinglist.insert(bindinglist.end(), user_bindinglist.begin(),
2921 user_bindinglist.end());
2922 bindinglist.insert(bindinglist.end(), user_unbindinglist.begin(),
2923 user_unbindinglist.end());
2925 KeyMap::BindingList::const_iterator it = bindinglist.begin();
2926 KeyMap::BindingList::const_iterator it_end = bindinglist.end();
2927 for (; it != it_end; ++it)
2928 insertShortcutItem(it->request, it->sequence, it->tag);
2930 shortcutsTW->sortItems(0, Qt::AscendingOrder);
2931 on_shortcutsTW_itemSelectionChanged();
2932 on_searchLE_textEdited();
2933 shortcutsTW->resizeColumnToContents(0);
2938 KeyMap::ItemType PrefShortcuts::itemType(QTreeWidgetItem & item)
2940 return static_cast<KeyMap::ItemType>(item.data(0, Qt::UserRole).toInt());
2945 bool PrefShortcuts::isAlwaysHidden(QTreeWidgetItem & item)
2947 // Hide rebound system settings that are empty
2948 return itemType(item) == KeyMap::UserUnbind && item.text(1).isEmpty();
2952 void PrefShortcuts::setItemType(QTreeWidgetItem * item, KeyMap::ItemType tag)
2954 item->setData(0, Qt::UserRole, QVariant(tag));
2958 case KeyMap::System:
2960 case KeyMap::UserBind:
2963 case KeyMap::UserUnbind:
2964 font.setStrikeOut(true);
2966 // this item is not displayed now.
2967 case KeyMap::UserExtraUnbind:
2968 font.setStrikeOut(true);
2971 item->setHidden(isAlwaysHidden(*item));
2972 item->setFont(1, font);
2976 QTreeWidgetItem * PrefShortcuts::insertShortcutItem(FuncRequest const & lfun,
2977 KeySequence const & seq, KeyMap::ItemType tag)
2979 FuncCode const action = lfun.action();
2980 string const action_name = lyxaction.getActionName(action);
2981 QString const lfun_name = toqstr(from_utf8(action_name)
2982 + ' ' + lfun.argument());
2983 QString const shortcut = toqstr(seq.print(KeySequence::ForGui));
2985 QTreeWidgetItem * newItem = nullptr;
2986 // for unbind items, try to find an existing item in the system bind list
2987 if (tag == KeyMap::UserUnbind) {
2988 QList<QTreeWidgetItem*> const items = shortcutsTW->findItems(shortcut,
2989 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 1);
2990 for (auto const & item : items) {
2991 if (item->text(0) == lfun_name || lfun == FuncRequest::unknown) {
2996 // if not found, this unbind item is KeyMap::UserExtraUnbind
2997 // Such an item is not displayed to avoid confusion (what is
2998 // unmatched removed?).
3004 switch(lyxaction.getActionType(action)) {
3005 case LyXAction::Hidden:
3007 case LyXAction::Edit:
3008 newItem = new QTreeWidgetItem(editItem_);
3010 case LyXAction::Math:
3011 newItem = new QTreeWidgetItem(mathItem_);
3013 case LyXAction::Buffer:
3014 newItem = new QTreeWidgetItem(bufferItem_);
3016 case LyXAction::Layout:
3017 newItem = new QTreeWidgetItem(layoutItem_);
3019 case LyXAction::System:
3020 newItem = new QTreeWidgetItem(systemItem_);
3023 // this should not happen
3024 newItem = new QTreeWidgetItem(shortcutsTW);
3026 newItem->setText(0, lfun_name);
3027 newItem->setText(1, shortcut);
3030 // record BindFile representation to recover KeySequence when needed.
3031 newItem->setData(1, Qt::UserRole, toqstr(seq.print(KeySequence::BindFile)));
3032 setItemType(newItem, tag);
3037 void PrefShortcuts::on_shortcutsTW_itemSelectionChanged()
3039 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
3040 removePB->setEnabled(!items.isEmpty() && !items[0]->text(1).isEmpty());
3041 modifyPB->setEnabled(!items.isEmpty());
3042 if (items.isEmpty())
3045 if (itemType(*items[0]) == KeyMap::UserUnbind)
3046 removePB->setText(qt_("Res&tore"));
3048 removePB->setText(qt_("Remo&ve"));
3052 void PrefShortcuts::on_shortcutsTW_itemDoubleClicked()
3058 void PrefShortcuts::modifyShortcut()
3060 QTreeWidgetItem * item = shortcutsTW->currentItem();
3061 if (item->flags() & Qt::ItemIsSelectable) {
3062 shortcut_->lfunLE->setText(item->text(0));
3063 save_lfun_ = item->text(0).trimmed();
3064 shortcut_->shortcutWG->setText(item->text(1));
3066 seq.parse(fromqstr(item->data(1, Qt::UserRole).toString()));
3067 shortcut_->shortcutWG->setKeySequence(seq);
3068 shortcut_->shortcutWG->setFocus();
3074 void PrefShortcuts::unhideEmpty(QString const & lfun, bool select)
3076 // list of items that match lfun
3077 QList<QTreeWidgetItem*> items = shortcutsTW->findItems(lfun,
3078 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 0);
3079 for (auto const & item : items) {
3080 if (isAlwaysHidden(*item)) {
3081 setItemType(item, KeyMap::System);
3083 shortcutsTW->setCurrentItem(item);
3090 void PrefShortcuts::removeShortcut()
3092 // it seems that only one item can be selected, but I am
3093 // removing all selected items anyway.
3094 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
3095 for (auto & item : items) {
3096 string shortcut = fromqstr(item->data(1, Qt::UserRole).toString());
3097 string lfun = fromqstr(item->text(0));
3098 FuncRequest const func = lyxaction.lookupFunc(lfun);
3100 switch (itemType(*item)) {
3101 case KeyMap::System: {
3102 // for system bind, we do not touch the item
3103 // but add an user unbind item
3104 user_unbind_.bind(shortcut, func);
3105 setItemType(item, KeyMap::UserUnbind);
3106 removePB->setText(qt_("Res&tore"));
3109 case KeyMap::UserBind: {
3110 // for user_bind, we remove this bind
3111 QTreeWidgetItem * parent = item->parent();
3112 int itemIdx = parent->indexOfChild(item);
3113 parent->takeChild(itemIdx);
3115 shortcutsTW->scrollToItem(parent->child(itemIdx - 1));
3117 shortcutsTW->scrollToItem(parent);
3118 user_bind_.unbind(shortcut, func);
3119 // If this user binding hid an empty system binding, unhide the
3120 // latter and select it.
3121 unhideEmpty(item->text(0), true);
3124 case KeyMap::UserUnbind: {
3125 // for user_unbind, we remove the unbind, and the item
3126 // become KeyMap::System again.
3128 seq.parse(shortcut);
3129 // Ask the user to replace current binding
3130 if (!validateNewShortcut(func, seq, QString()))
3132 user_unbind_.unbind(shortcut, func);
3133 setItemType(item, KeyMap::System);
3134 removePB->setText(qt_("Remo&ve"));
3137 case KeyMap::UserExtraUnbind: {
3138 // for user unbind that is not in system bind file,
3139 // remove this unbind file
3140 QTreeWidgetItem * parent = item->parent();
3141 parent->takeChild(parent->indexOfChild(item));
3142 user_unbind_.unbind(shortcut, func);
3149 void PrefShortcuts::deactivateShortcuts(QList<QTreeWidgetItem*> const & items)
3151 for (auto item : items) {
3152 string shortcut = fromqstr(item->data(1, Qt::UserRole).toString());
3153 string lfun = fromqstr(item->text(0));
3154 FuncRequest const func = lyxaction.lookupFunc(lfun);
3156 switch (itemType(*item)) {
3157 case KeyMap::System:
3158 // for system bind, we do not touch the item
3159 // but add an user unbind item
3160 user_unbind_.bind(shortcut, func);
3161 setItemType(item, KeyMap::UserUnbind);
3164 case KeyMap::UserBind: {
3165 // for user_bind, we remove this bind
3166 QTreeWidgetItem * parent = item->parent();
3167 int itemIdx = parent->indexOfChild(item);
3168 parent->takeChild(itemIdx);
3169 user_bind_.unbind(shortcut, func);
3170 unhideEmpty(item->text(0), false);
3180 void PrefShortcuts::selectBind()
3182 QString file = form_->browsebind(internalPath(bindFileED->text()));
3183 if (!file.isEmpty()) {
3184 bindFileED->setText(file);
3185 system_bind_ = KeyMap();
3186 system_bind_.read(fromqstr(file));
3187 updateShortcutsTW();
3192 void PrefShortcuts::on_modifyPB_pressed()
3198 void PrefShortcuts::on_newPB_pressed()
3200 shortcut_->lfunLE->clear();
3201 shortcut_->shortcutWG->reset();
3202 save_lfun_ = QString();
3207 void PrefShortcuts::on_removePB_pressed()
3214 void PrefShortcuts::on_searchLE_textEdited()
3216 if (searchLE->text().isEmpty()) {
3217 // show all hidden items
3218 QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Hidden);
3220 (*it)->setHidden(isAlwaysHidden(**it));
3221 // close all categories
3222 for (int i = 0; i < shortcutsTW->topLevelItemCount(); ++i)
3223 shortcutsTW->collapseItem(shortcutsTW->topLevelItem(i));
3226 // search both columns
3227 QList<QTreeWidgetItem *> matched = shortcutsTW->findItems(searchLE->text(),
3228 Qt::MatchFlags(Qt::MatchContains | Qt::MatchRecursive), 0);
3229 matched += shortcutsTW->findItems(searchLE->text(),
3230 Qt::MatchFlags(Qt::MatchContains | Qt::MatchRecursive), 1);
3232 // hide everyone (to avoid searching in matched QList repeatedly
3233 QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Selectable);
3235 (*it++)->setHidden(true);
3236 // show matched items
3237 for (auto & item : matched)
3238 if (!isAlwaysHidden(*item)) {
3239 item->setHidden(false);
3241 item->parent()->setExpanded(true);
3246 docstring makeCmdString(FuncRequest const & f)
3248 docstring actionStr = from_ascii(lyxaction.getActionName(f.action()));
3249 if (!f.argument().empty())
3250 actionStr += " " + f.argument();
3255 FuncRequest PrefShortcuts::currentBinding(KeySequence const & k)
3257 FuncRequest res = user_bind_.getBinding(k);
3258 if (res != FuncRequest::unknown)
3260 res = system_bind_.getBinding(k);
3262 // Check if it is unbound. Note: user_unbind_ can only unbind one
3263 // FuncRequest per key sequence.
3264 if (user_unbind_.getBinding(k) == res)
3265 return FuncRequest::unknown;
3270 bool PrefShortcuts::validateNewShortcut(FuncRequest const & func,
3271 KeySequence const & k,
3272 QString const & lfun_to_modify)
3274 if (func.action() == LFUN_UNKNOWN_ACTION) {
3275 Alert::error(_("Failed to create shortcut"),
3276 _("Unknown or invalid LyX function"));
3280 // It is not currently possible to bind Hidden lfuns such as self-insert. In
3281 // the future, to remove this limitation, see GuiPrefs::insertShortcutItem
3282 // and how it is used in GuiPrefs::shortcutOkPressed.
3283 if (lyxaction.getActionType(func.action()) == LyXAction::Hidden) {
3284 Alert::error(_("Failed to create shortcut"),
3285 _("This LyX function is hidden and cannot be bound."));
3289 if (k.length() == 0) {
3290 Alert::error(_("Failed to create shortcut"),
3291 _("Invalid or empty key sequence"));
3295 FuncRequest oldBinding = currentBinding(k);
3296 if (oldBinding == func)
3297 // nothing to change
3300 // Check whether the key sequence is a prefix for other shortcuts.
3301 if (oldBinding == FuncRequest::prefix) {
3302 docstring const new_action_string = makeCmdString(func);
3303 docstring const text = bformat(_("Shortcut `%1$s' is already a prefix for other commands.\n"
3304 "Are you sure you want to unbind these commands and bind it to %2$s?"),
3305 k.print(KeySequence::ForGui), new_action_string);
3306 int ret = Alert::prompt(_("Redefine shortcut?"),
3307 text, 0, 1, _("&Redefine"), _("&Cancel"));
3310 QString const sequence_text = toqstr(k.print(KeySequence::ForGui));
3311 QList<QTreeWidgetItem*> items = shortcutsTW->findItems(sequence_text,
3312 Qt::MatchFlags(Qt::MatchStartsWith | Qt::MatchRecursive), 1);
3313 deactivateShortcuts(items);
3317 // make sure this key isn't already bound---and, if so, prompt user
3318 // (exclude the lfun the user already wants to modify)
3319 docstring const action_string = makeCmdString(oldBinding);
3320 if (oldBinding.action() != LFUN_UNKNOWN_ACTION
3321 && lfun_to_modify != toqstr(action_string)) {
3322 docstring const new_action_string = makeCmdString(func);
3323 docstring const text = bformat(_("Shortcut `%1$s' is already bound to "
3325 "Are you sure you want to unbind the "
3326 "current shortcut and bind it to %3$s?"),
3327 k.print(KeySequence::ForGui), action_string,
3329 int ret = Alert::prompt(_("Redefine shortcut?"),
3330 text, 0, 1, _("&Redefine"), _("&Cancel"));
3333 QString const sequence_text = toqstr(k.print(KeySequence::ForGui));
3334 QList<QTreeWidgetItem*> items = shortcutsTW->findItems(sequence_text,
3335 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 1);
3336 deactivateShortcuts(items);
3342 void PrefShortcuts::shortcutOkPressed()
3344 QString const new_lfun = shortcut_->lfunLE->text();
3345 FuncRequest const func = lyxaction.lookupFunc(fromqstr(new_lfun));
3346 KeySequence k = shortcut_->shortcutWG->getKeySequence();
3348 // save_lfun_ contains the text of the lfun to modify, if the user clicked
3349 // "modify", or is empty if they clicked "new" (which I do not really like)
3350 if (!validateNewShortcut(func, k, save_lfun_))
3353 if (!save_lfun_.isEmpty()) {
3354 // real modification of the lfun's shortcut,
3355 // so remove the previous one
3356 QList<QTreeWidgetItem*> to_modify = shortcutsTW->selectedItems();
3357 deactivateShortcuts(to_modify);
3360 shortcut_->accept();
3362 QTreeWidgetItem * item = insertShortcutItem(func, k, KeyMap::UserBind);
3364 user_bind_.bind(&k, func);
3365 shortcutsTW->sortItems(0, Qt::AscendingOrder);
3367 item->parent()->setExpanded(true);
3368 shortcutsTW->setCurrentItem(item);
3369 shortcutsTW->scrollToItem(item);
3371 Alert::error(_("Failed to create shortcut"),
3372 _("Can not insert shortcut to the list"));
3378 void PrefShortcuts::shortcutCancelPressed()
3380 shortcut_->shortcutWG->reset();
3384 void PrefShortcuts::shortcutClearPressed()
3386 shortcut_->shortcutWG->reset();
3390 void PrefShortcuts::shortcutRemovePressed()
3392 shortcut_->shortcutWG->removeFromSequence();
3396 /////////////////////////////////////////////////////////////////////
3400 /////////////////////////////////////////////////////////////////////
3402 PrefIdentity::PrefIdentity(GuiPreferences * form)
3403 : PrefModule(QString(), N_("Identity"), form)
3407 connect(nameED, SIGNAL(textChanged(QString)),
3408 this, SIGNAL(changed()));
3409 connect(emailED, SIGNAL(textChanged(QString)),
3410 this, SIGNAL(changed()));
3411 connect(initialsED, SIGNAL(textChanged(QString)),
3412 this, SIGNAL(changed()));
3414 nameED->setValidator(new NoNewLineValidator(nameED));
3415 emailED->setValidator(new NoNewLineValidator(emailED));
3416 initialsED->setValidator(new NoNewLineValidator(initialsED));
3420 void PrefIdentity::applyRC(LyXRC & rc) const
3422 rc.user_name = fromqstr(nameED->text());
3423 rc.user_email = fromqstr(emailED->text());
3424 rc.user_initials = fromqstr(initialsED->text());
3428 void PrefIdentity::updateRC(LyXRC const & rc)
3430 nameED->setText(toqstr(rc.user_name));
3431 emailED->setText(toqstr(rc.user_email));
3432 initialsED->setText(toqstr(rc.user_initials));
3437 /////////////////////////////////////////////////////////////////////
3441 /////////////////////////////////////////////////////////////////////
3443 GuiPreferences::GuiPreferences(GuiView & lv)
3444 : GuiDialog(lv, "prefs", qt_("Preferences"))
3448 QDialog::setModal(false);
3450 connect(buttonBox, SIGNAL(clicked(QAbstractButton *)),
3451 this, SLOT(slotButtonBox(QAbstractButton *)));
3453 addModule(new PrefUserInterface(this));
3454 addModule(new PrefDocHandling(this));
3455 addModule(new PrefEdit(this));
3456 addModule(new PrefShortcuts(this));
3457 PrefScreenFonts * screenfonts = new PrefScreenFonts(this);
3458 connect(this, SIGNAL(prefsApplied(LyXRC const &)),
3459 screenfonts, SLOT(updateScreenFontSizes(LyXRC const &)));
3460 addModule(screenfonts);
3461 addModule(new PrefColors(this));
3462 addModule(new PrefDisplay(this));
3463 addModule(new PrefInput(this));
3464 addModule(new PrefCompletion(this));
3466 addModule(new PrefPaths(this));
3468 addModule(new PrefIdentity(this));
3470 addModule(new PrefLanguage(this));
3471 addModule(new PrefSpellchecker(this));
3473 PrefOutput * output = new PrefOutput(this);
3475 addModule(new PrefLatex(this));
3477 PrefConverters * converters = new PrefConverters(this);
3478 PrefFileformats * formats = new PrefFileformats(this);
3479 connect(formats, SIGNAL(formatsChanged()),
3480 converters, SLOT(updateGui()));
3481 addModule(converters);
3484 prefsPS->setCurrentPanel("User Interface");
3486 bc().setPolicy(ButtonPolicy::PreferencesPolicy);
3487 bc().setOK(buttonBox->button(QDialogButtonBox::Ok));
3488 bc().setApply(buttonBox->button(QDialogButtonBox::Apply));
3489 bc().setCancel(buttonBox->button(QDialogButtonBox::Cancel));
3490 bc().setRestore(buttonBox->button(QDialogButtonBox::Reset));
3492 guilyxfiles_ = new GuiLyXFiles(lv);
3493 connect(guilyxfiles_, SIGNAL(fileSelected(QString)),
3494 this, SLOT(slotFileSelected(QString)));
3498 void GuiPreferences::addModule(PrefModule * module)
3500 LASSERT(module, return);
3501 if (module->category().isEmpty())
3502 prefsPS->addPanel(module, module->title());
3504 prefsPS->addPanel(module, module->title(), module->category());
3505 connect(module, SIGNAL(changed()), this, SLOT(change_adaptor()));
3506 modules_.push_back(module);
3510 void GuiPreferences::change_adaptor()
3516 void GuiPreferences::applyRC(LyXRC & rc) const
3518 size_t end = modules_.size();
3519 for (size_t i = 0; i != end; ++i)
3520 modules_[i]->applyRC(rc);
3524 void GuiPreferences::updateRC(LyXRC const & rc)
3526 size_t const end = modules_.size();
3527 for (size_t i = 0; i != end; ++i)
3528 modules_[i]->updateRC(rc);
3532 void GuiPreferences::applyView()
3538 bool GuiPreferences::initialiseParams(string const &)
3541 formats_ = theFormats();
3542 converters_ = theConverters();
3543 converters_.update(formats_);
3544 movers_ = theMovers();
3548 // Make sure that the bc is in the INITIAL state
3549 if (bc().policy().buttonStatus(ButtonPolicy::RESTORE))
3556 void GuiPreferences::dispatchParams()
3559 rc_.write(ss, true);
3560 dispatch(FuncRequest(LFUN_LYXRC_APPLY, ss.str()));
3561 // issue prefsApplied signal. This will update the
3562 // localized screen font sizes.
3564 // FIXME: these need lfuns
3566 Author const & author =
3567 Author(from_utf8(rc_.user_name), from_utf8(rc_.user_email),
3568 from_utf8(rc_.user_initials));
3569 theBufferList().recordCurrentAuthor(author);
3571 theFormats() = formats_;
3573 theConverters() = converters_;
3574 theConverters().update(formats_);
3575 theConverters().buildGraph();
3576 theBufferList().invalidateConverterCache();
3578 theMovers() = movers_;
3580 for (string const & color : colors_)
3581 dispatch(FuncRequest(LFUN_SET_COLOR, color));
3585 if (!tempSaveCB->isChecked())
3586 dispatch(FuncRequest(LFUN_PREFERENCES_SAVE));
3590 void GuiPreferences::setColor(ColorCode col, QString const & hex)
3592 colors_.push_back(lcolor.getLyXName(col) + ' ' + fromqstr(hex));
3596 void GuiPreferences::slotFileSelected(QString const file)
3602 QString GuiPreferences::browseLibFile(QString const & dir,
3603 QString const & name, QString const & ext)
3607 guilyxfiles_->passParams(fromqstr(dir));
3608 guilyxfiles_->selectItem(name);
3609 guilyxfiles_->exec();
3611 if (frontend::guiApp->platformName() == "cocoa") {
3612 QWidget * dialog_ = asQWidget();
3614 dialog_->activateWindow();
3617 QString const result = uifile_;
3619 // remove the extension if it is the default one
3620 QString noextresult;
3621 if (getExtension(result) == ext)
3622 noextresult = removeExtension(result);
3624 noextresult = result;
3626 // remove the directory, if it is the default one
3627 QString const file = onlyFileName(noextresult);
3628 if (toqstr(libFileSearch(dir, file, ext).absFileName()) == result)
3635 QString GuiPreferences::browsebind(QString const & file)
3637 return browseLibFile("bind", file, "bind");
3641 QString GuiPreferences::browseUI(QString const & file)
3643 return browseLibFile("ui", file, "ui");
3647 QString GuiPreferences::browsekbmap(QString const & file)
3649 return browseLibFile("kbd", file, "kmap");
3653 QString GuiPreferences::browse(QString const & file,
3654 QString const & title)
3656 return browseFile(file, title, QStringList(), true);
3660 } // namespace frontend
3663 #include "moc_GuiPrefs.cpp"