3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
9 * Full author contact details are available in file CREDITS.
16 #include "ColorCache.h"
17 #include "FileDialog.h"
18 #include "GuiApplication.h"
19 #include "GuiFontExample.h"
20 #include "GuiFontLoader.h"
21 #include "GuiKeySymbol.h"
22 #include "GuiLyXFiles.h"
24 #include "qt_helpers.h"
25 #include "Validator.h"
28 #include "BufferList.h"
31 #include "ConverterCache.h"
32 #include "FontEnums.h"
33 #include "FuncRequest.h"
34 #include "KeySequence.h"
36 #include "LyXAction.h"
38 #include "PanelStack.h"
40 #include "SpellChecker.h"
42 #include "support/debug.h"
43 #include "support/FileName.h"
44 #include "support/filetools.h"
45 #include "support/gettext.h"
46 #include "support/lassert.h"
47 #include "support/lstrings.h"
48 #include "support/Messages.h"
49 #include "support/os.h"
50 #include "support/Package.h"
52 #include "frontends/alert.h"
53 #include "frontends/Application.h"
54 #include "frontends/FontLoader.h"
56 #include <QAbstractItemModel>
58 #include <QColorDialog>
59 #include <QFontDatabase>
60 #include <QHeaderView>
62 #include <QMessageBox>
63 #include <QPushButton>
66 #include <QTreeWidget>
67 #include <QTreeWidgetItem>
78 using namespace lyx::support;
79 using namespace lyx::support::os;
84 /////////////////////////////////////////////////////////////////////
88 /////////////////////////////////////////////////////////////////////
90 /** Launch a file dialog and return the chosen file.
91 filename: a suggested filename.
92 title: the title of the dialog.
94 dir1 = (name, dir), dir2 = (name, dir): extra buttons on the dialog.
96 QString browseFile(QString const & filename,
97 QString const & title,
98 QStringList const & filters,
100 QString const & label1 = QString(),
101 QString const & dir1 = QString(),
102 QString const & label2 = QString(),
103 QString const & dir2 = QString(),
104 QString const & fallback_dir = QString())
106 QString lastPath = ".";
107 if (!filename.isEmpty())
108 lastPath = onlyPath(filename);
109 else if(!fallback_dir.isEmpty())
110 lastPath = fallback_dir;
112 FileDialog dlg(title);
113 dlg.setButton1(label1, dir1);
114 dlg.setButton2(label2, dir2);
116 FileDialog::Result result;
119 result = dlg.save(lastPath, filters, onlyFileName(filename));
121 result = dlg.open(lastPath, filters, onlyFileName(filename));
123 return result.second;
127 /** Launch a file dialog and return the chosen directory.
128 pathname: a suggested pathname.
129 title: the title of the dialog.
130 dir1 = (name, dir), dir2 = (name, dir): extra buttons on the dialog.
132 QString browseDir(QString const & pathname,
133 QString const & title,
134 QString const & label1 = QString(),
135 QString const & dir1 = QString(),
136 QString const & label2 = QString(),
137 QString const & dir2 = QString())
139 QString lastPath = ".";
140 if (!pathname.isEmpty())
141 lastPath = onlyPath(pathname);
143 FileDialog dlg(title);
144 dlg.setButton1(label1, dir1);
145 dlg.setButton2(label2, dir2);
147 FileDialog::Result const result =
148 dlg.opendir(lastPath, onlyFileName(pathname));
150 return result.second;
154 } // namespace frontend
157 QString browseRelToParent(QString const & filename, QString const & relpath,
158 QString const & title, QStringList const & filters, bool save,
159 QString const & label1, QString const & dir1,
160 QString const & label2, QString const & dir2)
162 QString const fname = makeAbsPath(filename, relpath);
164 QString const outname =
165 frontend::browseFile(fname, title, filters, save, label1, dir1, label2, dir2);
167 QString const reloutname =
168 toqstr(makeRelPath(qstring_to_ucs4(outname), qstring_to_ucs4(relpath)));
170 if (reloutname.startsWith("../"))
177 QString browseRelToSub(QString const & filename, QString const & relpath,
178 QString const & title, QStringList const & filters, bool save,
179 QString const & label1, QString const & dir1,
180 QString const & label2, QString const & dir2)
182 QString const fname = makeAbsPath(filename, relpath);
184 QString const outname =
185 frontend::browseFile(fname, title, filters, save, label1, dir1, label2, dir2);
187 QString const reloutname =
188 toqstr(makeRelPath(qstring_to_ucs4(outname), qstring_to_ucs4(relpath)));
190 QString testname = reloutname;
191 testname.remove(QRegExp("^(\\.\\./)+"));
193 if (testname.contains("/"))
201 /////////////////////////////////////////////////////////////////////
205 /////////////////////////////////////////////////////////////////////
209 QString const catLookAndFeel = N_("Look & Feel");
210 QString const catEditing = N_("Editing");
211 QString const catLanguage = N_("Language Settings");
212 QString const catOutput = N_("Output");
213 QString const catFiles = N_("File Handling");
215 static void parseFontName(QString const & mangled0,
216 string & name, string & foundry)
218 string mangled = fromqstr(mangled0);
219 size_t const idx = mangled.find('[');
220 if (idx == string::npos || idx == 0) {
224 name = mangled.substr(0, idx - 1);
225 foundry = mangled.substr(idx + 1, mangled.size() - idx - 2);
230 static void setComboxFont(QComboBox * cb, string const & family,
231 string const & foundry)
233 QString fontname = toqstr(family);
234 if (!foundry.empty())
235 fontname += " [" + toqstr(foundry) + ']';
237 for (int i = 0; i != cb->count(); ++i) {
238 if (cb->itemText(i) == fontname) {
239 cb->setCurrentIndex(i);
244 // Try matching without foundry name
246 // We count in reverse in order to prefer the Xft foundry
247 for (int i = cb->count(); --i >= 0;) {
248 string name, fnt_foundry;
249 parseFontName(cb->itemText(i), name, fnt_foundry);
250 if (compare_ascii_no_case(name, family) == 0) {
251 cb->setCurrentIndex(i);
256 // family alone can contain e.g. "Helvetica [Adobe]"
257 string tmpname, tmpfoundry;
258 parseFontName(toqstr(family), tmpname, tmpfoundry);
260 // We count in reverse in order to prefer the Xft foundry
261 for (int i = cb->count(); --i >= 0; ) {
262 string name, fnt_foundry;
263 parseFontName(cb->itemText(i), name, fnt_foundry);
264 if (compare_ascii_no_case(name, fnt_foundry) == 0) {
265 cb->setCurrentIndex(i);
270 // Bleh, default fonts, and the names couldn't be found. Hack
275 QString const font_family = toqstr(family);
276 if (font_family == guiApp->romanFontName()) {
277 font.setStyleHint(QFont::Serif);
278 font.setFamily(font_family);
279 } else if (font_family == guiApp->sansFontName()) {
280 font.setStyleHint(QFont::SansSerif);
281 font.setFamily(font_family);
282 } else if (font_family == guiApp->typewriterFontName()) {
283 font.setStyleHint(QFont::TypeWriter);
284 font.setFamily(font_family);
286 LYXERR0("FAILED to find the default font: '"
287 << foundry << "', '" << family << '\'');
291 QFontInfo info(font);
292 string default_font_name, dummyfoundry;
293 parseFontName(info.family(), default_font_name, dummyfoundry);
294 LYXERR0("Apparent font is " << default_font_name);
296 for (int i = 0; i < cb->count(); ++i) {
297 LYXERR0("Looking at " << cb->itemText(i));
298 if (compare_ascii_no_case(fromqstr(cb->itemText(i)),
299 default_font_name) == 0) {
300 cb->setCurrentIndex(i);
305 LYXERR0("FAILED to find the font: '"
306 << foundry << "', '" << family << '\'');
310 /////////////////////////////////////////////////////////////////////
314 /////////////////////////////////////////////////////////////////////
316 PrefOutput::PrefOutput(GuiPreferences * form)
317 : PrefModule(catOutput, N_("General[[settings]]"), form)
321 dviCB->setValidator(new NoNewLineValidator(dviCB));
322 pdfCB->setValidator(new NoNewLineValidator(pdfCB));
324 connect(plaintextLinelengthSB, SIGNAL(valueChanged(int)),
325 this, SIGNAL(changed()));
326 connect(overwriteCO, SIGNAL(activated(int)),
327 this, SIGNAL(changed()));
328 connect(dviCB, SIGNAL(editTextChanged(QString)),
329 this, SIGNAL(changed()));
330 connect(pdfCB, SIGNAL(editTextChanged(QString)),
331 this, SIGNAL(changed()));
332 connect(printerPaperTypeED, SIGNAL(textChanged(QString)),
333 this, SIGNAL(changed()));
334 connect(printerLandscapeED, SIGNAL(textChanged(QString)),
335 this, SIGNAL(changed()));
336 connect(printerPaperSizeED, SIGNAL(textChanged(QString)),
337 this, SIGNAL(changed()));
339 printerPaperTypeED->setValidator(new NoNewLineValidator(printerPaperTypeED));
340 printerLandscapeED->setValidator(new NoNewLineValidator(printerLandscapeED));
341 printerPaperSizeED->setValidator(new NoNewLineValidator(printerPaperSizeED));
344 dviCB->addItem("xdvi -sourceposition '$$n:\\ $$t' $$o");
345 dviCB->addItem("yap -1 -s \"$$n $$t\" $$o");
346 dviCB->addItem("okular --unique \"$$o#src:$$n $$f\"");
347 dviCB->addItem("synctex view -i $$n:0:$$t -o $$o -x \"evince -i %{page+1} $$o\"");
349 pdfCB->addItem("CMCDDE SUMATRA control [ForwardSearch(\\\"$$o\\\",\\\"$$t\\\",$$n,0,0,1)]");
350 pdfCB->addItem("SumatraPDF -reuse-instance \"$$o\" -forward-search \"$$t\" $$n");
351 pdfCB->addItem("synctex view -i $$n:0:$$t -o $$o -x \"xpdf -raise -remote $$t.tmp $$o %{page+1}\"");
352 pdfCB->addItem("okular --unique \"$$o#src:$$n $$f\"");
353 pdfCB->addItem("qpdfview --unique \"$$o#src:$$f:$$n:0\"");
354 pdfCB->addItem("synctex view -i $$n:0:$$t -o $$o -x \"evince -i %{page+1} $$o\"");
355 pdfCB->addItem("/Applications/Skim.app/Contents/SharedSupport/displayline $$n $$o $$t");
359 void PrefOutput::applyRC(LyXRC & rc) const
361 rc.plaintext_linelen = plaintextLinelengthSB->value();
362 rc.forward_search_dvi = fromqstr(dviCB->currentText());
363 rc.forward_search_pdf = fromqstr(pdfCB->currentText());
365 switch (overwriteCO->currentIndex()) {
367 rc.export_overwrite = NO_FILES;
370 rc.export_overwrite = MAIN_FILE;
373 rc.export_overwrite = ALL_FILES;
377 rc.print_paper_flag = fromqstr(printerPaperTypeED->text());
378 rc.print_landscape_flag = fromqstr(printerLandscapeED->text());
379 rc.print_paper_dimension_flag = fromqstr(printerPaperSizeED->text());
383 void PrefOutput::updateRC(LyXRC const & rc)
385 plaintextLinelengthSB->setValue(rc.plaintext_linelen);
386 dviCB->setEditText(toqstr(rc.forward_search_dvi));
387 pdfCB->setEditText(toqstr(rc.forward_search_pdf));
389 switch (rc.export_overwrite) {
391 overwriteCO->setCurrentIndex(0);
394 overwriteCO->setCurrentIndex(1);
397 overwriteCO->setCurrentIndex(2);
401 printerPaperTypeED->setText(toqstr(rc.print_paper_flag));
402 printerLandscapeED->setText(toqstr(rc.print_landscape_flag));
403 printerPaperSizeED->setText(toqstr(rc.print_paper_dimension_flag));
407 /////////////////////////////////////////////////////////////////////
411 /////////////////////////////////////////////////////////////////////
413 PrefInput::PrefInput(GuiPreferences * form)
414 : PrefModule(catEditing, N_("Keyboard/Mouse"), form)
418 connect(keymapCB, SIGNAL(clicked()),
419 this, SIGNAL(changed()));
420 connect(firstKeymapED, SIGNAL(textChanged(QString)),
421 this, SIGNAL(changed()));
422 connect(secondKeymapED, SIGNAL(textChanged(QString)),
423 this, SIGNAL(changed()));
424 connect(mouseWheelSpeedSB, SIGNAL(valueChanged(double)),
425 this, SIGNAL(changed()));
426 connect(scrollzoomEnableCB, SIGNAL(clicked()),
427 this, SIGNAL(changed()));
428 connect(scrollzoomValueCO, SIGNAL(activated(int)),
429 this, SIGNAL(changed()));
430 connect(dontswapCB, SIGNAL(toggled(bool)),
431 this, SIGNAL(changed()));
432 connect(mmPasteCB, SIGNAL(toggled(bool)),
433 this, SIGNAL(changed()));
435 // reveal checkbox for switching Ctrl and Meta on Mac:
438 #if QT_VERSION > 0x040600
442 dontswapCB->setVisible(swapcb);
446 void PrefInput::applyRC(LyXRC & rc) const
448 // FIXME: can derive CB from the two EDs
449 rc.use_kbmap = keymapCB->isChecked();
450 rc.primary_kbmap = internal_path(fromqstr(firstKeymapED->text()));
451 rc.secondary_kbmap = internal_path(fromqstr(secondKeymapED->text()));
452 rc.mouse_wheel_speed = mouseWheelSpeedSB->value();
453 if (scrollzoomEnableCB->isChecked()) {
454 switch (scrollzoomValueCO->currentIndex()) {
456 rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_CTRL;
459 rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_SHIFT;
462 rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_ALT;
466 rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_OFF;
468 rc.mac_dontswap_ctrl_meta = dontswapCB->isChecked();
469 rc.mouse_middlebutton_paste = mmPasteCB->isChecked();
473 void PrefInput::updateRC(LyXRC const & rc)
475 // FIXME: can derive CB from the two EDs
476 keymapCB->setChecked(rc.use_kbmap);
477 firstKeymapED->setText(toqstr(external_path(rc.primary_kbmap)));
478 secondKeymapED->setText(toqstr(external_path(rc.secondary_kbmap)));
479 mouseWheelSpeedSB->setValue(rc.mouse_wheel_speed);
480 switch (rc.scroll_wheel_zoom) {
481 case LyXRC::SCROLL_WHEEL_ZOOM_OFF:
482 scrollzoomEnableCB->setChecked(false);
484 case LyXRC::SCROLL_WHEEL_ZOOM_CTRL:
485 scrollzoomEnableCB->setChecked(true);
486 scrollzoomValueCO->setCurrentIndex(0);
488 case LyXRC::SCROLL_WHEEL_ZOOM_SHIFT:
489 scrollzoomEnableCB->setChecked(true);
490 scrollzoomValueCO->setCurrentIndex(1);
492 case LyXRC::SCROLL_WHEEL_ZOOM_ALT:
493 scrollzoomEnableCB->setChecked(true);
494 scrollzoomValueCO->setCurrentIndex(2);
497 dontswapCB->setChecked(rc.mac_dontswap_ctrl_meta);
498 mmPasteCB->setChecked(rc.mouse_middlebutton_paste);
502 QString PrefInput::testKeymap(QString const & keymap)
504 return form_->browsekbmap(internalPath(keymap));
508 void PrefInput::on_firstKeymapPB_clicked(bool)
510 QString const file = testKeymap(firstKeymapED->text());
512 firstKeymapED->setText(file);
516 void PrefInput::on_secondKeymapPB_clicked(bool)
518 QString const file = testKeymap(secondKeymapED->text());
520 secondKeymapED->setText(file);
524 void PrefInput::on_keymapCB_toggled(bool keymap)
526 firstKeymapLA->setEnabled(keymap);
527 secondKeymapLA->setEnabled(keymap);
528 firstKeymapED->setEnabled(keymap);
529 secondKeymapED->setEnabled(keymap);
530 firstKeymapPB->setEnabled(keymap);
531 secondKeymapPB->setEnabled(keymap);
535 void PrefInput::on_scrollzoomEnableCB_toggled(bool enabled)
537 scrollzoomValueCO->setEnabled(enabled);
541 /////////////////////////////////////////////////////////////////////
545 /////////////////////////////////////////////////////////////////////
547 PrefCompletion::PrefCompletion(GuiPreferences * form)
548 : PrefModule(catEditing, N_("Input Completion"), form)
552 connect(inlineDelaySB, SIGNAL(valueChanged(double)),
553 this, SIGNAL(changed()));
554 connect(inlineMathCB, SIGNAL(clicked()),
555 this, SIGNAL(changed()));
556 connect(inlineTextCB, SIGNAL(clicked()),
557 this, SIGNAL(changed()));
558 connect(inlineDotsCB, SIGNAL(clicked()),
559 this, SIGNAL(changed()));
560 connect(popupDelaySB, SIGNAL(valueChanged(double)),
561 this, SIGNAL(changed()));
562 connect(popupMathCB, SIGNAL(clicked()),
563 this, SIGNAL(changed()));
564 connect(autocorrectionCB, SIGNAL(clicked()),
565 this, SIGNAL(changed()));
566 connect(popupTextCB, SIGNAL(clicked()),
567 this, SIGNAL(changed()));
568 connect(popupAfterCompleteCB, SIGNAL(clicked()),
569 this, SIGNAL(changed()));
570 connect(cursorTextCB, SIGNAL(clicked()),
571 this, SIGNAL(changed()));
572 connect(minlengthSB, SIGNAL(valueChanged(int)),
573 this, SIGNAL(changed()));
577 void PrefCompletion::on_inlineTextCB_clicked()
583 void PrefCompletion::on_popupTextCB_clicked()
589 void PrefCompletion::enableCB()
591 cursorTextCB->setEnabled(
592 popupTextCB->isChecked() || inlineTextCB->isChecked());
596 void PrefCompletion::applyRC(LyXRC & rc) const
598 rc.completion_inline_delay = inlineDelaySB->value();
599 rc.completion_inline_math = inlineMathCB->isChecked();
600 rc.completion_inline_text = inlineTextCB->isChecked();
601 rc.completion_inline_dots = inlineDotsCB->isChecked() ? 13 : -1;
602 rc.completion_popup_delay = popupDelaySB->value();
603 rc.completion_popup_math = popupMathCB->isChecked();
604 rc.autocorrection_math = autocorrectionCB->isChecked();
605 rc.completion_popup_text = popupTextCB->isChecked();
606 rc.completion_cursor_text = cursorTextCB->isChecked();
607 rc.completion_popup_after_complete =
608 popupAfterCompleteCB->isChecked();
609 rc.completion_minlength = minlengthSB->value();
613 void PrefCompletion::updateRC(LyXRC const & rc)
615 inlineDelaySB->setValue(rc.completion_inline_delay);
616 inlineMathCB->setChecked(rc.completion_inline_math);
617 inlineTextCB->setChecked(rc.completion_inline_text);
618 inlineDotsCB->setChecked(rc.completion_inline_dots != -1);
619 popupDelaySB->setValue(rc.completion_popup_delay);
620 popupMathCB->setChecked(rc.completion_popup_math);
621 autocorrectionCB->setChecked(rc.autocorrection_math);
622 popupTextCB->setChecked(rc.completion_popup_text);
623 cursorTextCB->setChecked(rc.completion_cursor_text);
624 popupAfterCompleteCB->setChecked(rc.completion_popup_after_complete);
626 minlengthSB->setValue(rc.completion_minlength);
631 /////////////////////////////////////////////////////////////////////
635 /////////////////////////////////////////////////////////////////////
637 PrefLatex::PrefLatex(GuiPreferences * form)
638 : PrefModule(catOutput, N_("LaTeX"), form)
642 latexDviPaperED->setValidator(new NoNewLineValidator(latexDviPaperED));
643 latexBibtexED->setValidator(new NoNewLineValidator(latexBibtexED));
644 latexJBibtexED->setValidator(new NoNewLineValidator(latexJBibtexED));
645 latexIndexED->setValidator(new NoNewLineValidator(latexIndexED));
646 latexJIndexED->setValidator(new NoNewLineValidator(latexJIndexED));
647 latexNomenclED->setValidator(new NoNewLineValidator(latexNomenclED));
648 latexChecktexED->setValidator(new NoNewLineValidator(latexChecktexED));
650 connect(latexChecktexED, SIGNAL(textChanged(QString)),
651 this, SIGNAL(changed()));
652 connect(latexBibtexCO, SIGNAL(activated(int)),
653 this, SIGNAL(changed()));
654 connect(latexBibtexED, SIGNAL(textChanged(QString)),
655 this, SIGNAL(changed()));
656 connect(latexJBibtexCO, SIGNAL(activated(int)),
657 this, SIGNAL(changed()));
658 connect(latexJBibtexED, SIGNAL(textChanged(QString)),
659 this, SIGNAL(changed()));
660 connect(latexIndexCO, SIGNAL(activated(int)),
661 this, SIGNAL(changed()));
662 connect(latexIndexED, SIGNAL(textChanged(QString)),
663 this, SIGNAL(changed()));
664 connect(latexJIndexED, SIGNAL(textChanged(QString)),
665 this, SIGNAL(changed()));
666 connect(latexAutoresetCB, SIGNAL(clicked()),
667 this, SIGNAL(changed()));
668 connect(latexDviPaperED, SIGNAL(textChanged(QString)),
669 this, SIGNAL(changed()));
670 connect(latexNomenclED, SIGNAL(textChanged(QString)),
671 this, SIGNAL(changed()));
673 #if defined(__CYGWIN__) || defined(_WIN32)
674 pathCB->setVisible(true);
675 connect(pathCB, SIGNAL(clicked()),
676 this, SIGNAL(changed()));
678 pathCB->setVisible(false);
683 void PrefLatex::on_latexBibtexCO_activated(int n)
685 QString const bibtex = latexBibtexCO->itemData(n).toString();
686 if (bibtex.isEmpty()) {
687 latexBibtexED->clear();
688 latexBibtexOptionsLA->setText(qt_("C&ommand:"));
691 for (LyXRC::CommandSet::const_iterator it = bibtex_alternatives.begin();
692 it != bibtex_alternatives.end(); ++it) {
693 QString const bib = toqstr(*it);
694 int ind = bib.indexOf(" ");
695 QString sel_command = bib.left(ind);
696 QString sel_options = ind < 0 ? QString() : bib.mid(ind + 1);
697 if (bibtex == sel_command) {
699 latexBibtexED->clear();
701 latexBibtexED->setText(sel_options.trimmed());
704 latexBibtexOptionsLA->setText(qt_("&Options:"));
708 void PrefLatex::on_latexJBibtexCO_activated(int n)
710 QString const jbibtex = latexJBibtexCO->itemData(n).toString();
711 if (jbibtex.isEmpty()) {
712 latexJBibtexED->clear();
713 latexJBibtexOptionsLA->setText(qt_("Co&mmand:"));
716 for (LyXRC::CommandSet::const_iterator it = jbibtex_alternatives.begin();
717 it != jbibtex_alternatives.end(); ++it) {
718 QString const bib = toqstr(*it);
719 int ind = bib.indexOf(" ");
720 QString sel_command = bib.left(ind);
721 QString sel_options = ind < 0 ? QString() : bib.mid(ind + 1);
722 if (jbibtex == sel_command) {
724 latexJBibtexED->clear();
726 latexJBibtexED->setText(sel_options.trimmed());
729 latexJBibtexOptionsLA->setText(qt_("Opt&ions:"));
733 void PrefLatex::on_latexIndexCO_activated(int n)
735 QString const index = latexIndexCO->itemData(n).toString();
736 if (index.isEmpty()) {
737 latexIndexED->clear();
738 latexIndexOptionsLA->setText(qt_("Co&mmand:"));
741 for (LyXRC::CommandSet::const_iterator it = index_alternatives.begin();
742 it != index_alternatives.end(); ++it) {
743 QString const idx = toqstr(*it);
744 int ind = idx.indexOf(" ");
745 QString sel_command = idx.left(ind);
746 QString sel_options = ind < 0 ? QString() : idx.mid(ind + 1);
747 if (index == sel_command) {
749 latexIndexED->clear();
751 latexIndexED->setText(sel_options.trimmed());
754 latexIndexOptionsLA->setText(qt_("Op&tions:"));
758 void PrefLatex::applyRC(LyXRC & rc) const
760 // If bibtex is not empty, bibopt contains the options, otherwise
761 // it is a customized bibtex command with options.
762 QString const bibtex = latexBibtexCO->itemData(
763 latexBibtexCO->currentIndex()).toString();
764 QString const bibopt = latexBibtexED->text();
765 if (bibtex.isEmpty())
766 rc.bibtex_command = fromqstr(bibopt);
767 else if (bibopt.isEmpty())
768 rc.bibtex_command = fromqstr(bibtex);
770 rc.bibtex_command = fromqstr(bibtex) + " " + fromqstr(bibopt);
772 // If jbibtex is not empty, jbibopt contains the options, otherwise
773 // it is a customized bibtex command with options.
774 QString const jbibtex = latexJBibtexCO->itemData(
775 latexJBibtexCO->currentIndex()).toString();
776 QString const jbibopt = latexJBibtexED->text();
777 if (jbibtex.isEmpty())
778 rc.jbibtex_command = fromqstr(jbibopt);
779 else if (jbibopt.isEmpty())
780 rc.jbibtex_command = fromqstr(jbibtex);
782 rc.jbibtex_command = fromqstr(jbibtex) + " " + fromqstr(jbibopt);
784 // If index is not empty, idxopt contains the options, otherwise
785 // it is a customized index command with options.
786 QString const index = latexIndexCO->itemData(
787 latexIndexCO->currentIndex()).toString();
788 QString const idxopt = latexIndexED->text();
790 rc.index_command = fromqstr(idxopt);
791 else if (idxopt.isEmpty())
792 rc.index_command = fromqstr(index);
794 rc.index_command = fromqstr(index) + " " + fromqstr(idxopt);
796 rc.chktex_command = fromqstr(latexChecktexED->text());
797 rc.jindex_command = fromqstr(latexJIndexED->text());
798 rc.nomencl_command = fromqstr(latexNomenclED->text());
799 rc.auto_reset_options = latexAutoresetCB->isChecked();
800 rc.view_dvi_paper_option = fromqstr(latexDviPaperED->text());
801 #if defined(__CYGWIN__) || defined(_WIN32)
802 rc.windows_style_tex_paths = pathCB->isChecked();
807 void PrefLatex::updateRC(LyXRC const & rc)
809 latexBibtexCO->clear();
811 latexBibtexCO->addItem(qt_("Automatic"), "automatic");
812 latexBibtexCO->addItem(qt_("Custom"), QString());
813 for (LyXRC::CommandSet::const_iterator it = rc.bibtex_alternatives.begin();
814 it != rc.bibtex_alternatives.end(); ++it) {
815 QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
816 latexBibtexCO->addItem(command, command);
819 bibtex_alternatives = rc.bibtex_alternatives;
821 QString const bib = toqstr(rc.bibtex_command);
822 int ind = bib.indexOf(" ");
823 QString sel_command = bib.left(ind);
824 QString sel_options = ind < 0 ? QString() : bib.mid(ind + 1);
826 int pos = latexBibtexCO->findData(sel_command);
828 latexBibtexCO->setCurrentIndex(pos);
829 latexBibtexED->setText(sel_options.trimmed());
830 latexBibtexOptionsLA->setText(qt_("&Options:"));
832 latexBibtexED->setText(toqstr(rc.bibtex_command));
833 latexBibtexCO->setCurrentIndex(0);
834 latexBibtexOptionsLA->setText(qt_("C&ommand:"));
837 latexJBibtexCO->clear();
839 latexJBibtexCO->addItem(qt_("Automatic"), "automatic");
840 latexJBibtexCO->addItem(qt_("Custom"), QString());
841 for (LyXRC::CommandSet::const_iterator it = rc.jbibtex_alternatives.begin();
842 it != rc.jbibtex_alternatives.end(); ++it) {
843 QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
844 latexJBibtexCO->addItem(command, command);
847 jbibtex_alternatives = rc.jbibtex_alternatives;
849 QString const jbib = toqstr(rc.jbibtex_command);
850 ind = jbib.indexOf(" ");
851 sel_command = jbib.left(ind);
852 sel_options = ind < 0 ? QString() : jbib.mid(ind + 1);
854 pos = latexJBibtexCO->findData(sel_command);
856 latexJBibtexCO->setCurrentIndex(pos);
857 latexJBibtexED->setText(sel_options.trimmed());
858 latexJBibtexOptionsLA->setText(qt_("Opt&ions:"));
860 latexJBibtexED->setText(toqstr(rc.bibtex_command));
861 latexJBibtexCO->setCurrentIndex(0);
862 latexJBibtexOptionsLA->setText(qt_("Co&mmand:"));
865 latexIndexCO->clear();
867 latexIndexCO->addItem(qt_("Custom"), QString());
868 for (LyXRC::CommandSet::const_iterator it = rc.index_alternatives.begin();
869 it != rc.index_alternatives.end(); ++it) {
870 QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
871 latexIndexCO->addItem(command, command);
874 index_alternatives = rc.index_alternatives;
876 QString const idx = toqstr(rc.index_command);
877 ind = idx.indexOf(" ");
878 sel_command = idx.left(ind);
879 sel_options = ind < 0 ? QString() : idx.mid(ind + 1);
881 pos = latexIndexCO->findData(sel_command);
883 latexIndexCO->setCurrentIndex(pos);
884 latexIndexED->setText(sel_options.trimmed());
885 latexIndexOptionsLA->setText(qt_("Op&tions:"));
887 latexIndexED->setText(toqstr(rc.index_command));
888 latexIndexCO->setCurrentIndex(0);
889 latexIndexOptionsLA->setText(qt_("Co&mmand:"));
892 latexChecktexED->setText(toqstr(rc.chktex_command));
893 latexJIndexED->setText(toqstr(rc.jindex_command));
894 latexNomenclED->setText(toqstr(rc.nomencl_command));
895 latexAutoresetCB->setChecked(rc.auto_reset_options);
896 latexDviPaperED->setText(toqstr(rc.view_dvi_paper_option));
897 #if defined(__CYGWIN__) || defined(_WIN32)
898 pathCB->setChecked(rc.windows_style_tex_paths);
903 /////////////////////////////////////////////////////////////////////
907 /////////////////////////////////////////////////////////////////////
909 PrefScreenFonts::PrefScreenFonts(GuiPreferences * form)
910 : PrefModule(catLookAndFeel, N_("Screen Fonts"), form)
914 connect(screenRomanCO, SIGNAL(activated(QString)),
915 this, SLOT(selectRoman(QString)));
916 connect(screenSansCO, SIGNAL(activated(QString)),
917 this, SLOT(selectSans(QString)));
918 connect(screenTypewriterCO, SIGNAL(activated(QString)),
919 this, SLOT(selectTypewriter(QString)));
921 QFontDatabase fontdb;
922 QStringList families(fontdb.families());
923 for (auto const & family : families) {
924 screenRomanCO->addItem(family);
925 screenSansCO->addItem(family);
926 screenTypewriterCO->addItem(family);
928 connect(screenRomanCO, SIGNAL(activated(QString)),
929 this, SIGNAL(changed()));
930 connect(screenSansCO, SIGNAL(activated(QString)),
931 this, SIGNAL(changed()));
932 connect(screenTypewriterCO, SIGNAL(activated(QString)),
933 this, SIGNAL(changed()));
934 connect(screenZoomSB, SIGNAL(valueChanged(int)),
935 this, SIGNAL(changed()));
936 connect(screenTinyED, SIGNAL(textChanged(QString)),
937 this, SIGNAL(changed()));
938 connect(screenSmallestED, SIGNAL(textChanged(QString)),
939 this, SIGNAL(changed()));
940 connect(screenSmallerED, SIGNAL(textChanged(QString)),
941 this, SIGNAL(changed()));
942 connect(screenSmallED, SIGNAL(textChanged(QString)),
943 this, SIGNAL(changed()));
944 connect(screenNormalED, SIGNAL(textChanged(QString)),
945 this, SIGNAL(changed()));
946 connect(screenLargeED, SIGNAL(textChanged(QString)),
947 this, SIGNAL(changed()));
948 connect(screenLargerED, SIGNAL(textChanged(QString)),
949 this, SIGNAL(changed()));
950 connect(screenLargestED, SIGNAL(textChanged(QString)),
951 this, SIGNAL(changed()));
952 connect(screenHugeED, SIGNAL(textChanged(QString)),
953 this, SIGNAL(changed()));
954 connect(screenHugerED, SIGNAL(textChanged(QString)),
955 this, SIGNAL(changed()));
957 screenTinyED->setValidator(new QDoubleValidator(screenTinyED));
958 screenSmallestED->setValidator(new QDoubleValidator(screenSmallestED));
959 screenSmallerED->setValidator(new QDoubleValidator(screenSmallerED));
960 screenSmallED->setValidator(new QDoubleValidator(screenSmallED));
961 screenNormalED->setValidator(new QDoubleValidator(screenNormalED));
962 screenLargeED->setValidator(new QDoubleValidator(screenLargeED));
963 screenLargerED->setValidator(new QDoubleValidator(screenLargerED));
964 screenLargestED->setValidator(new QDoubleValidator(screenLargestED));
965 screenHugeED->setValidator(new QDoubleValidator(screenHugeED));
966 screenHugerED->setValidator(new QDoubleValidator(screenHugerED));
970 void PrefScreenFonts::applyRC(LyXRC & rc) const
972 LyXRC const oldrc = rc;
974 parseFontName(screenRomanCO->currentText(),
975 rc.roman_font_name, rc.roman_font_foundry);
976 parseFontName(screenSansCO->currentText(),
977 rc.sans_font_name, rc.sans_font_foundry);
978 parseFontName(screenTypewriterCO->currentText(),
979 rc.typewriter_font_name, rc.typewriter_font_foundry);
981 rc.defaultZoom = screenZoomSB->value();
982 rc.font_sizes[TINY_SIZE] = widgetToDoubleStr(screenTinyED);
983 rc.font_sizes[SCRIPT_SIZE] = widgetToDoubleStr(screenSmallestED);
984 rc.font_sizes[FOOTNOTE_SIZE] = widgetToDoubleStr(screenSmallerED);
985 rc.font_sizes[SMALL_SIZE] = widgetToDoubleStr(screenSmallED);
986 rc.font_sizes[NORMAL_SIZE] = widgetToDoubleStr(screenNormalED);
987 rc.font_sizes[LARGE_SIZE] = widgetToDoubleStr(screenLargeED);
988 rc.font_sizes[LARGER_SIZE] = widgetToDoubleStr(screenLargerED);
989 rc.font_sizes[LARGEST_SIZE] = widgetToDoubleStr(screenLargestED);
990 rc.font_sizes[HUGE_SIZE] = widgetToDoubleStr(screenHugeED);
991 rc.font_sizes[HUGER_SIZE] = widgetToDoubleStr(screenHugerED);
995 void PrefScreenFonts::updateRC(LyXRC const & rc)
997 setComboxFont(screenRomanCO, rc.roman_font_name,
998 rc.roman_font_foundry);
999 setComboxFont(screenSansCO, rc.sans_font_name,
1000 rc.sans_font_foundry);
1001 setComboxFont(screenTypewriterCO, rc.typewriter_font_name,
1002 rc.typewriter_font_foundry);
1004 selectRoman(screenRomanCO->currentText());
1005 selectSans(screenSansCO->currentText());
1006 selectTypewriter(screenTypewriterCO->currentText());
1008 screenZoomSB->setValue(rc.defaultZoom);
1009 updateScreenFontSizes(rc);
1013 void PrefScreenFonts::updateScreenFontSizes(LyXRC const & rc)
1015 doubleToWidget(screenTinyED, rc.font_sizes[TINY_SIZE]);
1016 doubleToWidget(screenSmallestED, rc.font_sizes[SCRIPT_SIZE]);
1017 doubleToWidget(screenSmallerED, rc.font_sizes[FOOTNOTE_SIZE]);
1018 doubleToWidget(screenSmallED, rc.font_sizes[SMALL_SIZE]);
1019 doubleToWidget(screenNormalED, rc.font_sizes[NORMAL_SIZE]);
1020 doubleToWidget(screenLargeED, rc.font_sizes[LARGE_SIZE]);
1021 doubleToWidget(screenLargerED, rc.font_sizes[LARGER_SIZE]);
1022 doubleToWidget(screenLargestED, rc.font_sizes[LARGEST_SIZE]);
1023 doubleToWidget(screenHugeED, rc.font_sizes[HUGE_SIZE]);
1024 doubleToWidget(screenHugerED, rc.font_sizes[HUGER_SIZE]);
1028 void PrefScreenFonts::selectRoman(const QString & name)
1030 screenRomanFE->set(QFont(name), name);
1034 void PrefScreenFonts::selectSans(const QString & name)
1036 screenSansFE->set(QFont(name), name);
1040 void PrefScreenFonts::selectTypewriter(const QString & name)
1042 screenTypewriterFE->set(QFont(name), name);
1046 /////////////////////////////////////////////////////////////////////
1050 /////////////////////////////////////////////////////////////////////
1053 PrefColors::PrefColors(GuiPreferences * form)
1054 : PrefModule(catLookAndFeel, N_("Colors"), form)
1058 // FIXME: all of this initialization should be put into the controller.
1059 // See http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg113301.html
1060 // for some discussion of why that is not trivial.
1061 QPixmap icon(32, 32);
1062 for (int i = 0; i < Color_ignore; ++i) {
1063 ColorCode lc = static_cast<ColorCode>(i);
1064 if (lc == Color_none
1065 || lc == Color_black
1066 || lc == Color_white
1068 || lc == Color_brown
1070 || lc == Color_darkgray
1072 || lc == Color_green
1073 || lc == Color_lightgray
1075 || lc == Color_magenta
1076 || lc == Color_olive
1077 || lc == Color_orange
1079 || lc == Color_purple
1082 || lc == Color_violet
1083 || lc == Color_yellow
1084 || lc == Color_inherit
1085 || lc == Color_ignore)
1087 lcolors_.push_back(lc);
1089 sort(lcolors_.begin(), lcolors_.end(), ColorSorter);
1090 vector<ColorCode>::const_iterator cit = lcolors_.begin();
1091 vector<ColorCode>::const_iterator const end = lcolors_.end();
1092 for (; cit != end; ++cit) {
1093 (void) new QListWidgetItem(QIcon(icon),
1094 toqstr(lcolor.getGUIName(*cit)), lyxObjectsLW);
1096 curcolors_.resize(lcolors_.size());
1097 newcolors_.resize(lcolors_.size());
1098 // End initialization
1100 connect(colorChangePB, SIGNAL(clicked()),
1101 this, SLOT(changeColor()));
1102 connect(colorResetPB, SIGNAL(clicked()),
1103 this, SLOT(resetColor()));
1104 connect(colorResetAllPB, SIGNAL(clicked()),
1105 this, SLOT(resetAllColor()));
1106 connect(lyxObjectsLW, SIGNAL(itemSelectionChanged()),
1107 this, SLOT(changeLyxObjectsSelection()));
1108 connect(lyxObjectsLW, SIGNAL(itemActivated(QListWidgetItem*)),
1109 this, SLOT(changeColor()));
1110 connect(syscolorsCB, SIGNAL(toggled(bool)),
1111 this, SIGNAL(changed()));
1112 connect(syscolorsCB, SIGNAL(toggled(bool)),
1113 this, SLOT(changeSysColor()));
1117 void PrefColors::applyRC(LyXRC & rc) const
1121 for (unsigned int i = 0; i < lcolors_.size(); ++i)
1122 if (curcolors_[i] != newcolors_[i])
1123 form_->setColor(lcolors_[i], newcolors_[i]);
1124 rc.use_system_colors = syscolorsCB->isChecked();
1126 if (oldrc.use_system_colors != rc.use_system_colors)
1127 guiApp->colorCache().clear();
1131 void PrefColors::updateRC(LyXRC const & rc)
1133 for (size_type i = 0; i < lcolors_.size(); ++i) {
1134 QColor color = QColor(guiApp->colorCache().get(lcolors_[i], false));
1135 QPixmap coloritem(32, 32);
1136 coloritem.fill(color);
1137 lyxObjectsLW->item(int(i))->setIcon(QIcon(coloritem));
1138 newcolors_[i] = curcolors_[i] = color.name();
1140 syscolorsCB->setChecked(rc.use_system_colors);
1141 changeLyxObjectsSelection();
1143 setDisabledResets();
1147 void PrefColors::changeColor()
1149 int const row = lyxObjectsLW->currentRow();
1155 QString const color = newcolors_[size_t(row)];
1156 QColor const c = QColorDialog::getColor(QColor(color), qApp->focusWidget());
1158 if (setColor(row, c, color)) {
1159 setDisabledResets();
1166 void PrefColors::resetColor()
1168 int const row = lyxObjectsLW->currentRow();
1174 QString const color = newcolors_[size_t(row)];
1175 QColor const c = getDefaultColorByRow(row);
1177 if (setColor(row, c, color)) {
1178 setDisabledResets();
1185 void PrefColors::resetAllColor()
1187 bool isChanged = false;
1189 colorResetAllPB->setDisabled(true);
1191 for (int irow = 0, count = lyxObjectsLW->count(); irow < count; ++irow) {
1192 QString const color = newcolors_[size_t(irow)];
1193 QColor const c = getDefaultColorByRow(irow);
1195 if (setColor(irow, c, color))
1200 setDisabledResets();
1207 bool PrefColors::setColor(int const row, QColor const & new_color,
1208 QString const & old_color)
1210 if (new_color.isValid() && new_color.name() != old_color) {
1211 newcolors_[size_t(row)] = new_color.name();
1212 QPixmap coloritem(32, 32);
1213 coloritem.fill(new_color);
1214 lyxObjectsLW->item(row)->setIcon(QIcon(coloritem));
1221 void PrefColors::setDisabledResets()
1223 int const row = lyxObjectsLW->currentRow();
1224 // set disable reset buttons ...
1226 colorResetPB->setDisabled(isDefaultColor(row, newcolors_[size_t(row)]));
1228 colorResetAllPB->setDisabled(true);
1230 // ... in between process qt events to give quicker visual feedback to the user ...
1231 guiApp->processEvents();
1233 // ... set disable Reset All button
1234 for (int irow = 0, count = lyxObjectsLW->count(); irow < count; ++irow) {
1235 if (!isDefaultColor(irow, newcolors_[size_t(irow)])) {
1236 colorResetAllPB->setDisabled(false);
1237 // the break condition might hide performance issues
1238 // if a non-default color is at the top of the list
1245 bool PrefColors::isDefaultColor(int const row, QString const & color)
1247 return color == getDefaultColorByRow(row).name();
1251 QColor PrefColors::getDefaultColorByRow(int const row)
1253 ColorSet const defaultcolor;
1254 return defaultcolor.getX11HexName(lcolors_[size_t(row)]).c_str();
1258 void PrefColors::changeSysColor()
1260 for (int row = 0 ; row < lyxObjectsLW->count() ; ++row) {
1261 // skip colors that are taken from system palette
1262 bool const disable = syscolorsCB->isChecked()
1263 && guiApp->colorCache().isSystem(lcolors_[size_t(row)]);
1265 QListWidgetItem * const item = lyxObjectsLW->item(row);
1266 Qt::ItemFlags const flags = item->flags();
1269 item->setFlags(flags & ~Qt::ItemIsEnabled);
1271 item->setFlags(flags | Qt::ItemIsEnabled);
1276 void PrefColors::changeLyxObjectsSelection()
1278 int currentRow = lyxObjectsLW->currentRow();
1279 colorChangePB->setDisabled(currentRow < 0);
1282 colorResetPB->setDisabled(true);
1284 colorResetPB->setDisabled(
1285 isDefaultColor(currentRow, newcolors_[size_t(currentRow)]));
1289 /////////////////////////////////////////////////////////////////////
1293 /////////////////////////////////////////////////////////////////////
1295 PrefDisplay::PrefDisplay(GuiPreferences * form)
1296 : PrefModule(catLookAndFeel, N_("Display"), form)
1299 connect(displayGraphicsCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1300 connect(instantPreviewCO, SIGNAL(activated(int)), this, SIGNAL(changed()));
1301 connect(previewSizeSB, SIGNAL(valueChanged(double)), this, SIGNAL(changed()));
1302 connect(paragraphMarkerCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1303 connect(ctAdditionsUnderlinedCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1307 void PrefDisplay::on_instantPreviewCO_currentIndexChanged(int index)
1309 previewSizeSB->setEnabled(index != 0);
1313 void PrefDisplay::applyRC(LyXRC & rc) const
1315 switch (instantPreviewCO->currentIndex()) {
1317 rc.preview = LyXRC::PREVIEW_OFF;
1320 rc.preview = LyXRC::PREVIEW_NO_MATH;
1323 rc.preview = LyXRC::PREVIEW_ON;
1327 rc.display_graphics = displayGraphicsCB->isChecked();
1328 rc.preview_scale_factor = previewSizeSB->value();
1329 rc.paragraph_markers = paragraphMarkerCB->isChecked();
1330 rc.ct_additions_underlined = ctAdditionsUnderlinedCB->isChecked();
1332 // FIXME!! The graphics cache no longer has a changeDisplay method.
1334 if (old_value != rc.display_graphics) {
1335 graphics::GCache & gc = graphics::GCache::get();
1342 void PrefDisplay::updateRC(LyXRC const & rc)
1344 switch (rc.preview) {
1345 case LyXRC::PREVIEW_OFF:
1346 instantPreviewCO->setCurrentIndex(0);
1348 case LyXRC::PREVIEW_NO_MATH :
1349 instantPreviewCO->setCurrentIndex(1);
1351 case LyXRC::PREVIEW_ON :
1352 instantPreviewCO->setCurrentIndex(2);
1356 displayGraphicsCB->setChecked(rc.display_graphics);
1357 previewSizeSB->setValue(rc.preview_scale_factor);
1358 paragraphMarkerCB->setChecked(rc.paragraph_markers);
1359 ctAdditionsUnderlinedCB->setChecked(rc.ct_additions_underlined);
1360 previewSizeSB->setEnabled(
1362 && rc.preview != LyXRC::PREVIEW_OFF);
1366 /////////////////////////////////////////////////////////////////////
1370 /////////////////////////////////////////////////////////////////////
1372 PrefPaths::PrefPaths(GuiPreferences * form)
1373 : PrefModule(QString(), N_("Paths"), form)
1377 connect(workingDirPB, SIGNAL(clicked()), this, SLOT(selectWorkingdir()));
1378 connect(workingDirED, SIGNAL(textChanged(QString)),
1379 this, SIGNAL(changed()));
1381 connect(templateDirPB, SIGNAL(clicked()), this, SLOT(selectTemplatedir()));
1382 connect(templateDirED, SIGNAL(textChanged(QString)),
1383 this, SIGNAL(changed()));
1385 connect(exampleDirPB, SIGNAL(clicked()), this, SLOT(selectExampledir()));
1386 connect(exampleDirED, SIGNAL(textChanged(QString)),
1387 this, SIGNAL(changed()));
1389 connect(backupDirPB, SIGNAL(clicked()), this, SLOT(selectBackupdir()));
1390 connect(backupDirED, SIGNAL(textChanged(QString)),
1391 this, SIGNAL(changed()));
1393 connect(lyxserverDirPB, SIGNAL(clicked()), this, SLOT(selectLyxPipe()));
1394 connect(lyxserverDirED, SIGNAL(textChanged(QString)),
1395 this, SIGNAL(changed()));
1397 connect(thesaurusDirPB, SIGNAL(clicked()), this, SLOT(selectThesaurusdir()));
1398 connect(thesaurusDirED, SIGNAL(textChanged(QString)),
1399 this, SIGNAL(changed()));
1401 connect(tempDirPB, SIGNAL(clicked()), this, SLOT(selectTempdir()));
1402 connect(tempDirED, SIGNAL(textChanged(QString)),
1403 this, SIGNAL(changed()));
1405 #if defined(USE_HUNSPELL)
1406 connect(hunspellDirPB, SIGNAL(clicked()), this, SLOT(selectHunspelldir()));
1407 connect(hunspellDirED, SIGNAL(textChanged(QString)),
1408 this, SIGNAL(changed()));
1410 hunspellDirPB->setEnabled(false);
1411 hunspellDirED->setEnabled(false);
1414 connect(pathPrefixED, SIGNAL(textChanged(QString)),
1415 this, SIGNAL(changed()));
1417 connect(texinputsPrefixED, SIGNAL(textChanged(QString)),
1418 this, SIGNAL(changed()));
1420 pathPrefixED->setValidator(new NoNewLineValidator(pathPrefixED));
1421 texinputsPrefixED->setValidator(new NoNewLineValidator(texinputsPrefixED));
1425 void PrefPaths::applyRC(LyXRC & rc) const
1427 rc.document_path = internal_path(fromqstr(workingDirED->text()));
1428 rc.example_path = internal_path(fromqstr(exampleDirED->text()));
1429 rc.template_path = internal_path(fromqstr(templateDirED->text()));
1430 rc.backupdir_path = internal_path(fromqstr(backupDirED->text()));
1431 rc.tempdir_path = internal_path(fromqstr(tempDirED->text()));
1432 rc.thesaurusdir_path = internal_path(fromqstr(thesaurusDirED->text()));
1433 rc.hunspelldir_path = internal_path(fromqstr(hunspellDirED->text()));
1434 rc.path_prefix = internal_path_list(fromqstr(pathPrefixED->text()));
1435 rc.texinputs_prefix = internal_path_list(fromqstr(texinputsPrefixED->text()));
1436 // FIXME: should be a checkbox only
1437 rc.lyxpipes = internal_path(fromqstr(lyxserverDirED->text()));
1441 void PrefPaths::updateRC(LyXRC const & rc)
1443 workingDirED->setText(toqstr(external_path(rc.document_path)));
1444 exampleDirED->setText(toqstr(external_path(rc.example_path)));
1445 templateDirED->setText(toqstr(external_path(rc.template_path)));
1446 backupDirED->setText(toqstr(external_path(rc.backupdir_path)));
1447 tempDirED->setText(toqstr(external_path(rc.tempdir_path)));
1448 thesaurusDirED->setText(toqstr(external_path(rc.thesaurusdir_path)));
1449 hunspellDirED->setText(toqstr(external_path(rc.hunspelldir_path)));
1450 pathPrefixED->setText(toqstr(external_path_list(rc.path_prefix)));
1451 texinputsPrefixED->setText(toqstr(external_path_list(rc.texinputs_prefix)));
1452 // FIXME: should be a checkbox only
1453 lyxserverDirED->setText(toqstr(external_path(rc.lyxpipes)));
1457 void PrefPaths::selectExampledir()
1459 QString file = browseDir(internalPath(exampleDirED->text()),
1460 qt_("Select directory for example files"));
1461 if (!file.isEmpty())
1462 exampleDirED->setText(file);
1466 void PrefPaths::selectTemplatedir()
1468 QString file = browseDir(internalPath(templateDirED->text()),
1469 qt_("Select a document templates directory"));
1470 if (!file.isEmpty())
1471 templateDirED->setText(file);
1475 void PrefPaths::selectTempdir()
1477 QString file = browseDir(internalPath(tempDirED->text()),
1478 qt_("Select a temporary directory"));
1479 if (!file.isEmpty())
1480 tempDirED->setText(file);
1484 void PrefPaths::selectBackupdir()
1486 QString file = browseDir(internalPath(backupDirED->text()),
1487 qt_("Select a backups directory"));
1488 if (!file.isEmpty())
1489 backupDirED->setText(file);
1493 void PrefPaths::selectWorkingdir()
1495 QString file = browseDir(internalPath(workingDirED->text()),
1496 qt_("Select a document directory"));
1497 if (!file.isEmpty())
1498 workingDirED->setText(file);
1502 void PrefPaths::selectThesaurusdir()
1504 QString file = browseDir(internalPath(thesaurusDirED->text()),
1505 qt_("Set the path to the thesaurus dictionaries"));
1506 if (!file.isEmpty())
1507 thesaurusDirED->setText(file);
1511 void PrefPaths::selectHunspelldir()
1513 QString file = browseDir(internalPath(hunspellDirED->text()),
1514 qt_("Set the path to the Hunspell dictionaries"));
1515 if (!file.isEmpty())
1516 hunspellDirED->setText(file);
1520 void PrefPaths::selectLyxPipe()
1522 QString file = form_->browse(internalPath(lyxserverDirED->text()),
1523 qt_("Give a filename for the LyX server pipe"));
1524 if (!file.isEmpty())
1525 lyxserverDirED->setText(file);
1529 /////////////////////////////////////////////////////////////////////
1533 /////////////////////////////////////////////////////////////////////
1535 PrefSpellchecker::PrefSpellchecker(GuiPreferences * form)
1536 : PrefModule(catLanguage, N_("Spellchecker"), form)
1540 // FIXME: this check should test the target platform (darwin)
1541 #if defined(USE_MACOSX_PACKAGING)
1542 spellcheckerCB->addItem(qt_("Native"), QString("native"));
1543 #define CONNECT_APPLESPELL
1545 #undef CONNECT_APPLESPELL
1547 #if defined(USE_ASPELL)
1548 spellcheckerCB->addItem(qt_("Aspell"), QString("aspell"));
1550 #if defined(USE_ENCHANT)
1551 spellcheckerCB->addItem(qt_("Enchant"), QString("enchant"));
1553 #if defined(USE_HUNSPELL)
1554 spellcheckerCB->addItem(qt_("Hunspell"), QString("hunspell"));
1557 #if defined(CONNECT_APPLESPELL) || defined(USE_ASPELL) || defined(USE_ENCHANT) || defined(USE_HUNSPELL)
1558 connect(spellcheckerCB, SIGNAL(currentIndexChanged(int)),
1559 this, SIGNAL(changed()));
1560 connect(altLanguageED, SIGNAL(textChanged(QString)),
1561 this, SIGNAL(changed()));
1562 connect(escapeCharactersED, SIGNAL(textChanged(QString)),
1563 this, SIGNAL(changed()));
1564 connect(compoundWordCB, SIGNAL(clicked()),
1565 this, SIGNAL(changed()));
1566 connect(spellcheckContinuouslyCB, SIGNAL(clicked()),
1567 this, SIGNAL(changed()));
1568 connect(spellcheckNotesCB, SIGNAL(clicked()),
1569 this, SIGNAL(changed()));
1571 altLanguageED->setValidator(new NoNewLineValidator(altLanguageED));
1572 escapeCharactersED->setValidator(new NoNewLineValidator(escapeCharactersED));
1574 spellcheckerCB->setEnabled(false);
1575 altLanguageED->setEnabled(false);
1576 escapeCharactersED->setEnabled(false);
1577 compoundWordCB->setEnabled(false);
1578 spellcheckContinuouslyCB->setEnabled(false);
1579 spellcheckNotesCB->setEnabled(false);
1584 void PrefSpellchecker::applyRC(LyXRC & rc) const
1586 string const speller = fromqstr(spellcheckerCB->
1587 itemData(spellcheckerCB->currentIndex()).toString());
1588 if (!speller.empty())
1589 rc.spellchecker = speller;
1590 rc.spellchecker_alt_lang = fromqstr(altLanguageED->text());
1591 rc.spellchecker_esc_chars = fromqstr(escapeCharactersED->text());
1592 rc.spellchecker_accept_compound = compoundWordCB->isChecked();
1593 rc.spellcheck_continuously = spellcheckContinuouslyCB->isChecked();
1594 rc.spellcheck_notes = spellcheckNotesCB->isChecked();
1598 void PrefSpellchecker::updateRC(LyXRC const & rc)
1600 spellcheckerCB->setCurrentIndex(
1601 spellcheckerCB->findData(toqstr(rc.spellchecker)));
1602 altLanguageED->setText(toqstr(rc.spellchecker_alt_lang));
1603 escapeCharactersED->setText(toqstr(rc.spellchecker_esc_chars));
1604 compoundWordCB->setChecked(rc.spellchecker_accept_compound);
1605 spellcheckContinuouslyCB->setChecked(rc.spellcheck_continuously);
1606 spellcheckNotesCB->setChecked(rc.spellcheck_notes);
1610 void PrefSpellchecker::on_spellcheckerCB_currentIndexChanged(int index)
1612 QString spellchecker = spellcheckerCB->itemData(index).toString();
1614 compoundWordCB->setEnabled(spellchecker == QString("aspell"));
1619 /////////////////////////////////////////////////////////////////////
1623 /////////////////////////////////////////////////////////////////////
1626 PrefConverters::PrefConverters(GuiPreferences * form)
1627 : PrefModule(catFiles, N_("Converters"), form)
1631 connect(converterNewPB, SIGNAL(clicked()),
1632 this, SLOT(updateConverter()));
1633 connect(converterRemovePB, SIGNAL(clicked()),
1634 this, SLOT(removeConverter()));
1635 connect(converterModifyPB, SIGNAL(clicked()),
1636 this, SLOT(updateConverter()));
1637 connect(convertersLW, SIGNAL(currentRowChanged(int)),
1638 this, SLOT(switchConverter()));
1639 connect(converterFromCO, SIGNAL(activated(QString)),
1640 this, SLOT(changeConverter()));
1641 connect(converterToCO, SIGNAL(activated(QString)),
1642 this, SLOT(changeConverter()));
1643 connect(converterED, SIGNAL(textEdited(QString)),
1644 this, SLOT(changeConverter()));
1645 connect(converterFlagED, SIGNAL(textEdited(QString)),
1646 this, SLOT(changeConverter()));
1647 connect(converterNewPB, SIGNAL(clicked()),
1648 this, SIGNAL(changed()));
1649 connect(converterRemovePB, SIGNAL(clicked()),
1650 this, SIGNAL(changed()));
1651 connect(converterModifyPB, SIGNAL(clicked()),
1652 this, SIGNAL(changed()));
1653 connect(maxAgeLE, SIGNAL(textEdited(QString)),
1654 this, SIGNAL(changed()));
1655 connect(needauthForbiddenCB, SIGNAL(toggled(bool)),
1656 this, SIGNAL(changed()));
1658 converterED->setValidator(new NoNewLineValidator(converterED));
1659 converterFlagED->setValidator(new NoNewLineValidator(converterFlagED));
1660 maxAgeLE->setValidator(new QDoubleValidator(0, HUGE_VAL, 6, maxAgeLE));
1661 //converterDefGB->setFocusProxy(convertersLW);
1665 void PrefConverters::applyRC(LyXRC & rc) const
1667 rc.use_converter_cache = cacheCB->isChecked();
1668 rc.use_converter_needauth_forbidden = needauthForbiddenCB->isChecked();
1669 rc.use_converter_needauth = needauthCB->isChecked();
1670 rc.converter_cache_maxage = int(widgetToDouble(maxAgeLE) * 86400.0);
1674 static void setCheckboxBlockSignals(QCheckBox *cb, bool checked) {
1675 cb->blockSignals(true);
1676 cb->setChecked(checked);
1677 cb->blockSignals(false);
1681 void PrefConverters::updateRC(LyXRC const & rc)
1683 cacheCB->setChecked(rc.use_converter_cache);
1684 needauthForbiddenCB->setChecked(rc.use_converter_needauth_forbidden);
1685 setCheckboxBlockSignals(needauthCB, rc.use_converter_needauth);
1687 doubleToWidget(maxAgeLE, (double(rc.converter_cache_maxage) / 86400.0), 'g', 6);
1692 void PrefConverters::updateGui()
1694 QString const pattern("%1 -> %2");
1695 form_->formats().sort();
1696 form_->converters().update(form_->formats());
1697 // save current selection
1700 .arg(converterFromCO->currentText())
1701 .arg(converterToCO->currentText());
1703 converterFromCO->clear();
1704 converterToCO->clear();
1706 for (Format const & f : form_->formats()) {
1707 QString const name = toqstr(translateIfPossible(f.prettyname()));
1708 converterFromCO->addItem(name);
1709 converterToCO->addItem(name);
1712 // currentRowChanged(int) is also triggered when updating the listwidget
1713 // block signals to avoid unnecessary calls to switchConverter()
1714 convertersLW->blockSignals(true);
1715 convertersLW->clear();
1717 for (Converter const & c : form_->converters()) {
1718 QString const name =
1720 .arg(toqstr(translateIfPossible(c.From()->prettyname())))
1721 .arg(toqstr(translateIfPossible(c.To()->prettyname())));
1722 int type = form_->converters().getNumber(c.From()->name(),
1724 new QListWidgetItem(name, convertersLW, type);
1726 convertersLW->sortItems(Qt::AscendingOrder);
1727 convertersLW->blockSignals(false);
1729 // restore selection
1730 if (current != pattern.arg(QString()).arg(QString())) {
1731 QList<QListWidgetItem *> const item =
1732 convertersLW->findItems(current, Qt::MatchExactly);
1733 if (!item.isEmpty())
1734 convertersLW->setCurrentItem(item.at(0));
1737 // select first element if restoring failed
1738 if (convertersLW->currentRow() == -1)
1739 convertersLW->setCurrentRow(0);
1745 void PrefConverters::switchConverter()
1747 int const cnr = convertersLW->currentItem()->type();
1748 Converter const & c(form_->converters().get(cnr));
1749 converterFromCO->setCurrentIndex(form_->formats().getNumber(c.from()));
1750 converterToCO->setCurrentIndex(form_->formats().getNumber(c.to()));
1751 converterED->setText(toqstr(c.command()));
1752 converterFlagED->setText(toqstr(c.flags()));
1758 void PrefConverters::changeConverter()
1764 void PrefConverters::updateButtons()
1766 if (form_->formats().empty())
1768 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1769 Format const & to = form_->formats().get(converterToCO->currentIndex());
1770 int const sel = form_->converters().getNumber(from.name(), to.name());
1771 bool const known = sel >= 0;
1772 bool const valid = !(converterED->text().isEmpty()
1773 || from.name() == to.name());
1778 if (convertersLW->count() > 0) {
1779 int const cnr = convertersLW->currentItem()->type();
1780 Converter const & c = form_->converters().get(cnr);
1781 old_command = c.command();
1782 old_flag = c.flags();
1785 string const new_command = fromqstr(converterED->text());
1786 string const new_flag = fromqstr(converterFlagED->text());
1788 bool modified = (old_command != new_command || old_flag != new_flag);
1790 converterModifyPB->setEnabled(valid && known && modified);
1791 converterNewPB->setEnabled(valid && !known);
1792 converterRemovePB->setEnabled(known);
1794 maxAgeLE->setEnabled(cacheCB->isChecked());
1795 maxAgeLA->setEnabled(cacheCB->isChecked());
1800 // specify unique from/to or it doesn't appear. This is really bad UI
1801 // this is why we can use the same function for both new and modify
1802 void PrefConverters::updateConverter()
1804 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1805 Format const & to = form_->formats().get(converterToCO->currentIndex());
1806 string const flags = fromqstr(converterFlagED->text());
1807 string const command = fromqstr(converterED->text());
1809 Converter const * old =
1810 form_->converters().getConverter(from.name(), to.name());
1811 form_->converters().add(from.name(), to.name(), command, flags);
1814 form_->converters().updateLast(form_->formats());
1818 // Remove all files created by this converter from the cache, since
1819 // the modified converter might create different files.
1820 ConverterCache::get().remove_all(from.name(), to.name());
1824 void PrefConverters::removeConverter()
1826 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1827 Format const & to = form_->formats().get(converterToCO->currentIndex());
1828 form_->converters().erase(from.name(), to.name());
1832 // Remove all files created by this converter from the cache, since
1833 // a possible new converter might create different files.
1834 ConverterCache::get().remove_all(from.name(), to.name());
1838 void PrefConverters::on_cacheCB_stateChanged(int state)
1840 maxAgeLE->setEnabled(state == Qt::Checked);
1841 maxAgeLA->setEnabled(state == Qt::Checked);
1846 void PrefConverters::on_needauthForbiddenCB_toggled(bool checked)
1848 needauthCB->setEnabled(!checked);
1852 void PrefConverters::on_needauthCB_toggled(bool checked)
1859 int ret = frontend::Alert::prompt(
1860 _("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!"),
1861 0, 0, _("&No"), _("&Yes"));
1865 setCheckboxBlockSignals(needauthCB, true);
1869 /////////////////////////////////////////////////////////////////////
1873 /////////////////////////////////////////////////////////////////////
1875 class FormatValidator : public QValidator
1878 FormatValidator(QWidget *, Formats const & f);
1879 void fixup(QString & input) const override;
1880 QValidator::State validate(QString & input, int & pos) const override;
1882 virtual QString toString(Format const & format) const = 0;
1884 Formats const & formats_;
1888 FormatValidator::FormatValidator(QWidget * parent, Formats const & f)
1889 : QValidator(parent), formats_(f)
1894 void FormatValidator::fixup(QString & input) const
1896 Formats::const_iterator cit = formats_.begin();
1897 Formats::const_iterator end = formats_.end();
1898 for (; cit != end; ++cit) {
1899 QString const name = toString(*cit);
1900 if (distance(formats_.begin(), cit) == nr()) {
1908 QValidator::State FormatValidator::validate(QString & input, int & /*pos*/) const
1910 Formats::const_iterator cit = formats_.begin();
1911 Formats::const_iterator end = formats_.end();
1912 bool unknown = true;
1913 for (; unknown && cit != end; ++cit) {
1914 QString const name = toString(*cit);
1915 if (distance(formats_.begin(), cit) != nr())
1916 unknown = name != input;
1919 if (unknown && !input.isEmpty())
1920 return QValidator::Acceptable;
1922 return QValidator::Intermediate;
1926 int FormatValidator::nr() const
1928 QComboBox * p = qobject_cast<QComboBox *>(parent());
1929 return p->itemData(p->currentIndex()).toInt();
1933 /////////////////////////////////////////////////////////////////////
1935 // FormatNameValidator
1937 /////////////////////////////////////////////////////////////////////
1939 class FormatNameValidator : public FormatValidator
1942 FormatNameValidator(QWidget * parent, Formats const & f)
1943 : FormatValidator(parent, f)
1946 QString toString(Format const & format) const override
1948 return toqstr(format.name());
1953 /////////////////////////////////////////////////////////////////////
1955 // FormatPrettynameValidator
1957 /////////////////////////////////////////////////////////////////////
1959 class FormatPrettynameValidator : public FormatValidator
1962 FormatPrettynameValidator(QWidget * parent, Formats const & f)
1963 : FormatValidator(parent, f)
1966 QString toString(Format const & format) const override
1968 return toqstr(translateIfPossible(format.prettyname()));
1973 /////////////////////////////////////////////////////////////////////
1977 /////////////////////////////////////////////////////////////////////
1979 PrefFileformats::PrefFileformats(GuiPreferences * form)
1980 : PrefModule(catFiles, N_("File Formats"), form)
1984 formatED->setValidator(new FormatNameValidator(formatsCB, form_->formats()));
1985 formatsCB->setValidator(new FormatPrettynameValidator(formatsCB, form_->formats()));
1986 extensionsED->setValidator(new NoNewLineValidator(extensionsED));
1987 shortcutED->setValidator(new NoNewLineValidator(shortcutED));
1988 editorED->setValidator(new NoNewLineValidator(editorED));
1989 viewerED->setValidator(new NoNewLineValidator(viewerED));
1990 copierED->setValidator(new NoNewLineValidator(copierED));
1992 connect(documentCB, SIGNAL(clicked()),
1993 this, SLOT(setFlags()));
1994 connect(vectorCB, SIGNAL(clicked()),
1995 this, SLOT(setFlags()));
1996 connect(exportMenuCB, SIGNAL(clicked()),
1997 this, SLOT(setFlags()));
1998 connect(formatsCB->lineEdit(), SIGNAL(editingFinished()),
1999 this, SLOT(updatePrettyname()));
2000 connect(formatsCB->lineEdit(), SIGNAL(textEdited(QString)),
2001 this, SIGNAL(changed()));
2002 connect(defaultFormatCB, SIGNAL(activated(QString)),
2003 this, SIGNAL(changed()));
2004 connect(defaultOTFFormatCB, SIGNAL(activated(QString)),
2005 this, SIGNAL(changed()));
2006 connect(defaultPlatexFormatCB, SIGNAL(activated(QString)),
2007 this, SIGNAL(changed()));
2008 connect(viewerCO, SIGNAL(activated(int)),
2009 this, SIGNAL(changed()));
2010 connect(editorCO, SIGNAL(activated(int)),
2011 this, SIGNAL(changed()));
2017 string const l10n_shortcut(docstring const & prettyname, string const & shortcut)
2019 if (shortcut.empty())
2022 string l10n_format =
2023 to_utf8(_(to_utf8(prettyname) + '|' + shortcut));
2024 return split(l10n_format, '|');
2030 void PrefFileformats::applyRC(LyXRC & rc) const
2032 QString const default_format = defaultFormatCB->itemData(
2033 defaultFormatCB->currentIndex()).toString();
2034 rc.default_view_format = fromqstr(default_format);
2035 QString const default_otf_format = defaultOTFFormatCB->itemData(
2036 defaultOTFFormatCB->currentIndex()).toString();
2037 rc.default_otf_view_format = fromqstr(default_otf_format);
2038 QString const default_platex_format = defaultPlatexFormatCB->itemData(
2039 defaultPlatexFormatCB->currentIndex()).toString();
2040 rc.default_platex_view_format = fromqstr(default_platex_format);
2044 void PrefFileformats::updateRC(LyXRC const & rc)
2046 viewer_alternatives = rc.viewer_alternatives;
2047 editor_alternatives = rc.editor_alternatives;
2048 bool const init = defaultFormatCB->currentText().isEmpty();
2052 defaultFormatCB->findData(toqstr(rc.default_view_format));
2053 defaultFormatCB->setCurrentIndex(pos);
2054 pos = defaultOTFFormatCB->findData(toqstr(rc.default_otf_view_format));
2055 defaultOTFFormatCB->setCurrentIndex(pos);
2056 defaultOTFFormatCB->setCurrentIndex(pos);
2057 pos = defaultPlatexFormatCB->findData(toqstr(rc.default_platex_view_format));
2058 defaultPlatexFormatCB->setCurrentIndex(pos);
2059 defaultPlatexFormatCB->setCurrentIndex(pos);
2064 void PrefFileformats::updateView()
2066 QString const current = formatsCB->currentText();
2067 QString const current_def = defaultFormatCB->currentText();
2068 QString const current_def_otf = defaultOTFFormatCB->currentText();
2069 QString const current_def_platex = defaultPlatexFormatCB->currentText();
2071 // update comboboxes with formats
2072 formatsCB->blockSignals(true);
2073 defaultFormatCB->blockSignals(true);
2074 defaultOTFFormatCB->blockSignals(true);
2075 defaultPlatexFormatCB->blockSignals(true);
2077 defaultFormatCB->clear();
2078 defaultOTFFormatCB->clear();
2079 defaultPlatexFormatCB->clear();
2080 form_->formats().sort();
2081 for (Format const & f : form_->formats()) {
2082 QString const prettyname = toqstr(translateIfPossible(f.prettyname()));
2083 formatsCB->addItem(prettyname,
2084 QVariant(form_->formats().getNumber(f.name())));
2085 if (f.viewer().empty())
2087 if (form_->converters().isReachable("xhtml", f.name())
2088 || form_->converters().isReachable("dviluatex", f.name())
2089 || form_->converters().isReachable("luatex", f.name())
2090 || form_->converters().isReachable("xetex", f.name())) {
2091 defaultFormatCB->addItem(prettyname,
2092 QVariant(toqstr(f.name())));
2093 defaultOTFFormatCB->addItem(prettyname,
2094 QVariant(toqstr(f.name())));
2096 if (form_->converters().isReachable("latex", f.name())
2097 || form_->converters().isReachable("pdflatex", f.name()))
2098 defaultFormatCB->addItem(prettyname,
2099 QVariant(toqstr(f.name())));
2100 if (form_->converters().isReachable("platex", f.name()))
2101 defaultPlatexFormatCB->addItem(prettyname,
2102 QVariant(toqstr(f.name())));
2106 // restore selections
2107 int item = formatsCB->findText(current, Qt::MatchExactly);
2108 formatsCB->setCurrentIndex(item < 0 ? 0 : item);
2109 on_formatsCB_currentIndexChanged(item < 0 ? 0 : item);
2110 item = defaultFormatCB->findText(current_def, Qt::MatchExactly);
2111 defaultFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2112 item = defaultOTFFormatCB->findText(current_def_otf, Qt::MatchExactly);
2113 defaultOTFFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2114 item = defaultPlatexFormatCB->findText(current_def_platex, Qt::MatchExactly);
2115 defaultPlatexFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2116 formatsCB->blockSignals(false);
2117 defaultFormatCB->blockSignals(false);
2118 defaultOTFFormatCB->blockSignals(false);
2119 defaultPlatexFormatCB->blockSignals(false);
2123 void PrefFileformats::on_formatsCB_currentIndexChanged(int i)
2125 if (form_->formats().empty())
2127 int const nr = formatsCB->itemData(i).toInt();
2128 Format const f = form_->formats().get(nr);
2130 formatED->setText(toqstr(f.name()));
2131 copierED->setText(toqstr(form_->movers().command(f.name())));
2132 extensionsED->setText(toqstr(f.extensions()));
2133 mimeED->setText(toqstr(f.mime()));
2134 shortcutED->setText(
2135 toqstr(l10n_shortcut(f.prettyname(), f.shortcut())));
2136 documentCB->setChecked((f.documentFormat()));
2137 vectorCB->setChecked((f.vectorFormat()));
2138 exportMenuCB->setChecked((f.inExportMenu()));
2139 exportMenuCB->setEnabled((f.documentFormat()));
2145 void PrefFileformats::setFlags()
2147 int flags = Format::none;
2148 if (documentCB->isChecked())
2149 flags |= Format::document;
2150 if (vectorCB->isChecked())
2151 flags |= Format::vector;
2152 if (exportMenuCB->isChecked())
2153 flags |= Format::export_menu;
2154 currentFormat().setFlags(flags);
2155 exportMenuCB->setEnabled(documentCB->isChecked());
2160 void PrefFileformats::on_copierED_textEdited(const QString & s)
2162 string const fmt = fromqstr(formatED->text());
2163 form_->movers().set(fmt, fromqstr(s));
2168 void PrefFileformats::on_extensionsED_textEdited(const QString & s)
2170 currentFormat().setExtensions(fromqstr(s));
2175 void PrefFileformats::on_viewerED_textEdited(const QString & s)
2177 currentFormat().setViewer(fromqstr(s));
2182 void PrefFileformats::on_editorED_textEdited(const QString & s)
2184 currentFormat().setEditor(fromqstr(s));
2189 void PrefFileformats::on_mimeED_textEdited(const QString & s)
2191 currentFormat().setMime(fromqstr(s));
2196 void PrefFileformats::on_shortcutED_textEdited(const QString & s)
2198 string const new_shortcut = fromqstr(s);
2199 if (new_shortcut == l10n_shortcut(currentFormat().prettyname(),
2200 currentFormat().shortcut()))
2202 currentFormat().setShortcut(new_shortcut);
2207 void PrefFileformats::on_formatED_editingFinished()
2209 string const newname = fromqstr(formatED->displayText());
2210 string const oldname = currentFormat().name();
2211 if (newname == oldname)
2213 if (form_->converters().formatIsUsed(oldname)) {
2214 Alert::error(_("Format in use"),
2215 _("You cannot change a format's short name "
2216 "if the format is used by a converter. "
2217 "Please remove the converter first."));
2222 currentFormat().setName(newname);
2227 void PrefFileformats::on_formatED_textChanged(const QString &)
2229 QString t = formatED->text();
2231 bool valid = formatED->validator()->validate(t, p) == QValidator::Acceptable;
2232 setValid(formatLA, valid);
2236 void PrefFileformats::on_formatsCB_editTextChanged(const QString &)
2238 QString t = formatsCB->currentText();
2240 bool valid = formatsCB->validator()->validate(t, p) == QValidator::Acceptable;
2241 setValid(formatsLA, valid);
2245 void PrefFileformats::updatePrettyname()
2247 QString const newname = formatsCB->currentText();
2248 if (newname == toqstr(translateIfPossible(currentFormat().prettyname())))
2251 currentFormat().setPrettyname(qstring_to_ucs4(newname));
2259 void updateComboBox(LyXRC::Alternatives const & alts,
2260 string const & fmt, QComboBox * combo)
2262 LyXRC::Alternatives::const_iterator it =
2264 if (it != alts.end()) {
2265 LyXRC::CommandSet const & cmds = it->second;
2266 LyXRC::CommandSet::const_iterator sit =
2268 LyXRC::CommandSet::const_iterator const sen =
2270 for (; sit != sen; ++sit) {
2271 QString const qcmd = toqstr(*sit);
2272 combo->addItem(qcmd, qcmd);
2279 void PrefFileformats::updateViewers()
2281 Format const f = currentFormat();
2282 viewerCO->blockSignals(true);
2284 viewerCO->addItem(qt_("None"), QString());
2285 updateComboBox(viewer_alternatives, f.name(), viewerCO);
2286 viewerCO->addItem(qt_("Custom"), QString("custom viewer"));
2287 viewerCO->blockSignals(false);
2289 int pos = viewerCO->findData(toqstr(f.viewer()));
2292 viewerED->setEnabled(false);
2293 viewerCO->setCurrentIndex(pos);
2295 viewerED->setEnabled(true);
2296 viewerED->setText(toqstr(f.viewer()));
2297 viewerCO->setCurrentIndex(viewerCO->findData(toqstr("custom viewer")));
2302 void PrefFileformats::updateEditors()
2304 Format const f = currentFormat();
2305 editorCO->blockSignals(true);
2307 editorCO->addItem(qt_("None"), QString());
2308 updateComboBox(editor_alternatives, f.name(), editorCO);
2309 editorCO->addItem(qt_("Custom"), QString("custom editor"));
2310 editorCO->blockSignals(false);
2312 int pos = editorCO->findData(toqstr(f.editor()));
2315 editorED->setEnabled(false);
2316 editorCO->setCurrentIndex(pos);
2318 editorED->setEnabled(true);
2319 editorED->setText(toqstr(f.editor()));
2320 editorCO->setCurrentIndex(editorCO->findData(toqstr("custom editor")));
2325 void PrefFileformats::on_viewerCO_currentIndexChanged(int i)
2327 bool const custom = viewerCO->itemData(i).toString() == "custom viewer";
2328 viewerED->setEnabled(custom);
2330 currentFormat().setViewer(fromqstr(viewerCO->itemData(i).toString()));
2334 void PrefFileformats::on_editorCO_currentIndexChanged(int i)
2336 bool const custom = editorCO->itemData(i).toString() == "custom editor";
2337 editorED->setEnabled(custom);
2339 currentFormat().setEditor(fromqstr(editorCO->itemData(i).toString()));
2343 Format & PrefFileformats::currentFormat()
2345 int const i = formatsCB->currentIndex();
2346 int const nr = formatsCB->itemData(i).toInt();
2347 return form_->formats().get(nr);
2351 void PrefFileformats::on_formatNewPB_clicked()
2353 form_->formats().add("", "", docstring(), "", "", "", "", Format::none);
2355 formatsCB->setCurrentIndex(0);
2356 formatsCB->setFocus(Qt::OtherFocusReason);
2360 void PrefFileformats::on_formatRemovePB_clicked()
2362 int const i = formatsCB->currentIndex();
2363 int const nr = formatsCB->itemData(i).toInt();
2364 string const current_text = form_->formats().get(nr).name();
2365 if (form_->converters().formatIsUsed(current_text)) {
2366 Alert::error(_("Format in use"),
2367 _("Cannot remove a Format used by a Converter. "
2368 "Remove the converter first."));
2372 form_->formats().erase(current_text);
2375 on_formatsCB_editTextChanged(formatsCB->currentText());
2380 /////////////////////////////////////////////////////////////////////
2384 /////////////////////////////////////////////////////////////////////
2386 PrefLanguage::PrefLanguage(GuiPreferences * form)
2387 : PrefModule(catLanguage, N_("Language"), form)
2391 connect(visualCursorRB, SIGNAL(clicked()),
2392 this, SIGNAL(changed()));
2393 connect(logicalCursorRB, SIGNAL(clicked()),
2394 this, SIGNAL(changed()));
2395 connect(markForeignCB, SIGNAL(clicked()),
2396 this, SIGNAL(changed()));
2397 connect(respectOSkbdCB, SIGNAL(clicked()),
2398 this, SIGNAL(changed()));
2399 connect(explicitDocLangBeginCB, SIGNAL(clicked()),
2400 this, SIGNAL(changed()));
2401 connect(explicitDocLangEndCB, SIGNAL(clicked()),
2402 this, SIGNAL(changed()));
2403 connect(languagePackageCO, SIGNAL(activated(int)),
2404 this, SIGNAL(changed()));
2405 connect(languagePackageED, SIGNAL(textChanged(QString)),
2406 this, SIGNAL(changed()));
2407 connect(globalCB, SIGNAL(clicked()),
2408 this, SIGNAL(changed()));
2409 connect(startCommandED, SIGNAL(textChanged(QString)),
2410 this, SIGNAL(changed()));
2411 connect(endCommandED, SIGNAL(textChanged(QString)),
2412 this, SIGNAL(changed()));
2413 connect(uiLanguageCO, SIGNAL(activated(int)),
2414 this, SIGNAL(changed()));
2415 connect(defaultDecimalSepED, SIGNAL(textChanged(QString)),
2416 this, SIGNAL(changed()));
2417 connect(defaultDecimalSepCO, SIGNAL(activated(int)),
2418 this, SIGNAL(changed()));
2419 connect(defaultLengthUnitCO, SIGNAL(activated(int)),
2420 this, SIGNAL(changed()));
2422 languagePackageED->setValidator(new NoNewLineValidator(languagePackageED));
2423 startCommandED->setValidator(new NoNewLineValidator(startCommandED));
2424 endCommandED->setValidator(new NoNewLineValidator(endCommandED));
2426 defaultDecimalSepED->setValidator(new QRegExpValidator(QRegExp("\\S"), this));
2427 defaultDecimalSepED->setMaxLength(1);
2429 defaultLengthUnitCO->addItem(lyx::qt_(unit_name_gui[Length::CM]), Length::CM);
2430 defaultLengthUnitCO->addItem(lyx::qt_(unit_name_gui[Length::IN]), Length::IN);
2432 QAbstractItemModel * language_model = guiApp->languageModel();
2433 language_model->sort(0);
2434 uiLanguageCO->blockSignals(true);
2435 uiLanguageCO->clear();
2436 uiLanguageCO->addItem(qt_("Default"), toqstr("auto"));
2437 for (int i = 0; i != language_model->rowCount(); ++i) {
2438 QModelIndex index = language_model->index(i, 0);
2439 // Filter the list based on the available translation and add
2440 // each language code only once
2441 string const name = fromqstr(index.data(Qt::UserRole).toString());
2442 Language const * lang = languages.getLanguage(name);
2445 // never remove the currently selected language
2446 if (name != form->rc().gui_language
2447 && name != lyxrc.gui_language
2448 && (!Messages::available(lang->code())
2449 || !lang->hasGuiSupport()))
2451 uiLanguageCO->addItem(index.data(Qt::DisplayRole).toString(),
2452 index.data(Qt::UserRole).toString());
2454 uiLanguageCO->blockSignals(false);
2458 void PrefLanguage::on_uiLanguageCO_currentIndexChanged(int)
2460 QMessageBox::information(this, qt_("LyX needs to be restarted!"),
2461 qt_("The change of user interface language will be fully "
2462 "effective only after a restart."));
2466 void PrefLanguage::on_languagePackageCO_currentIndexChanged(int i)
2469 languagePackageED->setText(save_langpack_);
2470 else if (!languagePackageED->text().isEmpty()) {
2471 save_langpack_ = languagePackageED->text();
2472 languagePackageED->clear();
2474 languagePackageED->setEnabled(i == 2);
2478 void PrefLanguage::on_defaultDecimalSepCO_currentIndexChanged(int i)
2480 defaultDecimalSepED->setEnabled(i == 1);
2484 void PrefLanguage::applyRC(LyXRC & rc) const
2486 rc.visual_cursor = visualCursorRB->isChecked();
2487 rc.mark_foreign_language = markForeignCB->isChecked();
2488 rc.respect_os_kbd_language = respectOSkbdCB->isChecked();
2489 rc.language_auto_begin = !explicitDocLangBeginCB->isChecked();
2490 rc.language_auto_end = !explicitDocLangEndCB->isChecked();
2491 int const p = languagePackageCO->currentIndex();
2493 rc.language_package_selection = LyXRC::LP_AUTO;
2495 rc.language_package_selection = LyXRC::LP_BABEL;
2497 rc.language_package_selection = LyXRC::LP_CUSTOM;
2499 rc.language_package_selection = LyXRC::LP_NONE;
2500 rc.language_custom_package = fromqstr(languagePackageED->text());
2501 rc.language_global_options = globalCB->isChecked();
2502 rc.language_command_begin = fromqstr(startCommandED->text());
2503 rc.language_command_end = fromqstr(endCommandED->text());
2504 rc.gui_language = fromqstr(
2505 uiLanguageCO->itemData(uiLanguageCO->currentIndex()).toString());
2506 if (defaultDecimalSepCO->currentIndex() == 0)
2507 rc.default_decimal_sep = "locale";
2509 rc.default_decimal_sep = fromqstr(defaultDecimalSepED->text());
2510 rc.default_length_unit = (Length::UNIT) defaultLengthUnitCO->itemData(defaultLengthUnitCO->currentIndex()).toInt();
2514 void PrefLanguage::updateRC(LyXRC const & rc)
2516 if (rc.visual_cursor)
2517 visualCursorRB->setChecked(true);
2519 logicalCursorRB->setChecked(true);
2520 markForeignCB->setChecked(rc.mark_foreign_language);
2521 respectOSkbdCB->setChecked(rc.respect_os_kbd_language);
2522 explicitDocLangBeginCB->setChecked(!rc.language_auto_begin);
2523 explicitDocLangEndCB->setChecked(!rc.language_auto_end);
2524 languagePackageCO->setCurrentIndex(rc.language_package_selection);
2525 if (languagePackageCO->currentIndex() == 2) {
2526 languagePackageED->setText(toqstr(rc.language_custom_package));
2527 languagePackageED->setEnabled(true);
2529 languagePackageED->clear();
2530 save_langpack_ = toqstr(rc.language_custom_package);
2531 languagePackageED->setEnabled(false);
2533 defaultDecimalSepED->setEnabled(defaultDecimalSepCO->currentIndex() == 1);
2534 globalCB->setChecked(rc.language_global_options);
2535 startCommandED->setText(toqstr(rc.language_command_begin));
2536 endCommandED->setText(toqstr(rc.language_command_end));
2537 if (rc.default_decimal_sep == "locale") {
2538 defaultDecimalSepCO->setCurrentIndex(0);
2539 defaultDecimalSepED->clear();
2541 defaultDecimalSepCO->setCurrentIndex(1);
2542 defaultDecimalSepED->setText(toqstr(rc.default_decimal_sep));
2544 int pos = defaultLengthUnitCO->findData(int(rc.default_length_unit));
2545 defaultLengthUnitCO->setCurrentIndex(pos);
2547 pos = uiLanguageCO->findData(toqstr(rc.gui_language));
2548 uiLanguageCO->blockSignals(true);
2549 uiLanguageCO->setCurrentIndex(pos);
2550 uiLanguageCO->blockSignals(false);
2554 /////////////////////////////////////////////////////////////////////
2556 // PrefUserInterface
2558 /////////////////////////////////////////////////////////////////////
2560 PrefUserInterface::PrefUserInterface(GuiPreferences * form)
2561 : PrefModule(catLookAndFeel, N_("User Interface"), form)
2565 connect(uiFilePB, SIGNAL(clicked()),
2566 this, SLOT(selectUi()));
2567 connect(uiFileED, SIGNAL(textChanged(QString)),
2568 this, SIGNAL(changed()));
2569 connect(iconSetCO, SIGNAL(activated(int)),
2570 this, SIGNAL(changed()));
2571 connect(useSystemThemeIconsCB, SIGNAL(clicked()),
2572 this, SIGNAL(changed()));
2573 connect(lastfilesSB, SIGNAL(valueChanged(int)),
2574 this, SIGNAL(changed()));
2575 connect(tooltipCB, SIGNAL(toggled(bool)),
2576 this, SIGNAL(changed()));
2577 lastfilesSB->setMaximum(maxlastfiles);
2579 iconSetCO->addItem(qt_("Default"), QString());
2580 iconSetCO->addItem(qt_("Classic"), "classic");
2581 iconSetCO->addItem(qt_("Oxygen"), "oxygen");
2583 #if (!(defined Q_WS_X11 || defined(QPA_XCB)) || QT_VERSION < 0x040600)
2584 useSystemThemeIconsCB->hide();
2589 void PrefUserInterface::applyRC(LyXRC & rc) const
2591 rc.icon_set = fromqstr(iconSetCO->itemData(
2592 iconSetCO->currentIndex()).toString());
2594 rc.ui_file = internal_path(fromqstr(uiFileED->text()));
2595 rc.use_system_theme_icons = useSystemThemeIconsCB->isChecked();
2596 rc.num_lastfiles = lastfilesSB->value();
2597 rc.use_tooltip = tooltipCB->isChecked();
2601 void PrefUserInterface::updateRC(LyXRC const & rc)
2603 int iconset = iconSetCO->findData(toqstr(rc.icon_set));
2606 iconSetCO->setCurrentIndex(iconset);
2607 useSystemThemeIconsCB->setChecked(rc.use_system_theme_icons);
2608 uiFileED->setText(toqstr(external_path(rc.ui_file)));
2609 lastfilesSB->setValue(rc.num_lastfiles);
2610 tooltipCB->setChecked(rc.use_tooltip);
2614 void PrefUserInterface::selectUi()
2616 QString file = form_->browseUI(internalPath(uiFileED->text()));
2617 if (!file.isEmpty())
2618 uiFileED->setText(file);
2622 /////////////////////////////////////////////////////////////////////
2624 // PrefDocumentHandling
2626 /////////////////////////////////////////////////////////////////////
2628 PrefDocHandling::PrefDocHandling(GuiPreferences * form)
2629 : PrefModule(catLookAndFeel, N_("Document Handling"), form)
2633 connect(autoSaveCB, SIGNAL(toggled(bool)),
2634 autoSaveSB, SLOT(setEnabled(bool)));
2635 connect(autoSaveCB, SIGNAL(toggled(bool)),
2636 TextLabel1, SLOT(setEnabled(bool)));
2637 connect(openDocumentsInTabsCB, SIGNAL(clicked()),
2638 this, SIGNAL(changed()));
2639 connect(singleInstanceCB, SIGNAL(clicked()),
2640 this, SIGNAL(changed()));
2641 connect(singleCloseTabButtonCB, SIGNAL(clicked()),
2642 this, SIGNAL(changed()));
2643 connect(closeLastViewCO, SIGNAL(activated(int)),
2644 this, SIGNAL(changed()));
2645 connect(restoreCursorCB, SIGNAL(clicked()),
2646 this, SIGNAL(changed()));
2647 connect(loadSessionCB, SIGNAL(clicked()),
2648 this, SIGNAL(changed()));
2649 connect(allowGeometrySessionCB, SIGNAL(clicked()),
2650 this, SIGNAL(changed()));
2651 connect(autoSaveSB, SIGNAL(valueChanged(int)),
2652 this, SIGNAL(changed()));
2653 connect(autoSaveCB, SIGNAL(clicked()),
2654 this, SIGNAL(changed()));
2655 connect(backupCB, SIGNAL(clicked()),
2656 this, SIGNAL(changed()));
2657 connect(saveCompressedCB, SIGNAL(clicked()),
2658 this, SIGNAL(changed()));
2659 connect(saveOriginCB, SIGNAL(clicked()),
2660 this, SIGNAL(changed()));
2664 void PrefDocHandling::applyRC(LyXRC & rc) const
2666 rc.use_lastfilepos = restoreCursorCB->isChecked();
2667 rc.load_session = loadSessionCB->isChecked();
2668 rc.allow_geometry_session = allowGeometrySessionCB->isChecked();
2669 rc.autosave = autoSaveCB->isChecked() ? autoSaveSB->value() * 60 : 0;
2670 rc.make_backup = backupCB->isChecked();
2671 rc.save_compressed = saveCompressedCB->isChecked();
2672 rc.save_origin = saveOriginCB->isChecked();
2673 rc.open_buffers_in_tabs = openDocumentsInTabsCB->isChecked();
2674 rc.single_instance = singleInstanceCB->isChecked();
2675 rc.single_close_tab_button = singleCloseTabButtonCB->isChecked();
2677 switch (closeLastViewCO->currentIndex()) {
2679 rc.close_buffer_with_last_view = "yes";
2682 rc.close_buffer_with_last_view = "no";
2685 rc.close_buffer_with_last_view = "ask";
2693 void PrefDocHandling::updateRC(LyXRC const & rc)
2695 restoreCursorCB->setChecked(rc.use_lastfilepos);
2696 loadSessionCB->setChecked(rc.load_session);
2697 allowGeometrySessionCB->setChecked(rc.allow_geometry_session);
2698 // convert to minutes
2699 bool autosave = rc.autosave > 0;
2700 int mins = rc.autosave / 60;
2703 autoSaveSB->setValue(mins);
2704 autoSaveCB->setChecked(autosave);
2705 autoSaveSB->setEnabled(autosave);
2706 backupCB->setChecked(rc.make_backup);
2707 saveCompressedCB->setChecked(rc.save_compressed);
2708 saveOriginCB->setChecked(rc.save_origin);
2709 openDocumentsInTabsCB->setChecked(rc.open_buffers_in_tabs);
2710 singleInstanceCB->setChecked(rc.single_instance && !rc.lyxpipes.empty());
2711 singleInstanceCB->setEnabled(!rc.lyxpipes.empty());
2712 singleCloseTabButtonCB->setChecked(rc.single_close_tab_button);
2713 if (rc.close_buffer_with_last_view == "yes")
2714 closeLastViewCO->setCurrentIndex(0);
2715 else if (rc.close_buffer_with_last_view == "no")
2716 closeLastViewCO->setCurrentIndex(1);
2717 else if (rc.close_buffer_with_last_view == "ask")
2718 closeLastViewCO->setCurrentIndex(2);
2722 void PrefDocHandling::on_clearSessionPB_clicked()
2724 guiApp->clearSession();
2729 /////////////////////////////////////////////////////////////////////
2733 /////////////////////////////////////////////////////////////////////
2735 PrefEdit::PrefEdit(GuiPreferences * form)
2736 : PrefModule(catEditing, N_("Control"), form)
2740 connect(cursorFollowsCB, SIGNAL(clicked()),
2741 this, SIGNAL(changed()));
2742 connect(scrollBelowCB, SIGNAL(clicked()),
2743 this, SIGNAL(changed()));
2744 connect(macLikeCursorMovementCB, SIGNAL(clicked()),
2745 this, SIGNAL(changed()));
2746 connect(copyCTMarkupCB, SIGNAL(clicked()),
2747 this, SIGNAL(changed()));
2748 connect(sortEnvironmentsCB, SIGNAL(clicked()),
2749 this, SIGNAL(changed()));
2750 connect(groupEnvironmentsCB, SIGNAL(clicked()),
2751 this, SIGNAL(changed()));
2752 connect(macroEditStyleCO, SIGNAL(activated(int)),
2753 this, SIGNAL(changed()));
2754 connect(cursorWidthSB, SIGNAL(valueChanged(int)),
2755 this, SIGNAL(changed()));
2756 connect(citationSearchLE, SIGNAL(textChanged(QString)),
2757 this, SIGNAL(changed()));
2758 connect(fullscreenWidthSB, SIGNAL(valueChanged(int)),
2759 this, SIGNAL(changed()));
2760 connect(toggleTabbarCB, SIGNAL(toggled(bool)),
2761 this, SIGNAL(changed()));
2762 connect(toggleMenubarCB, SIGNAL(toggled(bool)),
2763 this, SIGNAL(changed()));
2764 connect(toggleScrollbarCB, SIGNAL(toggled(bool)),
2765 this, SIGNAL(changed()));
2766 connect(toggleStatusbarCB, SIGNAL(toggled(bool)),
2767 this, SIGNAL(changed()));
2768 connect(toggleToolbarsCB, SIGNAL(toggled(bool)),
2769 this, SIGNAL(changed()));
2773 void PrefEdit::on_fullscreenLimitCB_toggled(bool const state)
2775 fullscreenWidthSB->setEnabled(state);
2776 fullscreenWidthLA->setEnabled(state);
2781 void PrefEdit::on_citationSearchCB_toggled(bool const state)
2783 citationSearchLE->setEnabled(state);
2784 citationSearchLA->setEnabled(state);
2789 void PrefEdit::applyRC(LyXRC & rc) const
2791 rc.cursor_follows_scrollbar = cursorFollowsCB->isChecked();
2792 rc.scroll_below_document = scrollBelowCB->isChecked();
2793 rc.mac_like_cursor_movement = macLikeCursorMovementCB->isChecked();
2794 rc.ct_markup_copied = copyCTMarkupCB->isChecked();
2795 rc.sort_layouts = sortEnvironmentsCB->isChecked();
2796 rc.group_layouts = groupEnvironmentsCB->isChecked();
2797 switch (macroEditStyleCO->currentIndex()) {
2798 case 0: rc.macro_edit_style = LyXRC::MACRO_EDIT_INLINE_BOX; break;
2799 case 1: rc.macro_edit_style = LyXRC::MACRO_EDIT_INLINE; break;
2800 case 2: rc.macro_edit_style = LyXRC::MACRO_EDIT_LIST; break;
2802 rc.cursor_width = cursorWidthSB->value();
2803 rc.citation_search = citationSearchCB->isChecked();
2804 rc.citation_search_pattern = fromqstr(citationSearchLE->text());
2805 rc.full_screen_toolbars = toggleToolbarsCB->isChecked();
2806 rc.full_screen_scrollbar = toggleScrollbarCB->isChecked();
2807 rc.full_screen_statusbar = toggleStatusbarCB->isChecked();
2808 rc.full_screen_tabbar = toggleTabbarCB->isChecked();
2809 rc.full_screen_menubar = toggleMenubarCB->isChecked();
2810 rc.full_screen_width = fullscreenWidthSB->value();
2811 rc.full_screen_limit = fullscreenLimitCB->isChecked();
2815 void PrefEdit::updateRC(LyXRC const & rc)
2817 cursorFollowsCB->setChecked(rc.cursor_follows_scrollbar);
2818 scrollBelowCB->setChecked(rc.scroll_below_document);
2819 macLikeCursorMovementCB->setChecked(rc.mac_like_cursor_movement);
2820 copyCTMarkupCB->setChecked(rc.ct_markup_copied);
2821 sortEnvironmentsCB->setChecked(rc.sort_layouts);
2822 groupEnvironmentsCB->setChecked(rc.group_layouts);
2823 macroEditStyleCO->setCurrentIndex(rc.macro_edit_style);
2824 cursorWidthSB->setValue(rc.cursor_width);
2825 citationSearchCB->setChecked(rc.citation_search);
2826 citationSearchLE->setText(toqstr(rc.citation_search_pattern));
2827 citationSearchLE->setEnabled(rc.citation_search);
2828 citationSearchLA->setEnabled(rc.citation_search);
2829 toggleScrollbarCB->setChecked(rc.full_screen_scrollbar);
2830 toggleStatusbarCB->setChecked(rc.full_screen_statusbar);
2831 toggleToolbarsCB->setChecked(rc.full_screen_toolbars);
2832 toggleTabbarCB->setChecked(rc.full_screen_tabbar);
2833 toggleMenubarCB->setChecked(rc.full_screen_menubar);
2834 fullscreenWidthSB->setValue(rc.full_screen_width);
2835 fullscreenLimitCB->setChecked(rc.full_screen_limit);
2836 fullscreenWidthSB->setEnabled(rc.full_screen_limit);
2837 fullscreenWidthLA->setEnabled(rc.full_screen_limit);
2841 /////////////////////////////////////////////////////////////////////
2845 /////////////////////////////////////////////////////////////////////
2848 GuiShortcutDialog::GuiShortcutDialog(QWidget * parent) : QDialog(parent)
2850 Ui::shortcutUi::setupUi(this);
2851 QDialog::setModal(true);
2852 lfunLE->setValidator(new NoNewLineValidator(lfunLE));
2856 PrefShortcuts::PrefShortcuts(GuiPreferences * form)
2857 : PrefModule(catEditing, N_("Shortcuts"), form),
2858 editItem_(nullptr), mathItem_(nullptr), bufferItem_(nullptr), layoutItem_(nullptr),
2859 systemItem_(nullptr)
2863 shortcutsTW->setColumnCount(2);
2864 shortcutsTW->headerItem()->setText(0, qt_("Function"));
2865 shortcutsTW->headerItem()->setText(1, qt_("Shortcut"));
2866 shortcutsTW->setSortingEnabled(true);
2867 // Multi-selection can be annoying.
2868 // shortcutsTW->setSelectionMode(QAbstractItemView::MultiSelection);
2870 connect(bindFilePB, SIGNAL(clicked()),
2871 this, SLOT(selectBind()));
2872 connect(bindFileED, SIGNAL(textChanged(QString)),
2873 this, SIGNAL(changed()));
2875 shortcut_ = new GuiShortcutDialog(this);
2876 shortcut_bc_.setPolicy(ButtonPolicy::OkCancelPolicy);
2877 shortcut_bc_.setOK(shortcut_->buttonBox->button(QDialogButtonBox::Ok));
2878 shortcut_bc_.setCancel(shortcut_->buttonBox->button(QDialogButtonBox::Cancel));
2880 connect(shortcut_->buttonBox, SIGNAL(accepted()),
2881 this, SIGNAL(changed()));
2882 connect(shortcut_->buttonBox, SIGNAL(rejected()),
2883 shortcut_, SLOT(reject()));
2884 connect(shortcut_->clearPB, SIGNAL(clicked()),
2885 this, SLOT(shortcutClearPressed()));
2886 connect(shortcut_->removePB, SIGNAL(clicked()),
2887 this, SLOT(shortcutRemovePressed()));
2888 connect(shortcut_->buttonBox, SIGNAL(accepted()),
2889 this, SLOT(shortcutOkPressed()));
2890 connect(shortcut_->buttonBox, SIGNAL(rejected()),
2891 this, SLOT(shortcutCancelPressed()));
2895 void PrefShortcuts::applyRC(LyXRC & rc) const
2897 rc.bind_file = internal_path(fromqstr(bindFileED->text()));
2898 // write user_bind and user_unbind to .lyx/bind/user.bind
2899 FileName bind_dir(addPath(package().user_support().absFileName(), "bind"));
2900 if (!bind_dir.exists() && !bind_dir.createDirectory(0777)) {
2901 lyxerr << "LyX could not create the user bind directory '"
2902 << bind_dir << "'. All user-defined key bindings will be lost." << endl;
2905 if (!bind_dir.isDirWritable()) {
2906 lyxerr << "LyX could not write to the user bind directory '"
2907 << bind_dir << "'. All user-defined key bindings will be lost." << endl;
2910 FileName user_bind_file(bind_dir.absFileName() + "/user.bind");
2911 user_unbind_.write(user_bind_file.toFilesystemEncoding(), false, true);
2912 user_bind_.write(user_bind_file.toFilesystemEncoding(), true, false);
2913 // immediately apply the keybindings. Why this is not done before?
2914 // The good thing is that the menus are updated automatically.
2915 theTopLevelKeymap().clear();
2916 theTopLevelKeymap().read("site");
2917 theTopLevelKeymap().read(rc.bind_file, nullptr, KeyMap::Fallback);
2918 theTopLevelKeymap().read("user", nullptr, KeyMap::MissingOK);
2922 void PrefShortcuts::updateRC(LyXRC const & rc)
2924 bindFileED->setText(toqstr(external_path(rc.bind_file)));
2926 system_bind_.clear();
2928 user_unbind_.clear();
2929 system_bind_.read("site");
2930 system_bind_.read(rc.bind_file);
2931 // \unbind in user.bind is added to user_unbind_
2932 user_bind_.read("user", &user_unbind_, KeyMap::MissingOK);
2933 updateShortcutsTW();
2937 void PrefShortcuts::updateShortcutsTW()
2939 shortcutsTW->clear();
2941 editItem_ = new QTreeWidgetItem(shortcutsTW);
2942 editItem_->setText(0, qt_("Cursor, Mouse and Editing Functions"));
2943 editItem_->setFlags(editItem_->flags() & ~Qt::ItemIsSelectable);
2945 mathItem_ = new QTreeWidgetItem(shortcutsTW);
2946 mathItem_->setText(0, qt_("Mathematical Symbols"));
2947 mathItem_->setFlags(mathItem_->flags() & ~Qt::ItemIsSelectable);
2949 bufferItem_ = new QTreeWidgetItem(shortcutsTW);
2950 bufferItem_->setText(0, qt_("Document and Window"));
2951 bufferItem_->setFlags(bufferItem_->flags() & ~Qt::ItemIsSelectable);
2953 layoutItem_ = new QTreeWidgetItem(shortcutsTW);
2954 layoutItem_->setText(0, qt_("Font, Layouts and Textclasses"));
2955 layoutItem_->setFlags(layoutItem_->flags() & ~Qt::ItemIsSelectable);
2957 systemItem_ = new QTreeWidgetItem(shortcutsTW);
2958 systemItem_->setText(0, qt_("System and Miscellaneous"));
2959 systemItem_->setFlags(systemItem_->flags() & ~Qt::ItemIsSelectable);
2961 // listBindings(unbound=true) lists all bound and unbound lfuns
2962 // Items in this list is tagged by its source.
2963 KeyMap::BindingList bindinglist = system_bind_.listBindings(true,
2965 KeyMap::BindingList user_bindinglist = user_bind_.listBindings(false,
2967 KeyMap::BindingList user_unbindinglist = user_unbind_.listBindings(false,
2968 KeyMap::UserUnbind);
2969 bindinglist.insert(bindinglist.end(), user_bindinglist.begin(),
2970 user_bindinglist.end());
2971 bindinglist.insert(bindinglist.end(), user_unbindinglist.begin(),
2972 user_unbindinglist.end());
2974 KeyMap::BindingList::const_iterator it = bindinglist.begin();
2975 KeyMap::BindingList::const_iterator it_end = bindinglist.end();
2976 for (; it != it_end; ++it)
2977 insertShortcutItem(it->request, it->sequence, it->tag);
2979 shortcutsTW->sortItems(0, Qt::AscendingOrder);
2980 on_shortcutsTW_itemSelectionChanged();
2981 on_searchLE_textEdited();
2982 shortcutsTW->resizeColumnToContents(0);
2987 KeyMap::ItemType PrefShortcuts::itemType(QTreeWidgetItem & item)
2989 return static_cast<KeyMap::ItemType>(item.data(0, Qt::UserRole).toInt());
2994 bool PrefShortcuts::isAlwaysHidden(QTreeWidgetItem & item)
2996 // Hide rebound system settings that are empty
2997 return itemType(item) == KeyMap::UserUnbind && item.text(1).isEmpty();
3001 void PrefShortcuts::setItemType(QTreeWidgetItem * item, KeyMap::ItemType tag)
3003 item->setData(0, Qt::UserRole, QVariant(tag));
3007 case KeyMap::System:
3009 case KeyMap::UserBind:
3012 case KeyMap::UserUnbind:
3013 font.setStrikeOut(true);
3015 // this item is not displayed now.
3016 case KeyMap::UserExtraUnbind:
3017 font.setStrikeOut(true);
3020 item->setHidden(isAlwaysHidden(*item));
3021 item->setFont(1, font);
3025 QTreeWidgetItem * PrefShortcuts::insertShortcutItem(FuncRequest const & lfun,
3026 KeySequence const & seq, KeyMap::ItemType tag)
3028 FuncCode const action = lfun.action();
3029 string const action_name = lyxaction.getActionName(action);
3030 QString const lfun_name = toqstr(from_utf8(action_name)
3031 + ' ' + lfun.argument());
3032 QString const shortcut = toqstr(seq.print(KeySequence::ForGui));
3034 QTreeWidgetItem * newItem = nullptr;
3035 // for unbind items, try to find an existing item in the system bind list
3036 if (tag == KeyMap::UserUnbind) {
3037 QList<QTreeWidgetItem*> const items = shortcutsTW->findItems(lfun_name,
3038 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 0);
3039 for (auto const & item : items) {
3040 if (item->text(1) == shortcut) {
3045 // if not found, this unbind item is KeyMap::UserExtraUnbind
3046 // Such an item is not displayed to avoid confusion (what is
3047 // unmatched removed?).
3053 switch(lyxaction.getActionType(action)) {
3054 case LyXAction::Hidden:
3056 case LyXAction::Edit:
3057 newItem = new QTreeWidgetItem(editItem_);
3059 case LyXAction::Math:
3060 newItem = new QTreeWidgetItem(mathItem_);
3062 case LyXAction::Buffer:
3063 newItem = new QTreeWidgetItem(bufferItem_);
3065 case LyXAction::Layout:
3066 newItem = new QTreeWidgetItem(layoutItem_);
3068 case LyXAction::System:
3069 newItem = new QTreeWidgetItem(systemItem_);
3072 // this should not happen
3073 newItem = new QTreeWidgetItem(shortcutsTW);
3077 newItem->setText(0, lfun_name);
3078 newItem->setText(1, shortcut);
3079 // record BindFile representation to recover KeySequence when needed.
3080 newItem->setData(1, Qt::UserRole, toqstr(seq.print(KeySequence::BindFile)));
3081 setItemType(newItem, tag);
3086 void PrefShortcuts::on_shortcutsTW_itemSelectionChanged()
3088 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
3089 removePB->setEnabled(!items.isEmpty() && !items[0]->text(1).isEmpty());
3090 modifyPB->setEnabled(!items.isEmpty());
3091 if (items.isEmpty())
3094 if (itemType(*items[0]) == KeyMap::UserUnbind)
3095 removePB->setText(qt_("Res&tore"));
3097 removePB->setText(qt_("Remo&ve"));
3101 void PrefShortcuts::on_shortcutsTW_itemDoubleClicked()
3107 void PrefShortcuts::modifyShortcut()
3109 QTreeWidgetItem * item = shortcutsTW->currentItem();
3110 if (item->flags() & Qt::ItemIsSelectable) {
3111 shortcut_->lfunLE->setText(item->text(0));
3112 save_lfun_ = item->text(0).trimmed();
3113 shortcut_->shortcutWG->setText(item->text(1));
3115 seq.parse(fromqstr(item->data(1, Qt::UserRole).toString()));
3116 shortcut_->shortcutWG->setKeySequence(seq);
3117 shortcut_->shortcutWG->setFocus();
3123 void PrefShortcuts::unhideEmpty(QString const & lfun, bool select)
3125 // list of items that match lfun
3126 QList<QTreeWidgetItem*> items = shortcutsTW->findItems(lfun,
3127 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 0);
3128 for (auto const & item : items) {
3129 if (isAlwaysHidden(*item)) {
3130 setItemType(item, KeyMap::System);
3132 shortcutsTW->setCurrentItem(item);
3139 void PrefShortcuts::removeShortcut()
3141 // it seems that only one item can be selected, but I am
3142 // removing all selected items anyway.
3143 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
3144 for (auto & item : items) {
3145 string shortcut = fromqstr(item->data(1, Qt::UserRole).toString());
3146 string lfun = fromqstr(item->text(0));
3147 FuncRequest const func = lyxaction.lookupFunc(lfun);
3149 switch (itemType(*item)) {
3150 case KeyMap::System: {
3151 // for system bind, we do not touch the item
3152 // but add an user unbind item
3153 user_unbind_.bind(shortcut, func);
3154 setItemType(item, KeyMap::UserUnbind);
3155 removePB->setText(qt_("Res&tore"));
3158 case KeyMap::UserBind: {
3159 // for user_bind, we remove this bind
3160 QTreeWidgetItem * parent = item->parent();
3161 int itemIdx = parent->indexOfChild(item);
3162 parent->takeChild(itemIdx);
3164 shortcutsTW->scrollToItem(parent->child(itemIdx - 1));
3166 shortcutsTW->scrollToItem(parent);
3167 user_bind_.unbind(shortcut, func);
3168 // If this user binding hid an empty system binding, unhide the
3169 // latter and select it.
3170 unhideEmpty(item->text(0), true);
3173 case KeyMap::UserUnbind: {
3174 // for user_unbind, we remove the unbind, and the item
3175 // become KeyMap::System again.
3177 seq.parse(shortcut);
3178 // Ask the user to replace current binding
3179 if (!validateNewShortcut(func, seq, QString()))
3181 user_unbind_.unbind(shortcut, func);
3182 setItemType(item, KeyMap::System);
3183 removePB->setText(qt_("Remo&ve"));
3186 case KeyMap::UserExtraUnbind: {
3187 // for user unbind that is not in system bind file,
3188 // remove this unbind file
3189 QTreeWidgetItem * parent = item->parent();
3190 parent->takeChild(parent->indexOfChild(item));
3191 user_unbind_.unbind(shortcut, func);
3198 void PrefShortcuts::deactivateShortcuts(QList<QTreeWidgetItem*> const & items)
3200 for (auto item : items) {
3201 string shortcut = fromqstr(item->data(1, Qt::UserRole).toString());
3202 string lfun = fromqstr(item->text(0));
3203 FuncRequest const func = lyxaction.lookupFunc(lfun);
3205 switch (itemType(*item)) {
3206 case KeyMap::System:
3207 // for system bind, we do not touch the item
3208 // but add an user unbind item
3209 user_unbind_.bind(shortcut, func);
3210 setItemType(item, KeyMap::UserUnbind);
3213 case KeyMap::UserBind: {
3214 // for user_bind, we remove this bind
3215 QTreeWidgetItem * parent = item->parent();
3216 int itemIdx = parent->indexOfChild(item);
3217 parent->takeChild(itemIdx);
3218 user_bind_.unbind(shortcut, func);
3219 unhideEmpty(item->text(0), false);
3229 void PrefShortcuts::selectBind()
3231 QString file = form_->browsebind(internalPath(bindFileED->text()));
3232 if (!file.isEmpty()) {
3233 bindFileED->setText(file);
3234 system_bind_ = KeyMap();
3235 system_bind_.read(fromqstr(file));
3236 updateShortcutsTW();
3241 void PrefShortcuts::on_modifyPB_pressed()
3247 void PrefShortcuts::on_newPB_pressed()
3249 shortcut_->lfunLE->clear();
3250 shortcut_->shortcutWG->reset();
3251 save_lfun_ = QString();
3256 void PrefShortcuts::on_removePB_pressed()
3263 void PrefShortcuts::on_searchLE_textEdited()
3265 if (searchLE->text().isEmpty()) {
3266 // show all hidden items
3267 QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Hidden);
3269 (*it)->setHidden(isAlwaysHidden(**it));
3270 // close all categories
3271 for (int i = 0; i < shortcutsTW->topLevelItemCount(); ++i)
3272 shortcutsTW->collapseItem(shortcutsTW->topLevelItem(i));
3275 // search both columns
3276 QList<QTreeWidgetItem *> matched = shortcutsTW->findItems(searchLE->text(),
3277 Qt::MatchFlags(Qt::MatchContains | Qt::MatchRecursive), 0);
3278 matched += shortcutsTW->findItems(searchLE->text(),
3279 Qt::MatchFlags(Qt::MatchContains | Qt::MatchRecursive), 1);
3281 // hide everyone (to avoid searching in matched QList repeatedly
3282 QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Selectable);
3284 (*it++)->setHidden(true);
3285 // show matched items
3286 for (auto & item : matched)
3287 if (!isAlwaysHidden(*item)) {
3288 item->setHidden(false);
3290 item->parent()->setExpanded(true);
3295 docstring makeCmdString(FuncRequest const & f)
3297 docstring actionStr = from_ascii(lyxaction.getActionName(f.action()));
3298 if (!f.argument().empty())
3299 actionStr += " " + f.argument();
3304 FuncRequest PrefShortcuts::currentBinding(KeySequence const & k)
3306 FuncRequest res = user_bind_.getBinding(k);
3307 if (res.action() != LFUN_UNKNOWN_ACTION)
3309 res = system_bind_.getBinding(k);
3310 // Check if it is unbound. Note: user_unbind_ can only unbind one
3311 // FuncRequest per key sequence.
3312 if (user_unbind_.getBinding(k) == res)
3313 return FuncRequest::unknown;
3318 bool PrefShortcuts::validateNewShortcut(FuncRequest const & func,
3319 KeySequence const & k,
3320 QString const & lfun_to_modify)
3322 if (func.action() == LFUN_UNKNOWN_ACTION) {
3323 Alert::error(_("Failed to create shortcut"),
3324 _("Unknown or invalid LyX function"));
3328 // It is not currently possible to bind Hidden lfuns such as self-insert. In
3329 // the future, to remove this limitation, see GuiPrefs::insertShortcutItem
3330 // and how it is used in GuiPrefs::shortcutOkPressed.
3331 if (lyxaction.getActionType(func.action()) == LyXAction::Hidden) {
3332 Alert::error(_("Failed to create shortcut"),
3333 _("This LyX function is hidden and cannot be bound."));
3337 if (k.length() == 0) {
3338 Alert::error(_("Failed to create shortcut"),
3339 _("Invalid or empty key sequence"));
3343 FuncRequest oldBinding = currentBinding(k);
3344 if (oldBinding == func)
3345 // nothing to change
3348 // make sure this key isn't already bound---and, if so, prompt user
3349 // (exclude the lfun the user already wants to modify)
3350 docstring const action_string = makeCmdString(oldBinding);
3351 if (oldBinding.action() != LFUN_UNKNOWN_ACTION
3352 && lfun_to_modify != toqstr(action_string)) {
3353 docstring const new_action_string = makeCmdString(func);
3354 docstring const text = bformat(_("Shortcut `%1$s' is already bound to "
3356 "Are you sure you want to unbind the "
3357 "current shortcut and bind it to %3$s?"),
3358 k.print(KeySequence::ForGui), action_string,
3360 int ret = Alert::prompt(_("Redefine shortcut?"),
3361 text, 0, 1, _("&Redefine"), _("&Cancel"));
3364 QString const sequence_text = toqstr(k.print(KeySequence::ForGui));
3365 QList<QTreeWidgetItem*> items = shortcutsTW->findItems(sequence_text,
3366 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 1);
3367 deactivateShortcuts(items);
3373 void PrefShortcuts::shortcutOkPressed()
3375 QString const new_lfun = shortcut_->lfunLE->text();
3376 FuncRequest const func = lyxaction.lookupFunc(fromqstr(new_lfun));
3377 KeySequence k = shortcut_->shortcutWG->getKeySequence();
3379 // save_lfun_ contains the text of the lfun to modify, if the user clicked
3380 // "modify", or is empty if they clicked "new" (which I do not really like)
3381 if (!validateNewShortcut(func, k, save_lfun_))
3384 if (!save_lfun_.isEmpty()) {
3385 // real modification of the lfun's shortcut,
3386 // so remove the previous one
3387 QList<QTreeWidgetItem*> to_modify = shortcutsTW->selectedItems();
3388 deactivateShortcuts(to_modify);
3391 shortcut_->accept();
3393 QTreeWidgetItem * item = insertShortcutItem(func, k, KeyMap::UserBind);
3395 user_bind_.bind(&k, func);
3396 shortcutsTW->sortItems(0, Qt::AscendingOrder);
3397 item->parent()->setExpanded(true);
3398 shortcutsTW->setCurrentItem(item);
3399 shortcutsTW->scrollToItem(item);
3401 Alert::error(_("Failed to create shortcut"),
3402 _("Can not insert shortcut to the list"));
3408 void PrefShortcuts::shortcutCancelPressed()
3410 shortcut_->shortcutWG->reset();
3414 void PrefShortcuts::shortcutClearPressed()
3416 shortcut_->shortcutWG->reset();
3420 void PrefShortcuts::shortcutRemovePressed()
3422 shortcut_->shortcutWG->removeFromSequence();
3426 /////////////////////////////////////////////////////////////////////
3430 /////////////////////////////////////////////////////////////////////
3432 PrefIdentity::PrefIdentity(GuiPreferences * form)
3433 : PrefModule(QString(), N_("Identity"), form)
3437 connect(nameED, SIGNAL(textChanged(QString)),
3438 this, SIGNAL(changed()));
3439 connect(emailED, SIGNAL(textChanged(QString)),
3440 this, SIGNAL(changed()));
3441 connect(initialsED, SIGNAL(textChanged(QString)),
3442 this, SIGNAL(changed()));
3444 nameED->setValidator(new NoNewLineValidator(nameED));
3445 emailED->setValidator(new NoNewLineValidator(emailED));
3446 initialsED->setValidator(new NoNewLineValidator(initialsED));
3450 void PrefIdentity::applyRC(LyXRC & rc) const
3452 rc.user_name = fromqstr(nameED->text());
3453 rc.user_email = fromqstr(emailED->text());
3454 rc.user_initials = fromqstr(initialsED->text());
3458 void PrefIdentity::updateRC(LyXRC const & rc)
3460 nameED->setText(toqstr(rc.user_name));
3461 emailED->setText(toqstr(rc.user_email));
3462 initialsED->setText(toqstr(rc.user_initials));
3467 /////////////////////////////////////////////////////////////////////
3471 /////////////////////////////////////////////////////////////////////
3473 GuiPreferences::GuiPreferences(GuiView & lv)
3474 : GuiDialog(lv, "prefs", qt_("Preferences"))
3478 QDialog::setModal(false);
3480 connect(buttonBox, SIGNAL(clicked(QAbstractButton *)),
3481 this, SLOT(slotButtonBox(QAbstractButton *)));
3483 addModule(new PrefUserInterface(this));
3484 addModule(new PrefDocHandling(this));
3485 addModule(new PrefEdit(this));
3486 addModule(new PrefShortcuts(this));
3487 PrefScreenFonts * screenfonts = new PrefScreenFonts(this);
3488 connect(this, SIGNAL(prefsApplied(LyXRC const &)),
3489 screenfonts, SLOT(updateScreenFontSizes(LyXRC const &)));
3490 addModule(screenfonts);
3491 addModule(new PrefColors(this));
3492 addModule(new PrefDisplay(this));
3493 addModule(new PrefInput(this));
3494 addModule(new PrefCompletion(this));
3496 addModule(new PrefPaths(this));
3498 addModule(new PrefIdentity(this));
3500 addModule(new PrefLanguage(this));
3501 addModule(new PrefSpellchecker(this));
3503 PrefOutput * output = new PrefOutput(this);
3505 addModule(new PrefLatex(this));
3507 PrefConverters * converters = new PrefConverters(this);
3508 PrefFileformats * formats = new PrefFileformats(this);
3509 connect(formats, SIGNAL(formatsChanged()),
3510 converters, SLOT(updateGui()));
3511 addModule(converters);
3514 prefsPS->setCurrentPanel("User Interface");
3515 // FIXME: hack to work around resizing bug in Qt >= 4.2
3516 // bug verified with Qt 4.2.{0-3} (JSpitzm)
3517 #if QT_VERSION >= 0x040200
3518 prefsPS->updateGeometry();
3521 bc().setPolicy(ButtonPolicy::PreferencesPolicy);
3522 bc().setOK(buttonBox->button(QDialogButtonBox::Ok));
3523 bc().setApply(buttonBox->button(QDialogButtonBox::Apply));
3524 bc().setCancel(buttonBox->button(QDialogButtonBox::Cancel));
3525 bc().setRestore(buttonBox->button(QDialogButtonBox::Reset));
3527 guilyxfiles_ = new GuiLyXFiles(lv);
3528 connect(guilyxfiles_, SIGNAL(fileSelected(QString)),
3529 this, SLOT(slotFileSelected(QString)));
3533 void GuiPreferences::addModule(PrefModule * module)
3535 LASSERT(module, return);
3536 if (module->category().isEmpty())
3537 prefsPS->addPanel(module, module->title());
3539 prefsPS->addPanel(module, module->title(), module->category());
3540 connect(module, SIGNAL(changed()), this, SLOT(change_adaptor()));
3541 modules_.push_back(module);
3545 void GuiPreferences::change_adaptor()
3551 void GuiPreferences::applyRC(LyXRC & rc) const
3553 size_t end = modules_.size();
3554 for (size_t i = 0; i != end; ++i)
3555 modules_[i]->applyRC(rc);
3559 void GuiPreferences::updateRC(LyXRC const & rc)
3561 size_t const end = modules_.size();
3562 for (size_t i = 0; i != end; ++i)
3563 modules_[i]->updateRC(rc);
3567 void GuiPreferences::applyView()
3573 bool GuiPreferences::initialiseParams(string const &)
3576 formats_ = theFormats();
3577 converters_ = theConverters();
3578 converters_.update(formats_);
3579 movers_ = theMovers();
3583 // Make sure that the bc is in the INITIAL state
3584 if (bc().policy().buttonStatus(ButtonPolicy::RESTORE))
3591 void GuiPreferences::dispatchParams()
3594 rc_.write(ss, true);
3595 dispatch(FuncRequest(LFUN_LYXRC_APPLY, ss.str()));
3596 // issue prefsApplied signal. This will update the
3597 // localized screen font sizes.
3599 // FIXME: these need lfuns
3601 Author const & author =
3602 Author(from_utf8(rc_.user_name), from_utf8(rc_.user_email),
3603 from_utf8(rc_.user_initials));
3604 theBufferList().recordCurrentAuthor(author);
3606 theFormats() = formats_;
3608 theConverters() = converters_;
3609 theConverters().update(formats_);
3610 theConverters().buildGraph();
3611 theBufferList().invalidateConverterCache();
3613 theMovers() = movers_;
3615 for (string const & color : colors_)
3616 dispatch(FuncRequest(LFUN_SET_COLOR, color));
3620 if (!tempSaveCB->isChecked())
3621 dispatch(FuncRequest(LFUN_PREFERENCES_SAVE));
3625 void GuiPreferences::setColor(ColorCode col, QString const & hex)
3627 colors_.push_back(lcolor.getLyXName(col) + ' ' + fromqstr(hex));
3631 void GuiPreferences::slotFileSelected(QString const file)
3637 QString GuiPreferences::browseLibFile(QString const & dir,
3638 QString const & name, QString const & ext)
3642 guilyxfiles_->passParams(fromqstr(dir));
3643 guilyxfiles_->selectItem(name);
3644 guilyxfiles_->exec();
3646 QString const result = uifile_;
3648 // remove the extension if it is the default one
3649 QString noextresult;
3650 if (getExtension(result) == ext)
3651 noextresult = removeExtension(result);
3653 noextresult = result;
3655 // remove the directory, if it is the default one
3656 QString const file = onlyFileName(noextresult);
3657 if (toqstr(libFileSearch(dir, file, ext).absFileName()) == result)
3664 QString GuiPreferences::browsebind(QString const & file)
3666 return browseLibFile("bind", file, "bind");
3670 QString GuiPreferences::browseUI(QString const & file)
3672 return browseLibFile("ui", file, "ui");
3676 QString GuiPreferences::browsekbmap(QString const & file)
3678 return browseLibFile("kbd", file, "kmap");
3682 QString GuiPreferences::browse(QString const & file,
3683 QString const & title) const
3685 return browseFile(file, title, QStringList(), true);
3689 Dialog * createGuiPreferences(GuiView & lv) { return new GuiPreferences(lv); }
3692 } // namespace frontend
3695 #include "moc_GuiPrefs.cpp"