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"
35 #include "KeySequence.h"
37 #include "LyXAction.h"
39 #include "PanelStack.h"
41 #include "SpellChecker.h"
43 #include "support/debug.h"
44 #include "support/FileName.h"
45 #include "support/filetools.h"
46 #include "support/gettext.h"
47 #include "support/lassert.h"
48 #include "support/lstrings.h"
49 #include "support/Messages.h"
50 #include "support/os.h"
51 #include "support/Package.h"
53 #include "graphics/GraphicsTypes.h"
55 #include "frontends/alert.h"
56 #include "frontends/Application.h"
57 #include "frontends/FontLoader.h"
59 #include <QAbstractItemModel>
61 #include <QColorDialog>
62 #include <QFontDatabase>
63 #include <QHeaderView>
65 #include <QMessageBox>
66 #include <QPushButton>
69 #include <QTreeWidget>
70 #include <QTreeWidgetItem>
81 using namespace lyx::support;
82 using namespace lyx::support::os;
87 /////////////////////////////////////////////////////////////////////
91 /////////////////////////////////////////////////////////////////////
93 /** Launch a file dialog and return the chosen file.
94 filename: a suggested filename.
95 title: the title of the dialog.
97 dir1 = (name, dir), dir2 = (name, dir): extra buttons on the dialog.
99 QString browseFile(QString const & filename,
100 QString const & title,
101 QStringList const & filters,
103 QString const & label1 = QString(),
104 QString const & dir1 = QString(),
105 QString const & label2 = QString(),
106 QString const & dir2 = QString(),
107 QString const & fallback_dir = QString())
109 QString lastPath = ".";
110 if (!filename.isEmpty())
111 lastPath = onlyPath(filename);
112 else if(!fallback_dir.isEmpty())
113 lastPath = fallback_dir;
115 FileDialog dlg(title);
116 dlg.setButton1(label1, dir1);
117 dlg.setButton2(label2, dir2);
119 FileDialog::Result result;
122 result = dlg.save(lastPath, filters, onlyFileName(filename));
124 result = dlg.open(lastPath, filters, onlyFileName(filename));
126 return result.second;
130 /** Launch a file dialog and return the chosen directory.
131 pathname: a suggested pathname.
132 title: the title of the dialog.
133 dir1 = (name, dir), dir2 = (name, dir): extra buttons on the dialog.
135 QString browseDir(QString const & pathname,
136 QString const & title,
137 QString const & label1 = QString(),
138 QString const & dir1 = QString(),
139 QString const & label2 = QString(),
140 QString const & dir2 = QString())
142 QString lastPath = ".";
143 if (!pathname.isEmpty())
144 lastPath = onlyPath(pathname);
146 FileDialog dlg(title);
147 dlg.setButton1(label1, dir1);
148 dlg.setButton2(label2, dir2);
150 FileDialog::Result const result =
151 dlg.opendir(lastPath, onlyFileName(pathname));
153 return result.second;
157 } // namespace frontend
160 QString browseRelToParent(QString const & filename, QString const & relpath,
161 QString const & title, QStringList const & filters, bool save,
162 QString const & label1, QString const & dir1,
163 QString const & label2, QString const & dir2)
165 QString const fname = makeAbsPath(filename, relpath);
167 QString const outname =
168 frontend::browseFile(fname, title, filters, save, label1, dir1, label2, dir2);
170 QString const reloutname =
171 toqstr(makeRelPath(qstring_to_ucs4(outname), qstring_to_ucs4(relpath)));
173 if (reloutname.startsWith("../"))
180 QString browseRelToSub(QString const & filename, QString const & relpath,
181 QString const & title, QStringList const & filters, bool save,
182 QString const & label1, QString const & dir1,
183 QString const & label2, QString const & dir2)
185 QString const fname = makeAbsPath(filename, relpath);
187 QString const outname =
188 frontend::browseFile(fname, title, filters, save, label1, dir1, label2, dir2);
190 QString const reloutname =
191 toqstr(makeRelPath(qstring_to_ucs4(outname), qstring_to_ucs4(relpath)));
193 QString testname = reloutname;
194 testname.remove(QRegExp("^(\\.\\./)+"));
196 if (testname.contains("/"))
204 /////////////////////////////////////////////////////////////////////
208 /////////////////////////////////////////////////////////////////////
212 QString const catLookAndFeel = N_("Look & Feel");
213 QString const catEditing = N_("Editing");
214 QString const catLanguage = N_("Language Settings");
215 QString const catOutput = N_("Output");
216 QString const catFiles = N_("File Handling");
218 static void parseFontName(QString const & mangled0,
219 string & name, string & foundry)
221 string mangled = fromqstr(mangled0);
222 size_t const idx = mangled.find('[');
223 if (idx == string::npos || idx == 0) {
227 name = mangled.substr(0, idx - 1);
228 foundry = mangled.substr(idx + 1, mangled.size() - idx - 2);
233 static void setComboxFont(QComboBox * cb, string const & family,
234 string const & foundry)
236 QString fontname = toqstr(family);
237 if (!foundry.empty())
238 fontname += " [" + toqstr(foundry) + ']';
240 for (int i = 0; i != cb->count(); ++i) {
241 if (cb->itemText(i) == fontname) {
242 cb->setCurrentIndex(i);
247 // Try matching without foundry name
249 // We count in reverse in order to prefer the Xft foundry
250 for (int i = cb->count(); --i >= 0;) {
251 string name, fnt_foundry;
252 parseFontName(cb->itemText(i), name, fnt_foundry);
253 if (compare_ascii_no_case(name, family) == 0) {
254 cb->setCurrentIndex(i);
259 // family alone can contain e.g. "Helvetica [Adobe]"
260 string tmpname, tmpfoundry;
261 parseFontName(toqstr(family), tmpname, tmpfoundry);
263 // We count in reverse in order to prefer the Xft foundry
264 for (int i = cb->count(); --i >= 0; ) {
265 string name, fnt_foundry;
266 parseFontName(cb->itemText(i), name, fnt_foundry);
267 if (compare_ascii_no_case(name, fnt_foundry) == 0) {
268 cb->setCurrentIndex(i);
273 // Bleh, default fonts, and the names couldn't be found. Hack
278 QString const font_family = toqstr(family);
279 if (font_family == guiApp->romanFontName()) {
280 font.setStyleHint(QFont::Serif);
281 font.setFamily(font_family);
282 } else if (font_family == guiApp->sansFontName()) {
283 font.setStyleHint(QFont::SansSerif);
284 font.setFamily(font_family);
285 } else if (font_family == guiApp->typewriterFontName()) {
286 font.setStyleHint(QFont::TypeWriter);
287 font.setFamily(font_family);
289 LYXERR0("FAILED to find the default font: '"
290 << foundry << "', '" << family << '\'');
294 QFontInfo info(font);
295 string default_font_name, dummyfoundry;
296 parseFontName(info.family(), default_font_name, dummyfoundry);
297 LYXERR0("Apparent font is " << default_font_name);
299 for (int i = 0; i < cb->count(); ++i) {
300 LYXERR0("Looking at " << cb->itemText(i));
301 if (compare_ascii_no_case(fromqstr(cb->itemText(i)),
302 default_font_name) == 0) {
303 cb->setCurrentIndex(i);
308 LYXERR0("FAILED to find the font: '"
309 << foundry << "', '" << family << '\'');
313 /////////////////////////////////////////////////////////////////////
317 /////////////////////////////////////////////////////////////////////
319 PrefOutput::PrefOutput(GuiPreferences * form)
320 : PrefModule(catOutput, N_("General[[settings]]"), form)
324 dviCB->setValidator(new NoNewLineValidator(dviCB));
325 pdfCB->setValidator(new NoNewLineValidator(pdfCB));
327 connect(plaintextLinelengthSB, SIGNAL(valueChanged(int)),
328 this, SIGNAL(changed()));
329 connect(overwriteCO, SIGNAL(activated(int)),
330 this, SIGNAL(changed()));
331 connect(dviCB, SIGNAL(editTextChanged(QString)),
332 this, SIGNAL(changed()));
333 connect(pdfCB, SIGNAL(editTextChanged(QString)),
334 this, SIGNAL(changed()));
335 connect(printerPaperTypeED, SIGNAL(textChanged(QString)),
336 this, SIGNAL(changed()));
337 connect(printerLandscapeED, SIGNAL(textChanged(QString)),
338 this, SIGNAL(changed()));
339 connect(printerPaperSizeED, SIGNAL(textChanged(QString)),
340 this, SIGNAL(changed()));
342 printerPaperTypeED->setValidator(new NoNewLineValidator(printerPaperTypeED));
343 printerLandscapeED->setValidator(new NoNewLineValidator(printerLandscapeED));
344 printerPaperSizeED->setValidator(new NoNewLineValidator(printerPaperSizeED));
347 dviCB->addItem("xdvi -sourceposition '$$n:\\ $$t' $$o");
348 dviCB->addItem("yap -1 -s \"$$n $$t\" $$o");
349 dviCB->addItem("okular --unique \"$$o#src:$$n $$f\"");
350 dviCB->addItem("synctex view -i $$n:0:$$t -o $$o -x \"evince -i %{page+1} $$o\"");
352 pdfCB->addItem("CMCDDE SUMATRA control [ForwardSearch(\\\"$$o\\\",\\\"$$t\\\",$$n,0,0,1)]");
353 pdfCB->addItem("SumatraPDF -reuse-instance \"$$o\" -forward-search \"$$t\" $$n");
354 pdfCB->addItem("synctex view -i $$n:0:$$t -o $$o -x \"xpdf -raise -remote $$t.tmp $$o %{page+1}\"");
355 pdfCB->addItem("okular --unique \"$$o#src:$$n $$f\"");
356 pdfCB->addItem("qpdfview --unique \"$$o#src:$$f:$$n:0\"");
357 pdfCB->addItem("synctex view -i $$n:0:$$t -o $$o -x \"evince -i %{page+1} $$o\"");
358 pdfCB->addItem("/Applications/Skim.app/Contents/SharedSupport/displayline $$n $$o $$t");
362 void PrefOutput::applyRC(LyXRC & rc) const
364 rc.plaintext_linelen = plaintextLinelengthSB->value();
365 rc.forward_search_dvi = fromqstr(dviCB->currentText());
366 rc.forward_search_pdf = fromqstr(pdfCB->currentText());
368 switch (overwriteCO->currentIndex()) {
370 rc.export_overwrite = NO_FILES;
373 rc.export_overwrite = MAIN_FILE;
376 rc.export_overwrite = ALL_FILES;
380 rc.print_paper_flag = fromqstr(printerPaperTypeED->text());
381 rc.print_landscape_flag = fromqstr(printerLandscapeED->text());
382 rc.print_paper_dimension_flag = fromqstr(printerPaperSizeED->text());
386 void PrefOutput::updateRC(LyXRC const & rc)
388 plaintextLinelengthSB->setValue(rc.plaintext_linelen);
389 dviCB->setEditText(toqstr(rc.forward_search_dvi));
390 pdfCB->setEditText(toqstr(rc.forward_search_pdf));
392 switch (rc.export_overwrite) {
394 overwriteCO->setCurrentIndex(0);
397 overwriteCO->setCurrentIndex(1);
400 overwriteCO->setCurrentIndex(2);
404 printerPaperTypeED->setText(toqstr(rc.print_paper_flag));
405 printerLandscapeED->setText(toqstr(rc.print_landscape_flag));
406 printerPaperSizeED->setText(toqstr(rc.print_paper_dimension_flag));
410 /////////////////////////////////////////////////////////////////////
414 /////////////////////////////////////////////////////////////////////
416 PrefInput::PrefInput(GuiPreferences * form)
417 : PrefModule(catEditing, N_("Keyboard/Mouse"), form)
421 connect(keymapCB, SIGNAL(clicked()),
422 this, SIGNAL(changed()));
423 connect(firstKeymapED, SIGNAL(textChanged(QString)),
424 this, SIGNAL(changed()));
425 connect(secondKeymapED, SIGNAL(textChanged(QString)),
426 this, SIGNAL(changed()));
427 connect(mouseWheelSpeedSB, SIGNAL(valueChanged(double)),
428 this, SIGNAL(changed()));
429 connect(scrollzoomEnableCB, SIGNAL(clicked()),
430 this, SIGNAL(changed()));
431 connect(scrollzoomValueCO, SIGNAL(activated(int)),
432 this, SIGNAL(changed()));
433 connect(dontswapCB, SIGNAL(toggled(bool)),
434 this, SIGNAL(changed()));
435 connect(mmPasteCB, SIGNAL(toggled(bool)),
436 this, SIGNAL(changed()));
438 // reveal checkbox for switching Ctrl and Meta on Mac:
441 #if QT_VERSION > 0x040600
445 dontswapCB->setVisible(swapcb);
449 void PrefInput::applyRC(LyXRC & rc) const
451 // FIXME: can derive CB from the two EDs
452 rc.use_kbmap = keymapCB->isChecked();
453 rc.primary_kbmap = internal_path(fromqstr(firstKeymapED->text()));
454 rc.secondary_kbmap = internal_path(fromqstr(secondKeymapED->text()));
455 rc.mouse_wheel_speed = mouseWheelSpeedSB->value();
456 if (scrollzoomEnableCB->isChecked()) {
457 switch (scrollzoomValueCO->currentIndex()) {
459 rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_CTRL;
462 rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_SHIFT;
465 rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_ALT;
469 rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_OFF;
471 rc.mac_dontswap_ctrl_meta = dontswapCB->isChecked();
472 rc.mouse_middlebutton_paste = mmPasteCB->isChecked();
476 void PrefInput::updateRC(LyXRC const & rc)
478 // FIXME: can derive CB from the two EDs
479 keymapCB->setChecked(rc.use_kbmap);
480 firstKeymapED->setText(toqstr(external_path(rc.primary_kbmap)));
481 secondKeymapED->setText(toqstr(external_path(rc.secondary_kbmap)));
482 mouseWheelSpeedSB->setValue(rc.mouse_wheel_speed);
483 switch (rc.scroll_wheel_zoom) {
484 case LyXRC::SCROLL_WHEEL_ZOOM_OFF:
485 scrollzoomEnableCB->setChecked(false);
487 case LyXRC::SCROLL_WHEEL_ZOOM_CTRL:
488 scrollzoomEnableCB->setChecked(true);
489 scrollzoomValueCO->setCurrentIndex(0);
491 case LyXRC::SCROLL_WHEEL_ZOOM_SHIFT:
492 scrollzoomEnableCB->setChecked(true);
493 scrollzoomValueCO->setCurrentIndex(1);
495 case LyXRC::SCROLL_WHEEL_ZOOM_ALT:
496 scrollzoomEnableCB->setChecked(true);
497 scrollzoomValueCO->setCurrentIndex(2);
500 dontswapCB->setChecked(rc.mac_dontswap_ctrl_meta);
501 mmPasteCB->setChecked(rc.mouse_middlebutton_paste);
505 QString PrefInput::testKeymap(QString const & keymap)
507 return form_->browsekbmap(internalPath(keymap));
511 void PrefInput::on_firstKeymapPB_clicked(bool)
513 QString const file = testKeymap(firstKeymapED->text());
515 firstKeymapED->setText(file);
519 void PrefInput::on_secondKeymapPB_clicked(bool)
521 QString const file = testKeymap(secondKeymapED->text());
523 secondKeymapED->setText(file);
527 void PrefInput::on_keymapCB_toggled(bool keymap)
529 firstKeymapLA->setEnabled(keymap);
530 secondKeymapLA->setEnabled(keymap);
531 firstKeymapED->setEnabled(keymap);
532 secondKeymapED->setEnabled(keymap);
533 firstKeymapPB->setEnabled(keymap);
534 secondKeymapPB->setEnabled(keymap);
538 void PrefInput::on_scrollzoomEnableCB_toggled(bool enabled)
540 scrollzoomValueCO->setEnabled(enabled);
544 /////////////////////////////////////////////////////////////////////
548 /////////////////////////////////////////////////////////////////////
550 PrefCompletion::PrefCompletion(GuiPreferences * form)
551 : PrefModule(catEditing, N_("Input Completion"), form)
555 connect(inlineDelaySB, SIGNAL(valueChanged(double)),
556 this, SIGNAL(changed()));
557 connect(inlineMathCB, SIGNAL(clicked()),
558 this, SIGNAL(changed()));
559 connect(inlineTextCB, SIGNAL(clicked()),
560 this, SIGNAL(changed()));
561 connect(inlineDotsCB, SIGNAL(clicked()),
562 this, SIGNAL(changed()));
563 connect(popupDelaySB, SIGNAL(valueChanged(double)),
564 this, SIGNAL(changed()));
565 connect(popupMathCB, SIGNAL(clicked()),
566 this, SIGNAL(changed()));
567 connect(autocorrectionCB, SIGNAL(clicked()),
568 this, SIGNAL(changed()));
569 connect(popupTextCB, SIGNAL(clicked()),
570 this, SIGNAL(changed()));
571 connect(popupAfterCompleteCB, SIGNAL(clicked()),
572 this, SIGNAL(changed()));
573 connect(cursorTextCB, SIGNAL(clicked()),
574 this, SIGNAL(changed()));
575 connect(minlengthSB, SIGNAL(valueChanged(int)),
576 this, SIGNAL(changed()));
580 void PrefCompletion::on_inlineTextCB_clicked()
586 void PrefCompletion::on_popupTextCB_clicked()
592 void PrefCompletion::enableCB()
594 cursorTextCB->setEnabled(
595 popupTextCB->isChecked() || inlineTextCB->isChecked());
599 void PrefCompletion::applyRC(LyXRC & rc) const
601 rc.completion_inline_delay = inlineDelaySB->value();
602 rc.completion_inline_math = inlineMathCB->isChecked();
603 rc.completion_inline_text = inlineTextCB->isChecked();
604 rc.completion_inline_dots = inlineDotsCB->isChecked() ? 13 : -1;
605 rc.completion_popup_delay = popupDelaySB->value();
606 rc.completion_popup_math = popupMathCB->isChecked();
607 rc.autocorrection_math = autocorrectionCB->isChecked();
608 rc.completion_popup_text = popupTextCB->isChecked();
609 rc.completion_cursor_text = cursorTextCB->isChecked();
610 rc.completion_popup_after_complete =
611 popupAfterCompleteCB->isChecked();
612 rc.completion_minlength = minlengthSB->value();
616 void PrefCompletion::updateRC(LyXRC const & rc)
618 inlineDelaySB->setValue(rc.completion_inline_delay);
619 inlineMathCB->setChecked(rc.completion_inline_math);
620 inlineTextCB->setChecked(rc.completion_inline_text);
621 inlineDotsCB->setChecked(rc.completion_inline_dots != -1);
622 popupDelaySB->setValue(rc.completion_popup_delay);
623 popupMathCB->setChecked(rc.completion_popup_math);
624 autocorrectionCB->setChecked(rc.autocorrection_math);
625 popupTextCB->setChecked(rc.completion_popup_text);
626 cursorTextCB->setChecked(rc.completion_cursor_text);
627 popupAfterCompleteCB->setChecked(rc.completion_popup_after_complete);
629 minlengthSB->setValue(rc.completion_minlength);
634 /////////////////////////////////////////////////////////////////////
638 /////////////////////////////////////////////////////////////////////
640 PrefLatex::PrefLatex(GuiPreferences * form)
641 : PrefModule(catOutput, N_("LaTeX"), form)
645 latexDviPaperED->setValidator(new NoNewLineValidator(latexDviPaperED));
646 latexBibtexED->setValidator(new NoNewLineValidator(latexBibtexED));
647 latexJBibtexED->setValidator(new NoNewLineValidator(latexJBibtexED));
648 latexIndexED->setValidator(new NoNewLineValidator(latexIndexED));
649 latexJIndexED->setValidator(new NoNewLineValidator(latexJIndexED));
650 latexNomenclED->setValidator(new NoNewLineValidator(latexNomenclED));
651 latexChecktexED->setValidator(new NoNewLineValidator(latexChecktexED));
653 connect(latexChecktexED, SIGNAL(textChanged(QString)),
654 this, SIGNAL(changed()));
655 connect(latexBibtexCO, SIGNAL(activated(int)),
656 this, SIGNAL(changed()));
657 connect(latexBibtexED, SIGNAL(textChanged(QString)),
658 this, SIGNAL(changed()));
659 connect(latexJBibtexCO, SIGNAL(activated(int)),
660 this, SIGNAL(changed()));
661 connect(latexJBibtexED, SIGNAL(textChanged(QString)),
662 this, SIGNAL(changed()));
663 connect(latexIndexCO, SIGNAL(activated(int)),
664 this, SIGNAL(changed()));
665 connect(latexIndexED, SIGNAL(textChanged(QString)),
666 this, SIGNAL(changed()));
667 connect(latexJIndexED, SIGNAL(textChanged(QString)),
668 this, SIGNAL(changed()));
669 connect(latexAutoresetCB, SIGNAL(clicked()),
670 this, SIGNAL(changed()));
671 connect(latexDviPaperED, SIGNAL(textChanged(QString)),
672 this, SIGNAL(changed()));
673 connect(latexNomenclED, SIGNAL(textChanged(QString)),
674 this, SIGNAL(changed()));
676 #if defined(__CYGWIN__) || defined(_WIN32)
677 pathCB->setVisible(true);
678 connect(pathCB, SIGNAL(clicked()),
679 this, SIGNAL(changed()));
681 pathCB->setVisible(false);
686 void PrefLatex::on_latexBibtexCO_activated(int n)
688 QString const bibtex = latexBibtexCO->itemData(n).toString();
689 if (bibtex.isEmpty()) {
690 latexBibtexED->clear();
691 latexBibtexOptionsLA->setText(qt_("C&ommand:"));
694 for (LyXRC::CommandSet::const_iterator it = bibtex_alternatives.begin();
695 it != bibtex_alternatives.end(); ++it) {
696 QString const bib = toqstr(*it);
697 int ind = bib.indexOf(" ");
698 QString sel_command = bib.left(ind);
699 QString sel_options = ind < 0 ? QString() : bib.mid(ind + 1);
700 if (bibtex == sel_command) {
702 latexBibtexED->clear();
704 latexBibtexED->setText(sel_options.trimmed());
707 latexBibtexOptionsLA->setText(qt_("&Options:"));
711 void PrefLatex::on_latexJBibtexCO_activated(int n)
713 QString const jbibtex = latexJBibtexCO->itemData(n).toString();
714 if (jbibtex.isEmpty()) {
715 latexJBibtexED->clear();
716 latexJBibtexOptionsLA->setText(qt_("Co&mmand:"));
719 for (LyXRC::CommandSet::const_iterator it = jbibtex_alternatives.begin();
720 it != jbibtex_alternatives.end(); ++it) {
721 QString const bib = toqstr(*it);
722 int ind = bib.indexOf(" ");
723 QString sel_command = bib.left(ind);
724 QString sel_options = ind < 0 ? QString() : bib.mid(ind + 1);
725 if (jbibtex == sel_command) {
727 latexJBibtexED->clear();
729 latexJBibtexED->setText(sel_options.trimmed());
732 latexJBibtexOptionsLA->setText(qt_("Opt&ions:"));
736 void PrefLatex::on_latexIndexCO_activated(int n)
738 QString const index = latexIndexCO->itemData(n).toString();
739 if (index.isEmpty()) {
740 latexIndexED->clear();
741 latexIndexOptionsLA->setText(qt_("Co&mmand:"));
744 for (LyXRC::CommandSet::const_iterator it = index_alternatives.begin();
745 it != index_alternatives.end(); ++it) {
746 QString const idx = toqstr(*it);
747 int ind = idx.indexOf(" ");
748 QString sel_command = idx.left(ind);
749 QString sel_options = ind < 0 ? QString() : idx.mid(ind + 1);
750 if (index == sel_command) {
752 latexIndexED->clear();
754 latexIndexED->setText(sel_options.trimmed());
757 latexIndexOptionsLA->setText(qt_("Op&tions:"));
761 void PrefLatex::applyRC(LyXRC & rc) const
763 // If bibtex is not empty, bibopt contains the options, otherwise
764 // it is a customized bibtex command with options.
765 QString const bibtex = latexBibtexCO->itemData(
766 latexBibtexCO->currentIndex()).toString();
767 QString const bibopt = latexBibtexED->text();
768 if (bibtex.isEmpty())
769 rc.bibtex_command = fromqstr(bibopt);
770 else if (bibopt.isEmpty())
771 rc.bibtex_command = fromqstr(bibtex);
773 rc.bibtex_command = fromqstr(bibtex) + " " + fromqstr(bibopt);
775 // If jbibtex is not empty, jbibopt contains the options, otherwise
776 // it is a customized bibtex command with options.
777 QString const jbibtex = latexJBibtexCO->itemData(
778 latexJBibtexCO->currentIndex()).toString();
779 QString const jbibopt = latexJBibtexED->text();
780 if (jbibtex.isEmpty())
781 rc.jbibtex_command = fromqstr(jbibopt);
782 else if (jbibopt.isEmpty())
783 rc.jbibtex_command = fromqstr(jbibtex);
785 rc.jbibtex_command = fromqstr(jbibtex) + " " + fromqstr(jbibopt);
787 // If index is not empty, idxopt contains the options, otherwise
788 // it is a customized index command with options.
789 QString const index = latexIndexCO->itemData(
790 latexIndexCO->currentIndex()).toString();
791 QString const idxopt = latexIndexED->text();
793 rc.index_command = fromqstr(idxopt);
794 else if (idxopt.isEmpty())
795 rc.index_command = fromqstr(index);
797 rc.index_command = fromqstr(index) + " " + fromqstr(idxopt);
799 rc.chktex_command = fromqstr(latexChecktexED->text());
800 rc.jindex_command = fromqstr(latexJIndexED->text());
801 rc.nomencl_command = fromqstr(latexNomenclED->text());
802 rc.auto_reset_options = latexAutoresetCB->isChecked();
803 rc.view_dvi_paper_option = fromqstr(latexDviPaperED->text());
804 #if defined(__CYGWIN__) || defined(_WIN32)
805 rc.windows_style_tex_paths = pathCB->isChecked();
810 void PrefLatex::updateRC(LyXRC const & rc)
812 latexBibtexCO->clear();
814 latexBibtexCO->addItem(qt_("Automatic"), "automatic");
815 latexBibtexCO->addItem(qt_("Custom"), QString());
816 for (LyXRC::CommandSet::const_iterator it = rc.bibtex_alternatives.begin();
817 it != rc.bibtex_alternatives.end(); ++it) {
818 QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
819 latexBibtexCO->addItem(command, command);
822 bibtex_alternatives = rc.bibtex_alternatives;
824 QString const bib = toqstr(rc.bibtex_command);
825 int ind = bib.indexOf(" ");
826 QString sel_command = bib.left(ind);
827 QString sel_options = ind < 0 ? QString() : bib.mid(ind + 1);
829 int pos = latexBibtexCO->findData(sel_command);
831 latexBibtexCO->setCurrentIndex(pos);
832 latexBibtexED->setText(sel_options.trimmed());
833 latexBibtexOptionsLA->setText(qt_("&Options:"));
835 latexBibtexED->setText(toqstr(rc.bibtex_command));
836 latexBibtexCO->setCurrentIndex(0);
837 latexBibtexOptionsLA->setText(qt_("C&ommand:"));
840 latexJBibtexCO->clear();
842 latexJBibtexCO->addItem(qt_("Automatic"), "automatic");
843 latexJBibtexCO->addItem(qt_("Custom"), QString());
844 for (LyXRC::CommandSet::const_iterator it = rc.jbibtex_alternatives.begin();
845 it != rc.jbibtex_alternatives.end(); ++it) {
846 QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
847 latexJBibtexCO->addItem(command, command);
850 jbibtex_alternatives = rc.jbibtex_alternatives;
852 QString const jbib = toqstr(rc.jbibtex_command);
853 ind = jbib.indexOf(" ");
854 sel_command = jbib.left(ind);
855 sel_options = ind < 0 ? QString() : jbib.mid(ind + 1);
857 pos = latexJBibtexCO->findData(sel_command);
859 latexJBibtexCO->setCurrentIndex(pos);
860 latexJBibtexED->setText(sel_options.trimmed());
861 latexJBibtexOptionsLA->setText(qt_("Opt&ions:"));
863 latexJBibtexED->setText(toqstr(rc.bibtex_command));
864 latexJBibtexCO->setCurrentIndex(0);
865 latexJBibtexOptionsLA->setText(qt_("Co&mmand:"));
868 latexIndexCO->clear();
870 latexIndexCO->addItem(qt_("Custom"), QString());
871 for (LyXRC::CommandSet::const_iterator it = rc.index_alternatives.begin();
872 it != rc.index_alternatives.end(); ++it) {
873 QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
874 latexIndexCO->addItem(command, command);
877 index_alternatives = rc.index_alternatives;
879 QString const idx = toqstr(rc.index_command);
880 ind = idx.indexOf(" ");
881 sel_command = idx.left(ind);
882 sel_options = ind < 0 ? QString() : idx.mid(ind + 1);
884 pos = latexIndexCO->findData(sel_command);
886 latexIndexCO->setCurrentIndex(pos);
887 latexIndexED->setText(sel_options.trimmed());
888 latexIndexOptionsLA->setText(qt_("Op&tions:"));
890 latexIndexED->setText(toqstr(rc.index_command));
891 latexIndexCO->setCurrentIndex(0);
892 latexIndexOptionsLA->setText(qt_("Co&mmand:"));
895 latexChecktexED->setText(toqstr(rc.chktex_command));
896 latexJIndexED->setText(toqstr(rc.jindex_command));
897 latexNomenclED->setText(toqstr(rc.nomencl_command));
898 latexAutoresetCB->setChecked(rc.auto_reset_options);
899 latexDviPaperED->setText(toqstr(rc.view_dvi_paper_option));
900 #if defined(__CYGWIN__) || defined(_WIN32)
901 pathCB->setChecked(rc.windows_style_tex_paths);
906 /////////////////////////////////////////////////////////////////////
910 /////////////////////////////////////////////////////////////////////
912 PrefScreenFonts::PrefScreenFonts(GuiPreferences * form)
913 : PrefModule(catLookAndFeel, N_("Screen Fonts"), form)
917 connect(screenRomanCO, SIGNAL(activated(QString)),
918 this, SLOT(selectRoman(QString)));
919 connect(screenSansCO, SIGNAL(activated(QString)),
920 this, SLOT(selectSans(QString)));
921 connect(screenTypewriterCO, SIGNAL(activated(QString)),
922 this, SLOT(selectTypewriter(QString)));
924 QFontDatabase fontdb;
925 QStringList families(fontdb.families());
926 for (auto const & family : families) {
927 screenRomanCO->addItem(family);
928 screenSansCO->addItem(family);
929 screenTypewriterCO->addItem(family);
931 connect(screenRomanCO, SIGNAL(activated(QString)),
932 this, SIGNAL(changed()));
933 connect(screenSansCO, SIGNAL(activated(QString)),
934 this, SIGNAL(changed()));
935 connect(screenTypewriterCO, SIGNAL(activated(QString)),
936 this, SIGNAL(changed()));
937 connect(screenZoomSB, SIGNAL(valueChanged(int)),
938 this, SIGNAL(changed()));
939 connect(screenTinyED, SIGNAL(textChanged(QString)),
940 this, SIGNAL(changed()));
941 connect(screenSmallestED, SIGNAL(textChanged(QString)),
942 this, SIGNAL(changed()));
943 connect(screenSmallerED, SIGNAL(textChanged(QString)),
944 this, SIGNAL(changed()));
945 connect(screenSmallED, SIGNAL(textChanged(QString)),
946 this, SIGNAL(changed()));
947 connect(screenNormalED, SIGNAL(textChanged(QString)),
948 this, SIGNAL(changed()));
949 connect(screenLargeED, SIGNAL(textChanged(QString)),
950 this, SIGNAL(changed()));
951 connect(screenLargerED, SIGNAL(textChanged(QString)),
952 this, SIGNAL(changed()));
953 connect(screenLargestED, SIGNAL(textChanged(QString)),
954 this, SIGNAL(changed()));
955 connect(screenHugeED, SIGNAL(textChanged(QString)),
956 this, SIGNAL(changed()));
957 connect(screenHugerED, SIGNAL(textChanged(QString)),
958 this, SIGNAL(changed()));
960 screenTinyED->setValidator(new QDoubleValidator(screenTinyED));
961 screenSmallestED->setValidator(new QDoubleValidator(screenSmallestED));
962 screenSmallerED->setValidator(new QDoubleValidator(screenSmallerED));
963 screenSmallED->setValidator(new QDoubleValidator(screenSmallED));
964 screenNormalED->setValidator(new QDoubleValidator(screenNormalED));
965 screenLargeED->setValidator(new QDoubleValidator(screenLargeED));
966 screenLargerED->setValidator(new QDoubleValidator(screenLargerED));
967 screenLargestED->setValidator(new QDoubleValidator(screenLargestED));
968 screenHugeED->setValidator(new QDoubleValidator(screenHugeED));
969 screenHugerED->setValidator(new QDoubleValidator(screenHugerED));
973 void PrefScreenFonts::applyRC(LyXRC & rc) const
975 LyXRC const oldrc = rc;
977 parseFontName(screenRomanCO->currentText(),
978 rc.roman_font_name, rc.roman_font_foundry);
979 parseFontName(screenSansCO->currentText(),
980 rc.sans_font_name, rc.sans_font_foundry);
981 parseFontName(screenTypewriterCO->currentText(),
982 rc.typewriter_font_name, rc.typewriter_font_foundry);
984 rc.defaultZoom = screenZoomSB->value();
985 rc.font_sizes[TINY_SIZE] = widgetToDoubleStr(screenTinyED);
986 rc.font_sizes[SCRIPT_SIZE] = widgetToDoubleStr(screenSmallestED);
987 rc.font_sizes[FOOTNOTE_SIZE] = widgetToDoubleStr(screenSmallerED);
988 rc.font_sizes[SMALL_SIZE] = widgetToDoubleStr(screenSmallED);
989 rc.font_sizes[NORMAL_SIZE] = widgetToDoubleStr(screenNormalED);
990 rc.font_sizes[LARGE_SIZE] = widgetToDoubleStr(screenLargeED);
991 rc.font_sizes[LARGER_SIZE] = widgetToDoubleStr(screenLargerED);
992 rc.font_sizes[LARGEST_SIZE] = widgetToDoubleStr(screenLargestED);
993 rc.font_sizes[HUGE_SIZE] = widgetToDoubleStr(screenHugeED);
994 rc.font_sizes[HUGER_SIZE] = widgetToDoubleStr(screenHugerED);
998 void PrefScreenFonts::updateRC(LyXRC const & rc)
1000 setComboxFont(screenRomanCO, rc.roman_font_name,
1001 rc.roman_font_foundry);
1002 setComboxFont(screenSansCO, rc.sans_font_name,
1003 rc.sans_font_foundry);
1004 setComboxFont(screenTypewriterCO, rc.typewriter_font_name,
1005 rc.typewriter_font_foundry);
1007 selectRoman(screenRomanCO->currentText());
1008 selectSans(screenSansCO->currentText());
1009 selectTypewriter(screenTypewriterCO->currentText());
1011 screenZoomSB->setValue(rc.defaultZoom);
1012 updateScreenFontSizes(rc);
1016 void PrefScreenFonts::updateScreenFontSizes(LyXRC const & rc)
1018 doubleToWidget(screenTinyED, rc.font_sizes[TINY_SIZE]);
1019 doubleToWidget(screenSmallestED, rc.font_sizes[SCRIPT_SIZE]);
1020 doubleToWidget(screenSmallerED, rc.font_sizes[FOOTNOTE_SIZE]);
1021 doubleToWidget(screenSmallED, rc.font_sizes[SMALL_SIZE]);
1022 doubleToWidget(screenNormalED, rc.font_sizes[NORMAL_SIZE]);
1023 doubleToWidget(screenLargeED, rc.font_sizes[LARGE_SIZE]);
1024 doubleToWidget(screenLargerED, rc.font_sizes[LARGER_SIZE]);
1025 doubleToWidget(screenLargestED, rc.font_sizes[LARGEST_SIZE]);
1026 doubleToWidget(screenHugeED, rc.font_sizes[HUGE_SIZE]);
1027 doubleToWidget(screenHugerED, rc.font_sizes[HUGER_SIZE]);
1031 void PrefScreenFonts::selectRoman(const QString & name)
1033 screenRomanFE->set(QFont(name), name);
1037 void PrefScreenFonts::selectSans(const QString & name)
1039 screenSansFE->set(QFont(name), name);
1043 void PrefScreenFonts::selectTypewriter(const QString & name)
1045 screenTypewriterFE->set(QFont(name), name);
1049 /////////////////////////////////////////////////////////////////////
1053 /////////////////////////////////////////////////////////////////////
1056 PrefColors::PrefColors(GuiPreferences * form)
1057 : PrefModule(catLookAndFeel, N_("Colors"), form)
1061 // FIXME: all of this initialization should be put into the controller.
1062 // See http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg113301.html
1063 // for some discussion of why that is not trivial.
1064 QPixmap icon(32, 32);
1065 for (int i = 0; i < Color_ignore; ++i) {
1066 ColorCode lc = static_cast<ColorCode>(i);
1067 if (lc == Color_none
1068 || lc == Color_black
1069 || lc == Color_white
1071 || lc == Color_brown
1073 || lc == Color_darkgray
1075 || lc == Color_green
1076 || lc == Color_lightgray
1078 || lc == Color_magenta
1079 || lc == Color_olive
1080 || lc == Color_orange
1082 || lc == Color_purple
1085 || lc == Color_violet
1086 || lc == Color_yellow
1087 || lc == Color_inherit
1088 || lc == Color_ignore)
1090 lcolors_.push_back(lc);
1092 sort(lcolors_.begin(), lcolors_.end(), ColorSorter);
1093 vector<ColorCode>::const_iterator cit = lcolors_.begin();
1094 vector<ColorCode>::const_iterator const end = lcolors_.end();
1095 for (; cit != end; ++cit) {
1096 (void) new QListWidgetItem(QIcon(icon),
1097 toqstr(lcolor.getGUIName(*cit)), lyxObjectsLW);
1099 curcolors_.resize(lcolors_.size());
1100 newcolors_.resize(lcolors_.size());
1101 // End initialization
1103 connect(colorChangePB, SIGNAL(clicked()),
1104 this, SLOT(changeColor()));
1105 connect(colorResetPB, SIGNAL(clicked()),
1106 this, SLOT(resetColor()));
1107 connect(colorResetAllPB, SIGNAL(clicked()),
1108 this, SLOT(resetAllColor()));
1109 connect(lyxObjectsLW, SIGNAL(itemSelectionChanged()),
1110 this, SLOT(changeLyxObjectsSelection()));
1111 connect(lyxObjectsLW, SIGNAL(itemActivated(QListWidgetItem*)),
1112 this, SLOT(changeColor()));
1113 connect(syscolorsCB, SIGNAL(toggled(bool)),
1114 this, SIGNAL(changed()));
1115 connect(syscolorsCB, SIGNAL(toggled(bool)),
1116 this, SLOT(changeSysColor()));
1120 void PrefColors::applyRC(LyXRC & rc) const
1124 for (unsigned int i = 0; i < lcolors_.size(); ++i)
1125 if (curcolors_[i] != newcolors_[i])
1126 form_->setColor(lcolors_[i], newcolors_[i]);
1127 rc.use_system_colors = syscolorsCB->isChecked();
1129 if (oldrc.use_system_colors != rc.use_system_colors)
1130 guiApp->colorCache().clear();
1134 void PrefColors::updateRC(LyXRC const & rc)
1136 for (size_type i = 0; i < lcolors_.size(); ++i) {
1137 QColor color = QColor(guiApp->colorCache().get(lcolors_[i], false));
1138 QPixmap coloritem(32, 32);
1139 coloritem.fill(color);
1140 lyxObjectsLW->item(int(i))->setIcon(QIcon(coloritem));
1141 newcolors_[i] = curcolors_[i] = color.name();
1143 syscolorsCB->setChecked(rc.use_system_colors);
1144 changeLyxObjectsSelection();
1146 setDisabledResets();
1150 void PrefColors::changeColor()
1152 int const row = lyxObjectsLW->currentRow();
1158 QString const color = newcolors_[size_t(row)];
1159 QColor const c = QColorDialog::getColor(QColor(color), qApp->focusWidget());
1161 if (setColor(row, c, color)) {
1162 setDisabledResets();
1169 void PrefColors::resetColor()
1171 int const row = lyxObjectsLW->currentRow();
1177 QString const color = newcolors_[size_t(row)];
1178 QColor const c = getDefaultColorByRow(row);
1180 if (setColor(row, c, color)) {
1181 setDisabledResets();
1188 void PrefColors::resetAllColor()
1190 bool isChanged = false;
1192 colorResetAllPB->setDisabled(true);
1194 for (int irow = 0, count = lyxObjectsLW->count(); irow < count; ++irow) {
1195 QString const color = newcolors_[size_t(irow)];
1196 QColor const c = getDefaultColorByRow(irow);
1198 if (setColor(irow, c, color))
1203 setDisabledResets();
1210 bool PrefColors::setColor(int const row, QColor const new_color,
1211 QString const old_color)
1213 if (new_color.isValid() && new_color.name() != old_color) {
1214 newcolors_[size_t(row)] = new_color.name();
1215 QPixmap coloritem(32, 32);
1216 coloritem.fill(new_color);
1217 lyxObjectsLW->item(row)->setIcon(QIcon(coloritem));
1224 void PrefColors::setDisabledResets()
1226 int const row = lyxObjectsLW->currentRow();
1227 // set disable reset buttons ...
1229 colorResetPB->setDisabled(isDefaultColor(row, newcolors_[size_t(row)]));
1231 colorResetAllPB->setDisabled(true);
1233 // ... in between process qt events to give quicker visual feedback to the user ...
1234 guiApp->processEvents();
1236 // ... set disable Reset All button
1237 for (int irow = 0, count = lyxObjectsLW->count(); irow < count; ++irow) {
1238 if (!isDefaultColor(irow, newcolors_[size_t(irow)])) {
1239 colorResetAllPB->setDisabled(false);
1240 // the break condition might hide performance issues
1241 // if a non-default color is at the top of the list
1248 bool PrefColors::isDefaultColor(int const row, QString const color)
1250 return color == getDefaultColorByRow(row).name();
1254 QColor PrefColors::getDefaultColorByRow(int const row)
1256 ColorSet const defaultcolor;
1257 return defaultcolor.getX11HexName(lcolors_[size_t(row)]).c_str();
1261 void PrefColors::changeSysColor()
1263 for (int row = 0 ; row < lyxObjectsLW->count() ; ++row) {
1264 // skip colors that are taken from system palette
1265 bool const disable = syscolorsCB->isChecked()
1266 && guiApp->colorCache().isSystem(lcolors_[size_t(row)]);
1268 QListWidgetItem * const item = lyxObjectsLW->item(row);
1269 Qt::ItemFlags const flags = item->flags();
1272 item->setFlags(flags & ~Qt::ItemIsEnabled);
1274 item->setFlags(flags | Qt::ItemIsEnabled);
1279 void PrefColors::changeLyxObjectsSelection()
1281 int currentRow = lyxObjectsLW->currentRow();
1282 colorChangePB->setDisabled(currentRow < 0);
1285 colorResetPB->setDisabled(true);
1287 colorResetPB->setDisabled(
1288 isDefaultColor(currentRow, newcolors_[size_t(currentRow)]));
1292 /////////////////////////////////////////////////////////////////////
1296 /////////////////////////////////////////////////////////////////////
1298 PrefDisplay::PrefDisplay(GuiPreferences * form)
1299 : PrefModule(catLookAndFeel, N_("Display"), form)
1302 connect(displayGraphicsCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1303 connect(instantPreviewCO, SIGNAL(activated(int)), this, SIGNAL(changed()));
1304 connect(previewSizeSB, SIGNAL(valueChanged(double)), this, SIGNAL(changed()));
1305 connect(paragraphMarkerCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1306 connect(ctAdditionsUnderlinedCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1310 void PrefDisplay::on_instantPreviewCO_currentIndexChanged(int index)
1312 previewSizeSB->setEnabled(index != 0);
1316 void PrefDisplay::applyRC(LyXRC & rc) const
1318 switch (instantPreviewCO->currentIndex()) {
1320 rc.preview = LyXRC::PREVIEW_OFF;
1323 rc.preview = LyXRC::PREVIEW_NO_MATH;
1326 rc.preview = LyXRC::PREVIEW_ON;
1330 rc.display_graphics = displayGraphicsCB->isChecked();
1331 rc.preview_scale_factor = previewSizeSB->value();
1332 rc.paragraph_markers = paragraphMarkerCB->isChecked();
1333 rc.ct_additions_underlined = ctAdditionsUnderlinedCB->isChecked();
1335 // FIXME!! The graphics cache no longer has a changeDisplay method.
1337 if (old_value != rc.display_graphics) {
1338 graphics::GCache & gc = graphics::GCache::get();
1345 void PrefDisplay::updateRC(LyXRC const & rc)
1347 switch (rc.preview) {
1348 case LyXRC::PREVIEW_OFF:
1349 instantPreviewCO->setCurrentIndex(0);
1351 case LyXRC::PREVIEW_NO_MATH :
1352 instantPreviewCO->setCurrentIndex(1);
1354 case LyXRC::PREVIEW_ON :
1355 instantPreviewCO->setCurrentIndex(2);
1359 displayGraphicsCB->setChecked(rc.display_graphics);
1360 previewSizeSB->setValue(rc.preview_scale_factor);
1361 paragraphMarkerCB->setChecked(rc.paragraph_markers);
1362 ctAdditionsUnderlinedCB->setChecked(rc.ct_additions_underlined);
1363 previewSizeSB->setEnabled(
1365 && rc.preview != LyXRC::PREVIEW_OFF);
1369 /////////////////////////////////////////////////////////////////////
1373 /////////////////////////////////////////////////////////////////////
1375 PrefPaths::PrefPaths(GuiPreferences * form)
1376 : PrefModule(QString(), N_("Paths"), form)
1380 connect(workingDirPB, SIGNAL(clicked()), this, SLOT(selectWorkingdir()));
1381 connect(workingDirED, SIGNAL(textChanged(QString)),
1382 this, SIGNAL(changed()));
1384 connect(templateDirPB, SIGNAL(clicked()), this, SLOT(selectTemplatedir()));
1385 connect(templateDirED, SIGNAL(textChanged(QString)),
1386 this, SIGNAL(changed()));
1388 connect(exampleDirPB, SIGNAL(clicked()), this, SLOT(selectExampledir()));
1389 connect(exampleDirED, SIGNAL(textChanged(QString)),
1390 this, SIGNAL(changed()));
1392 connect(backupDirPB, SIGNAL(clicked()), this, SLOT(selectBackupdir()));
1393 connect(backupDirED, SIGNAL(textChanged(QString)),
1394 this, SIGNAL(changed()));
1396 connect(lyxserverDirPB, SIGNAL(clicked()), this, SLOT(selectLyxPipe()));
1397 connect(lyxserverDirED, SIGNAL(textChanged(QString)),
1398 this, SIGNAL(changed()));
1400 connect(thesaurusDirPB, SIGNAL(clicked()), this, SLOT(selectThesaurusdir()));
1401 connect(thesaurusDirED, SIGNAL(textChanged(QString)),
1402 this, SIGNAL(changed()));
1404 connect(tempDirPB, SIGNAL(clicked()), this, SLOT(selectTempdir()));
1405 connect(tempDirED, SIGNAL(textChanged(QString)),
1406 this, SIGNAL(changed()));
1408 #if defined(USE_HUNSPELL)
1409 connect(hunspellDirPB, SIGNAL(clicked()), this, SLOT(selectHunspelldir()));
1410 connect(hunspellDirED, SIGNAL(textChanged(QString)),
1411 this, SIGNAL(changed()));
1413 hunspellDirPB->setEnabled(false);
1414 hunspellDirED->setEnabled(false);
1417 connect(pathPrefixED, SIGNAL(textChanged(QString)),
1418 this, SIGNAL(changed()));
1420 connect(texinputsPrefixED, SIGNAL(textChanged(QString)),
1421 this, SIGNAL(changed()));
1423 pathPrefixED->setValidator(new NoNewLineValidator(pathPrefixED));
1424 texinputsPrefixED->setValidator(new NoNewLineValidator(texinputsPrefixED));
1428 void PrefPaths::applyRC(LyXRC & rc) const
1430 rc.document_path = internal_path(fromqstr(workingDirED->text()));
1431 rc.example_path = internal_path(fromqstr(exampleDirED->text()));
1432 rc.template_path = internal_path(fromqstr(templateDirED->text()));
1433 rc.backupdir_path = internal_path(fromqstr(backupDirED->text()));
1434 rc.tempdir_path = internal_path(fromqstr(tempDirED->text()));
1435 rc.thesaurusdir_path = internal_path(fromqstr(thesaurusDirED->text()));
1436 rc.hunspelldir_path = internal_path(fromqstr(hunspellDirED->text()));
1437 rc.path_prefix = internal_path_list(fromqstr(pathPrefixED->text()));
1438 rc.texinputs_prefix = internal_path_list(fromqstr(texinputsPrefixED->text()));
1439 // FIXME: should be a checkbox only
1440 rc.lyxpipes = internal_path(fromqstr(lyxserverDirED->text()));
1444 void PrefPaths::updateRC(LyXRC const & rc)
1446 workingDirED->setText(toqstr(external_path(rc.document_path)));
1447 exampleDirED->setText(toqstr(external_path(rc.example_path)));
1448 templateDirED->setText(toqstr(external_path(rc.template_path)));
1449 backupDirED->setText(toqstr(external_path(rc.backupdir_path)));
1450 tempDirED->setText(toqstr(external_path(rc.tempdir_path)));
1451 thesaurusDirED->setText(toqstr(external_path(rc.thesaurusdir_path)));
1452 hunspellDirED->setText(toqstr(external_path(rc.hunspelldir_path)));
1453 pathPrefixED->setText(toqstr(external_path_list(rc.path_prefix)));
1454 texinputsPrefixED->setText(toqstr(external_path_list(rc.texinputs_prefix)));
1455 // FIXME: should be a checkbox only
1456 lyxserverDirED->setText(toqstr(external_path(rc.lyxpipes)));
1460 void PrefPaths::selectExampledir()
1462 QString file = browseDir(internalPath(exampleDirED->text()),
1463 qt_("Select directory for example files"));
1464 if (!file.isEmpty())
1465 exampleDirED->setText(file);
1469 void PrefPaths::selectTemplatedir()
1471 QString file = browseDir(internalPath(templateDirED->text()),
1472 qt_("Select a document templates directory"));
1473 if (!file.isEmpty())
1474 templateDirED->setText(file);
1478 void PrefPaths::selectTempdir()
1480 QString file = browseDir(internalPath(tempDirED->text()),
1481 qt_("Select a temporary directory"));
1482 if (!file.isEmpty())
1483 tempDirED->setText(file);
1487 void PrefPaths::selectBackupdir()
1489 QString file = browseDir(internalPath(backupDirED->text()),
1490 qt_("Select a backups directory"));
1491 if (!file.isEmpty())
1492 backupDirED->setText(file);
1496 void PrefPaths::selectWorkingdir()
1498 QString file = browseDir(internalPath(workingDirED->text()),
1499 qt_("Select a document directory"));
1500 if (!file.isEmpty())
1501 workingDirED->setText(file);
1505 void PrefPaths::selectThesaurusdir()
1507 QString file = browseDir(internalPath(thesaurusDirED->text()),
1508 qt_("Set the path to the thesaurus dictionaries"));
1509 if (!file.isEmpty())
1510 thesaurusDirED->setText(file);
1514 void PrefPaths::selectHunspelldir()
1516 QString file = browseDir(internalPath(hunspellDirED->text()),
1517 qt_("Set the path to the Hunspell dictionaries"));
1518 if (!file.isEmpty())
1519 hunspellDirED->setText(file);
1523 void PrefPaths::selectLyxPipe()
1525 QString file = form_->browse(internalPath(lyxserverDirED->text()),
1526 qt_("Give a filename for the LyX server pipe"));
1527 if (!file.isEmpty())
1528 lyxserverDirED->setText(file);
1532 /////////////////////////////////////////////////////////////////////
1536 /////////////////////////////////////////////////////////////////////
1538 PrefSpellchecker::PrefSpellchecker(GuiPreferences * form)
1539 : PrefModule(catLanguage, N_("Spellchecker"), form)
1543 // FIXME: this check should test the target platform (darwin)
1544 #if defined(USE_MACOSX_PACKAGING)
1545 spellcheckerCB->addItem(qt_("Native"), QString("native"));
1546 #define CONNECT_APPLESPELL
1548 #undef CONNECT_APPLESPELL
1550 #if defined(USE_ASPELL)
1551 spellcheckerCB->addItem(qt_("Aspell"), QString("aspell"));
1553 #if defined(USE_ENCHANT)
1554 spellcheckerCB->addItem(qt_("Enchant"), QString("enchant"));
1556 #if defined(USE_HUNSPELL)
1557 spellcheckerCB->addItem(qt_("Hunspell"), QString("hunspell"));
1560 #if defined(CONNECT_APPLESPELL) || defined(USE_ASPELL) || defined(USE_ENCHANT) || defined(USE_HUNSPELL)
1561 connect(spellcheckerCB, SIGNAL(currentIndexChanged(int)),
1562 this, SIGNAL(changed()));
1563 connect(altLanguageED, SIGNAL(textChanged(QString)),
1564 this, SIGNAL(changed()));
1565 connect(escapeCharactersED, SIGNAL(textChanged(QString)),
1566 this, SIGNAL(changed()));
1567 connect(compoundWordCB, SIGNAL(clicked()),
1568 this, SIGNAL(changed()));
1569 connect(spellcheckContinuouslyCB, SIGNAL(clicked()),
1570 this, SIGNAL(changed()));
1571 connect(spellcheckNotesCB, SIGNAL(clicked()),
1572 this, SIGNAL(changed()));
1574 altLanguageED->setValidator(new NoNewLineValidator(altLanguageED));
1575 escapeCharactersED->setValidator(new NoNewLineValidator(escapeCharactersED));
1577 spellcheckerCB->setEnabled(false);
1578 altLanguageED->setEnabled(false);
1579 escapeCharactersED->setEnabled(false);
1580 compoundWordCB->setEnabled(false);
1581 spellcheckContinuouslyCB->setEnabled(false);
1582 spellcheckNotesCB->setEnabled(false);
1587 void PrefSpellchecker::applyRC(LyXRC & rc) const
1589 string const speller = fromqstr(spellcheckerCB->
1590 itemData(spellcheckerCB->currentIndex()).toString());
1591 if (!speller.empty())
1592 rc.spellchecker = speller;
1593 rc.spellchecker_alt_lang = fromqstr(altLanguageED->text());
1594 rc.spellchecker_esc_chars = fromqstr(escapeCharactersED->text());
1595 rc.spellchecker_accept_compound = compoundWordCB->isChecked();
1596 rc.spellcheck_continuously = spellcheckContinuouslyCB->isChecked();
1597 rc.spellcheck_notes = spellcheckNotesCB->isChecked();
1601 void PrefSpellchecker::updateRC(LyXRC const & rc)
1603 spellcheckerCB->setCurrentIndex(
1604 spellcheckerCB->findData(toqstr(rc.spellchecker)));
1605 altLanguageED->setText(toqstr(rc.spellchecker_alt_lang));
1606 escapeCharactersED->setText(toqstr(rc.spellchecker_esc_chars));
1607 compoundWordCB->setChecked(rc.spellchecker_accept_compound);
1608 spellcheckContinuouslyCB->setChecked(rc.spellcheck_continuously);
1609 spellcheckNotesCB->setChecked(rc.spellcheck_notes);
1613 void PrefSpellchecker::on_spellcheckerCB_currentIndexChanged(int index)
1615 QString spellchecker = spellcheckerCB->itemData(index).toString();
1617 compoundWordCB->setEnabled(spellchecker == QString("aspell"));
1622 /////////////////////////////////////////////////////////////////////
1626 /////////////////////////////////////////////////////////////////////
1629 PrefConverters::PrefConverters(GuiPreferences * form)
1630 : PrefModule(catFiles, N_("Converters"), form)
1634 connect(converterNewPB, SIGNAL(clicked()),
1635 this, SLOT(updateConverter()));
1636 connect(converterRemovePB, SIGNAL(clicked()),
1637 this, SLOT(removeConverter()));
1638 connect(converterModifyPB, SIGNAL(clicked()),
1639 this, SLOT(updateConverter()));
1640 connect(convertersLW, SIGNAL(currentRowChanged(int)),
1641 this, SLOT(switchConverter()));
1642 connect(converterFromCO, SIGNAL(activated(QString)),
1643 this, SLOT(changeConverter()));
1644 connect(converterToCO, SIGNAL(activated(QString)),
1645 this, SLOT(changeConverter()));
1646 connect(converterED, SIGNAL(textEdited(QString)),
1647 this, SLOT(changeConverter()));
1648 connect(converterFlagED, SIGNAL(textEdited(QString)),
1649 this, SLOT(changeConverter()));
1650 connect(converterNewPB, SIGNAL(clicked()),
1651 this, SIGNAL(changed()));
1652 connect(converterRemovePB, SIGNAL(clicked()),
1653 this, SIGNAL(changed()));
1654 connect(converterModifyPB, SIGNAL(clicked()),
1655 this, SIGNAL(changed()));
1656 connect(maxAgeLE, SIGNAL(textEdited(QString)),
1657 this, SIGNAL(changed()));
1658 connect(needauthForbiddenCB, SIGNAL(toggled(bool)),
1659 this, SIGNAL(changed()));
1661 converterED->setValidator(new NoNewLineValidator(converterED));
1662 converterFlagED->setValidator(new NoNewLineValidator(converterFlagED));
1663 maxAgeLE->setValidator(new QDoubleValidator(0, HUGE_VAL, 6, maxAgeLE));
1664 //converterDefGB->setFocusProxy(convertersLW);
1668 void PrefConverters::applyRC(LyXRC & rc) const
1670 rc.use_converter_cache = cacheCB->isChecked();
1671 rc.use_converter_needauth_forbidden = needauthForbiddenCB->isChecked();
1672 rc.use_converter_needauth = needauthCB->isChecked();
1673 rc.converter_cache_maxage = int(widgetToDouble(maxAgeLE) * 86400.0);
1677 static void setCheckboxBlockSignals(QCheckBox *cb, bool checked) {
1678 cb->blockSignals(true);
1679 cb->setChecked(checked);
1680 cb->blockSignals(false);
1684 void PrefConverters::updateRC(LyXRC const & rc)
1686 cacheCB->setChecked(rc.use_converter_cache);
1687 needauthForbiddenCB->setChecked(rc.use_converter_needauth_forbidden);
1688 setCheckboxBlockSignals(needauthCB, rc.use_converter_needauth);
1690 doubleToWidget(maxAgeLE, (double(rc.converter_cache_maxage) / 86400.0), 'g', 6);
1695 void PrefConverters::updateGui()
1697 QString const pattern("%1 -> %2");
1698 form_->formats().sort();
1699 form_->converters().update(form_->formats());
1700 // save current selection
1703 .arg(converterFromCO->currentText())
1704 .arg(converterToCO->currentText());
1706 converterFromCO->clear();
1707 converterToCO->clear();
1709 for (Format const & f : form_->formats()) {
1710 QString const name = toqstr(translateIfPossible(f.prettyname()));
1711 converterFromCO->addItem(name);
1712 converterToCO->addItem(name);
1715 // currentRowChanged(int) is also triggered when updating the listwidget
1716 // block signals to avoid unnecessary calls to switchConverter()
1717 convertersLW->blockSignals(true);
1718 convertersLW->clear();
1720 for (Converter const & c : form_->converters()) {
1721 QString const name =
1723 .arg(toqstr(translateIfPossible(c.From()->prettyname())))
1724 .arg(toqstr(translateIfPossible(c.To()->prettyname())));
1725 int type = form_->converters().getNumber(c.From()->name(),
1727 new QListWidgetItem(name, convertersLW, type);
1729 convertersLW->sortItems(Qt::AscendingOrder);
1730 convertersLW->blockSignals(false);
1732 // restore selection
1733 if (current != pattern.arg(QString()).arg(QString())) {
1734 QList<QListWidgetItem *> const item =
1735 convertersLW->findItems(current, Qt::MatchExactly);
1736 if (!item.isEmpty())
1737 convertersLW->setCurrentItem(item.at(0));
1740 // select first element if restoring failed
1741 if (convertersLW->currentRow() == -1)
1742 convertersLW->setCurrentRow(0);
1748 void PrefConverters::switchConverter()
1750 int const cnr = convertersLW->currentItem()->type();
1751 Converter const & c(form_->converters().get(cnr));
1752 converterFromCO->setCurrentIndex(form_->formats().getNumber(c.from()));
1753 converterToCO->setCurrentIndex(form_->formats().getNumber(c.to()));
1754 converterED->setText(toqstr(c.command()));
1755 converterFlagED->setText(toqstr(c.flags()));
1761 void PrefConverters::changeConverter()
1767 void PrefConverters::updateButtons()
1769 if (form_->formats().empty())
1771 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1772 Format const & to = form_->formats().get(converterToCO->currentIndex());
1773 int const sel = form_->converters().getNumber(from.name(), to.name());
1774 bool const known = sel >= 0;
1775 bool const valid = !(converterED->text().isEmpty()
1776 || from.name() == to.name());
1781 if (convertersLW->count() > 0) {
1782 int const cnr = convertersLW->currentItem()->type();
1783 Converter const & c = form_->converters().get(cnr);
1784 old_command = c.command();
1785 old_flag = c.flags();
1788 string const new_command = fromqstr(converterED->text());
1789 string const new_flag = fromqstr(converterFlagED->text());
1791 bool modified = (old_command != new_command || old_flag != new_flag);
1793 converterModifyPB->setEnabled(valid && known && modified);
1794 converterNewPB->setEnabled(valid && !known);
1795 converterRemovePB->setEnabled(known);
1797 maxAgeLE->setEnabled(cacheCB->isChecked());
1798 maxAgeLA->setEnabled(cacheCB->isChecked());
1803 // specify unique from/to or it doesn't appear. This is really bad UI
1804 // this is why we can use the same function for both new and modify
1805 void PrefConverters::updateConverter()
1807 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1808 Format const & to = form_->formats().get(converterToCO->currentIndex());
1809 string const flags = fromqstr(converterFlagED->text());
1810 string const command = fromqstr(converterED->text());
1812 Converter const * old =
1813 form_->converters().getConverter(from.name(), to.name());
1814 form_->converters().add(from.name(), to.name(), command, flags);
1817 form_->converters().updateLast(form_->formats());
1821 // Remove all files created by this converter from the cache, since
1822 // the modified converter might create different files.
1823 ConverterCache::get().remove_all(from.name(), to.name());
1827 void PrefConverters::removeConverter()
1829 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1830 Format const & to = form_->formats().get(converterToCO->currentIndex());
1831 form_->converters().erase(from.name(), to.name());
1835 // Remove all files created by this converter from the cache, since
1836 // a possible new converter might create different files.
1837 ConverterCache::get().remove_all(from.name(), to.name());
1841 void PrefConverters::on_cacheCB_stateChanged(int state)
1843 maxAgeLE->setEnabled(state == Qt::Checked);
1844 maxAgeLA->setEnabled(state == Qt::Checked);
1849 void PrefConverters::on_needauthForbiddenCB_toggled(bool checked)
1851 needauthCB->setEnabled(!checked);
1855 void PrefConverters::on_needauthCB_toggled(bool checked)
1862 int ret = frontend::Alert::prompt(
1863 _("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!"),
1864 0, 0, _("&No"), _("&Yes"));
1868 setCheckboxBlockSignals(needauthCB, true);
1872 /////////////////////////////////////////////////////////////////////
1876 /////////////////////////////////////////////////////////////////////
1878 class FormatValidator : public QValidator
1881 FormatValidator(QWidget *, Formats const & f);
1882 void fixup(QString & input) const override;
1883 QValidator::State validate(QString & input, int & pos) const override;
1885 virtual QString toString(Format const & format) const = 0;
1887 Formats const & formats_;
1891 FormatValidator::FormatValidator(QWidget * parent, Formats const & f)
1892 : QValidator(parent), formats_(f)
1897 void FormatValidator::fixup(QString & input) const
1899 Formats::const_iterator cit = formats_.begin();
1900 Formats::const_iterator end = formats_.end();
1901 for (; cit != end; ++cit) {
1902 QString const name = toString(*cit);
1903 if (distance(formats_.begin(), cit) == nr()) {
1911 QValidator::State FormatValidator::validate(QString & input, int & /*pos*/) const
1913 Formats::const_iterator cit = formats_.begin();
1914 Formats::const_iterator end = formats_.end();
1915 bool unknown = true;
1916 for (; unknown && cit != end; ++cit) {
1917 QString const name = toString(*cit);
1918 if (distance(formats_.begin(), cit) != nr())
1919 unknown = name != input;
1922 if (unknown && !input.isEmpty())
1923 return QValidator::Acceptable;
1925 return QValidator::Intermediate;
1929 int FormatValidator::nr() const
1931 QComboBox * p = qobject_cast<QComboBox *>(parent());
1932 return p->itemData(p->currentIndex()).toInt();
1936 /////////////////////////////////////////////////////////////////////
1938 // FormatNameValidator
1940 /////////////////////////////////////////////////////////////////////
1942 class FormatNameValidator : public FormatValidator
1945 FormatNameValidator(QWidget * parent, Formats const & f)
1946 : FormatValidator(parent, f)
1949 QString toString(Format const & format) const override
1951 return toqstr(format.name());
1956 /////////////////////////////////////////////////////////////////////
1958 // FormatPrettynameValidator
1960 /////////////////////////////////////////////////////////////////////
1962 class FormatPrettynameValidator : public FormatValidator
1965 FormatPrettynameValidator(QWidget * parent, Formats const & f)
1966 : FormatValidator(parent, f)
1969 QString toString(Format const & format) const override
1971 return toqstr(translateIfPossible(format.prettyname()));
1976 /////////////////////////////////////////////////////////////////////
1980 /////////////////////////////////////////////////////////////////////
1982 PrefFileformats::PrefFileformats(GuiPreferences * form)
1983 : PrefModule(catFiles, N_("File Formats"), form)
1987 formatED->setValidator(new FormatNameValidator(formatsCB, form_->formats()));
1988 formatsCB->setValidator(new FormatPrettynameValidator(formatsCB, form_->formats()));
1989 extensionsED->setValidator(new NoNewLineValidator(extensionsED));
1990 shortcutED->setValidator(new NoNewLineValidator(shortcutED));
1991 editorED->setValidator(new NoNewLineValidator(editorED));
1992 viewerED->setValidator(new NoNewLineValidator(viewerED));
1993 copierED->setValidator(new NoNewLineValidator(copierED));
1995 connect(documentCB, SIGNAL(clicked()),
1996 this, SLOT(setFlags()));
1997 connect(vectorCB, SIGNAL(clicked()),
1998 this, SLOT(setFlags()));
1999 connect(exportMenuCB, SIGNAL(clicked()),
2000 this, SLOT(setFlags()));
2001 connect(formatsCB->lineEdit(), SIGNAL(editingFinished()),
2002 this, SLOT(updatePrettyname()));
2003 connect(formatsCB->lineEdit(), SIGNAL(textEdited(QString)),
2004 this, SIGNAL(changed()));
2005 connect(defaultFormatCB, SIGNAL(activated(QString)),
2006 this, SIGNAL(changed()));
2007 connect(defaultOTFFormatCB, SIGNAL(activated(QString)),
2008 this, SIGNAL(changed()));
2009 connect(defaultPlatexFormatCB, SIGNAL(activated(QString)),
2010 this, SIGNAL(changed()));
2011 connect(viewerCO, SIGNAL(activated(int)),
2012 this, SIGNAL(changed()));
2013 connect(editorCO, SIGNAL(activated(int)),
2014 this, SIGNAL(changed()));
2020 string const l10n_shortcut(docstring const & prettyname, string const & shortcut)
2022 if (shortcut.empty())
2025 string l10n_format =
2026 to_utf8(_(to_utf8(prettyname) + '|' + shortcut));
2027 return split(l10n_format, '|');
2033 void PrefFileformats::applyRC(LyXRC & rc) const
2035 QString const default_format = defaultFormatCB->itemData(
2036 defaultFormatCB->currentIndex()).toString();
2037 rc.default_view_format = fromqstr(default_format);
2038 QString const default_otf_format = defaultOTFFormatCB->itemData(
2039 defaultOTFFormatCB->currentIndex()).toString();
2040 rc.default_otf_view_format = fromqstr(default_otf_format);
2041 QString const default_platex_format = defaultPlatexFormatCB->itemData(
2042 defaultPlatexFormatCB->currentIndex()).toString();
2043 rc.default_platex_view_format = fromqstr(default_platex_format);
2047 void PrefFileformats::updateRC(LyXRC const & rc)
2049 viewer_alternatives = rc.viewer_alternatives;
2050 editor_alternatives = rc.editor_alternatives;
2051 bool const init = defaultFormatCB->currentText().isEmpty();
2055 defaultFormatCB->findData(toqstr(rc.default_view_format));
2056 defaultFormatCB->setCurrentIndex(pos);
2057 pos = defaultOTFFormatCB->findData(toqstr(rc.default_otf_view_format));
2058 defaultOTFFormatCB->setCurrentIndex(pos);
2059 defaultOTFFormatCB->setCurrentIndex(pos);
2060 pos = defaultPlatexFormatCB->findData(toqstr(rc.default_platex_view_format));
2061 defaultPlatexFormatCB->setCurrentIndex(pos);
2062 defaultPlatexFormatCB->setCurrentIndex(pos);
2067 void PrefFileformats::updateView()
2069 QString const current = formatsCB->currentText();
2070 QString const current_def = defaultFormatCB->currentText();
2071 QString const current_def_otf = defaultOTFFormatCB->currentText();
2072 QString const current_def_platex = defaultPlatexFormatCB->currentText();
2074 // update comboboxes with formats
2075 formatsCB->blockSignals(true);
2076 defaultFormatCB->blockSignals(true);
2077 defaultOTFFormatCB->blockSignals(true);
2078 defaultPlatexFormatCB->blockSignals(true);
2080 defaultFormatCB->clear();
2081 defaultOTFFormatCB->clear();
2082 defaultPlatexFormatCB->clear();
2083 form_->formats().sort();
2084 for (Format const & f : form_->formats()) {
2085 QString const prettyname = toqstr(translateIfPossible(f.prettyname()));
2086 formatsCB->addItem(prettyname,
2087 QVariant(form_->formats().getNumber(f.name())));
2088 if (f.viewer().empty())
2090 if (form_->converters().isReachable("xhtml", f.name())
2091 || form_->converters().isReachable("dviluatex", f.name())
2092 || form_->converters().isReachable("luatex", f.name())
2093 || form_->converters().isReachable("xetex", f.name())) {
2094 defaultFormatCB->addItem(prettyname,
2095 QVariant(toqstr(f.name())));
2096 defaultOTFFormatCB->addItem(prettyname,
2097 QVariant(toqstr(f.name())));
2099 if (form_->converters().isReachable("latex", f.name())
2100 || form_->converters().isReachable("pdflatex", f.name()))
2101 defaultFormatCB->addItem(prettyname,
2102 QVariant(toqstr(f.name())));
2103 if (form_->converters().isReachable("platex", f.name()))
2104 defaultPlatexFormatCB->addItem(prettyname,
2105 QVariant(toqstr(f.name())));
2109 // restore selections
2110 int item = formatsCB->findText(current, Qt::MatchExactly);
2111 formatsCB->setCurrentIndex(item < 0 ? 0 : item);
2112 on_formatsCB_currentIndexChanged(item < 0 ? 0 : item);
2113 item = defaultFormatCB->findText(current_def, Qt::MatchExactly);
2114 defaultFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2115 item = defaultOTFFormatCB->findText(current_def_otf, Qt::MatchExactly);
2116 defaultOTFFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2117 item = defaultPlatexFormatCB->findText(current_def_platex, Qt::MatchExactly);
2118 defaultPlatexFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2119 formatsCB->blockSignals(false);
2120 defaultFormatCB->blockSignals(false);
2121 defaultOTFFormatCB->blockSignals(false);
2122 defaultPlatexFormatCB->blockSignals(false);
2126 void PrefFileformats::on_formatsCB_currentIndexChanged(int i)
2128 if (form_->formats().empty())
2130 int const nr = formatsCB->itemData(i).toInt();
2131 Format const f = form_->formats().get(nr);
2133 formatED->setText(toqstr(f.name()));
2134 copierED->setText(toqstr(form_->movers().command(f.name())));
2135 extensionsED->setText(toqstr(f.extensions()));
2136 mimeED->setText(toqstr(f.mime()));
2137 shortcutED->setText(
2138 toqstr(l10n_shortcut(f.prettyname(), f.shortcut())));
2139 documentCB->setChecked((f.documentFormat()));
2140 vectorCB->setChecked((f.vectorFormat()));
2141 exportMenuCB->setChecked((f.inExportMenu()));
2142 exportMenuCB->setEnabled((f.documentFormat()));
2148 void PrefFileformats::setFlags()
2150 int flags = Format::none;
2151 if (documentCB->isChecked())
2152 flags |= Format::document;
2153 if (vectorCB->isChecked())
2154 flags |= Format::vector;
2155 if (exportMenuCB->isChecked())
2156 flags |= Format::export_menu;
2157 currentFormat().setFlags(flags);
2158 exportMenuCB->setEnabled(documentCB->isChecked());
2163 void PrefFileformats::on_copierED_textEdited(const QString & s)
2165 string const fmt = fromqstr(formatED->text());
2166 form_->movers().set(fmt, fromqstr(s));
2171 void PrefFileformats::on_extensionsED_textEdited(const QString & s)
2173 currentFormat().setExtensions(fromqstr(s));
2178 void PrefFileformats::on_viewerED_textEdited(const QString & s)
2180 currentFormat().setViewer(fromqstr(s));
2185 void PrefFileformats::on_editorED_textEdited(const QString & s)
2187 currentFormat().setEditor(fromqstr(s));
2192 void PrefFileformats::on_mimeED_textEdited(const QString & s)
2194 currentFormat().setMime(fromqstr(s));
2199 void PrefFileformats::on_shortcutED_textEdited(const QString & s)
2201 string const new_shortcut = fromqstr(s);
2202 if (new_shortcut == l10n_shortcut(currentFormat().prettyname(),
2203 currentFormat().shortcut()))
2205 currentFormat().setShortcut(new_shortcut);
2210 void PrefFileformats::on_formatED_editingFinished()
2212 string const newname = fromqstr(formatED->displayText());
2213 string const oldname = currentFormat().name();
2214 if (newname == oldname)
2216 if (form_->converters().formatIsUsed(oldname)) {
2217 Alert::error(_("Format in use"),
2218 _("You cannot change a format's short name "
2219 "if the format is used by a converter. "
2220 "Please remove the converter first."));
2225 currentFormat().setName(newname);
2230 void PrefFileformats::on_formatED_textChanged(const QString &)
2232 QString t = formatED->text();
2234 bool valid = formatED->validator()->validate(t, p) == QValidator::Acceptable;
2235 setValid(formatLA, valid);
2239 void PrefFileformats::on_formatsCB_editTextChanged(const QString &)
2241 QString t = formatsCB->currentText();
2243 bool valid = formatsCB->validator()->validate(t, p) == QValidator::Acceptable;
2244 setValid(formatsLA, valid);
2248 void PrefFileformats::updatePrettyname()
2250 QString const newname = formatsCB->currentText();
2251 if (newname == toqstr(translateIfPossible(currentFormat().prettyname())))
2254 currentFormat().setPrettyname(qstring_to_ucs4(newname));
2262 void updateComboBox(LyXRC::Alternatives const & alts,
2263 string const & fmt, QComboBox * combo)
2265 LyXRC::Alternatives::const_iterator it =
2267 if (it != alts.end()) {
2268 LyXRC::CommandSet const & cmds = it->second;
2269 LyXRC::CommandSet::const_iterator sit =
2271 LyXRC::CommandSet::const_iterator const sen =
2273 for (; sit != sen; ++sit) {
2274 QString const qcmd = toqstr(*sit);
2275 combo->addItem(qcmd, qcmd);
2282 void PrefFileformats::updateViewers()
2284 Format const f = currentFormat();
2285 viewerCO->blockSignals(true);
2287 viewerCO->addItem(qt_("None"), QString());
2288 updateComboBox(viewer_alternatives, f.name(), viewerCO);
2289 viewerCO->addItem(qt_("Custom"), QString("custom viewer"));
2290 viewerCO->blockSignals(false);
2292 int pos = viewerCO->findData(toqstr(f.viewer()));
2295 viewerED->setEnabled(false);
2296 viewerCO->setCurrentIndex(pos);
2298 viewerED->setEnabled(true);
2299 viewerED->setText(toqstr(f.viewer()));
2300 viewerCO->setCurrentIndex(viewerCO->findData(toqstr("custom viewer")));
2305 void PrefFileformats::updateEditors()
2307 Format const f = currentFormat();
2308 editorCO->blockSignals(true);
2310 editorCO->addItem(qt_("None"), QString());
2311 updateComboBox(editor_alternatives, f.name(), editorCO);
2312 editorCO->addItem(qt_("Custom"), QString("custom editor"));
2313 editorCO->blockSignals(false);
2315 int pos = editorCO->findData(toqstr(f.editor()));
2318 editorED->setEnabled(false);
2319 editorCO->setCurrentIndex(pos);
2321 editorED->setEnabled(true);
2322 editorED->setText(toqstr(f.editor()));
2323 editorCO->setCurrentIndex(editorCO->findData(toqstr("custom editor")));
2328 void PrefFileformats::on_viewerCO_currentIndexChanged(int i)
2330 bool const custom = viewerCO->itemData(i).toString() == "custom viewer";
2331 viewerED->setEnabled(custom);
2333 currentFormat().setViewer(fromqstr(viewerCO->itemData(i).toString()));
2337 void PrefFileformats::on_editorCO_currentIndexChanged(int i)
2339 bool const custom = editorCO->itemData(i).toString() == "custom editor";
2340 editorED->setEnabled(custom);
2342 currentFormat().setEditor(fromqstr(editorCO->itemData(i).toString()));
2346 Format & PrefFileformats::currentFormat()
2348 int const i = formatsCB->currentIndex();
2349 int const nr = formatsCB->itemData(i).toInt();
2350 return form_->formats().get(nr);
2354 void PrefFileformats::on_formatNewPB_clicked()
2356 form_->formats().add("", "", docstring(), "", "", "", "", Format::none);
2358 formatsCB->setCurrentIndex(0);
2359 formatsCB->setFocus(Qt::OtherFocusReason);
2363 void PrefFileformats::on_formatRemovePB_clicked()
2365 int const i = formatsCB->currentIndex();
2366 int const nr = formatsCB->itemData(i).toInt();
2367 string const current_text = form_->formats().get(nr).name();
2368 if (form_->converters().formatIsUsed(current_text)) {
2369 Alert::error(_("Format in use"),
2370 _("Cannot remove a Format used by a Converter. "
2371 "Remove the converter first."));
2375 form_->formats().erase(current_text);
2378 on_formatsCB_editTextChanged(formatsCB->currentText());
2383 /////////////////////////////////////////////////////////////////////
2387 /////////////////////////////////////////////////////////////////////
2389 PrefLanguage::PrefLanguage(GuiPreferences * form)
2390 : PrefModule(catLanguage, N_("Language"), form)
2394 connect(visualCursorRB, SIGNAL(clicked()),
2395 this, SIGNAL(changed()));
2396 connect(logicalCursorRB, SIGNAL(clicked()),
2397 this, SIGNAL(changed()));
2398 connect(markForeignCB, SIGNAL(clicked()),
2399 this, SIGNAL(changed()));
2400 connect(respectOSkbdCB, SIGNAL(clicked()),
2401 this, SIGNAL(changed()));
2402 connect(explicitDocLangBeginCB, SIGNAL(clicked()),
2403 this, SIGNAL(changed()));
2404 connect(explicitDocLangEndCB, SIGNAL(clicked()),
2405 this, SIGNAL(changed()));
2406 connect(languagePackageCO, SIGNAL(activated(int)),
2407 this, SIGNAL(changed()));
2408 connect(languagePackageED, SIGNAL(textChanged(QString)),
2409 this, SIGNAL(changed()));
2410 connect(globalCB, SIGNAL(clicked()),
2411 this, SIGNAL(changed()));
2412 connect(startCommandED, SIGNAL(textChanged(QString)),
2413 this, SIGNAL(changed()));
2414 connect(endCommandED, SIGNAL(textChanged(QString)),
2415 this, SIGNAL(changed()));
2416 connect(uiLanguageCO, SIGNAL(activated(int)),
2417 this, SIGNAL(changed()));
2418 connect(defaultDecimalSepED, SIGNAL(textChanged(QString)),
2419 this, SIGNAL(changed()));
2420 connect(defaultDecimalSepCO, SIGNAL(activated(int)),
2421 this, SIGNAL(changed()));
2422 connect(defaultLengthUnitCO, SIGNAL(activated(int)),
2423 this, SIGNAL(changed()));
2425 languagePackageED->setValidator(new NoNewLineValidator(languagePackageED));
2426 startCommandED->setValidator(new NoNewLineValidator(startCommandED));
2427 endCommandED->setValidator(new NoNewLineValidator(endCommandED));
2429 defaultDecimalSepED->setValidator(new QRegExpValidator(QRegExp("\\S"), this));
2430 defaultDecimalSepED->setMaxLength(1);
2432 defaultLengthUnitCO->addItem(lyx::qt_(unit_name_gui[Length::CM]), Length::CM);
2433 defaultLengthUnitCO->addItem(lyx::qt_(unit_name_gui[Length::IN]), Length::IN);
2435 QAbstractItemModel * language_model = guiApp->languageModel();
2436 language_model->sort(0);
2437 uiLanguageCO->blockSignals(true);
2438 uiLanguageCO->clear();
2439 uiLanguageCO->addItem(qt_("Default"), toqstr("auto"));
2440 for (int i = 0; i != language_model->rowCount(); ++i) {
2441 QModelIndex index = language_model->index(i, 0);
2442 // Filter the list based on the available translation and add
2443 // each language code only once
2444 string const name = fromqstr(index.data(Qt::UserRole).toString());
2445 Language const * lang = languages.getLanguage(name);
2448 // never remove the currently selected language
2449 if (name != form->rc().gui_language
2450 && name != lyxrc.gui_language
2451 && (!Messages::available(lang->code())
2452 || !lang->hasGuiSupport()))
2454 uiLanguageCO->addItem(index.data(Qt::DisplayRole).toString(),
2455 index.data(Qt::UserRole).toString());
2457 uiLanguageCO->blockSignals(false);
2461 void PrefLanguage::on_uiLanguageCO_currentIndexChanged(int)
2463 QMessageBox::information(this, qt_("LyX needs to be restarted!"),
2464 qt_("The change of user interface language will be fully "
2465 "effective only after a restart."));
2469 void PrefLanguage::on_languagePackageCO_currentIndexChanged(int i)
2472 languagePackageED->setText(save_langpack_);
2473 else if (!languagePackageED->text().isEmpty()) {
2474 save_langpack_ = languagePackageED->text();
2475 languagePackageED->clear();
2477 languagePackageED->setEnabled(i == 2);
2481 void PrefLanguage::on_defaultDecimalSepCO_currentIndexChanged(int i)
2483 defaultDecimalSepED->setEnabled(i == 1);
2487 void PrefLanguage::applyRC(LyXRC & rc) const
2489 rc.visual_cursor = visualCursorRB->isChecked();
2490 rc.mark_foreign_language = markForeignCB->isChecked();
2491 rc.respect_os_kbd_language = respectOSkbdCB->isChecked();
2492 rc.language_auto_begin = !explicitDocLangBeginCB->isChecked();
2493 rc.language_auto_end = !explicitDocLangEndCB->isChecked();
2494 int const p = languagePackageCO->currentIndex();
2496 rc.language_package_selection = LyXRC::LP_AUTO;
2498 rc.language_package_selection = LyXRC::LP_BABEL;
2500 rc.language_package_selection = LyXRC::LP_CUSTOM;
2502 rc.language_package_selection = LyXRC::LP_NONE;
2503 rc.language_custom_package = fromqstr(languagePackageED->text());
2504 rc.language_global_options = globalCB->isChecked();
2505 rc.language_command_begin = fromqstr(startCommandED->text());
2506 rc.language_command_end = fromqstr(endCommandED->text());
2507 rc.gui_language = fromqstr(
2508 uiLanguageCO->itemData(uiLanguageCO->currentIndex()).toString());
2509 if (defaultDecimalSepCO->currentIndex() == 0)
2510 rc.default_decimal_sep = "locale";
2512 rc.default_decimal_sep = fromqstr(defaultDecimalSepED->text());
2513 rc.default_length_unit = (Length::UNIT) defaultLengthUnitCO->itemData(defaultLengthUnitCO->currentIndex()).toInt();
2517 void PrefLanguage::updateRC(LyXRC const & rc)
2519 if (rc.visual_cursor)
2520 visualCursorRB->setChecked(true);
2522 logicalCursorRB->setChecked(true);
2523 markForeignCB->setChecked(rc.mark_foreign_language);
2524 respectOSkbdCB->setChecked(rc.respect_os_kbd_language);
2525 explicitDocLangBeginCB->setChecked(!rc.language_auto_begin);
2526 explicitDocLangEndCB->setChecked(!rc.language_auto_end);
2527 languagePackageCO->setCurrentIndex(rc.language_package_selection);
2528 if (languagePackageCO->currentIndex() == 2) {
2529 languagePackageED->setText(toqstr(rc.language_custom_package));
2530 languagePackageED->setEnabled(true);
2532 languagePackageED->clear();
2533 save_langpack_ = toqstr(rc.language_custom_package);
2534 languagePackageED->setEnabled(false);
2536 defaultDecimalSepED->setEnabled(defaultDecimalSepCO->currentIndex() == 1);
2537 globalCB->setChecked(rc.language_global_options);
2538 startCommandED->setText(toqstr(rc.language_command_begin));
2539 endCommandED->setText(toqstr(rc.language_command_end));
2540 if (rc.default_decimal_sep == "locale") {
2541 defaultDecimalSepCO->setCurrentIndex(0);
2542 defaultDecimalSepED->clear();
2544 defaultDecimalSepCO->setCurrentIndex(1);
2545 defaultDecimalSepED->setText(toqstr(rc.default_decimal_sep));
2547 int pos = defaultLengthUnitCO->findData(int(rc.default_length_unit));
2548 defaultLengthUnitCO->setCurrentIndex(pos);
2550 pos = uiLanguageCO->findData(toqstr(rc.gui_language));
2551 uiLanguageCO->blockSignals(true);
2552 uiLanguageCO->setCurrentIndex(pos);
2553 uiLanguageCO->blockSignals(false);
2557 /////////////////////////////////////////////////////////////////////
2559 // PrefUserInterface
2561 /////////////////////////////////////////////////////////////////////
2563 PrefUserInterface::PrefUserInterface(GuiPreferences * form)
2564 : PrefModule(catLookAndFeel, N_("User Interface"), form)
2568 connect(uiFilePB, SIGNAL(clicked()),
2569 this, SLOT(selectUi()));
2570 connect(uiFileED, SIGNAL(textChanged(QString)),
2571 this, SIGNAL(changed()));
2572 connect(iconSetCO, SIGNAL(activated(int)),
2573 this, SIGNAL(changed()));
2574 connect(useSystemThemeIconsCB, SIGNAL(clicked()),
2575 this, SIGNAL(changed()));
2576 connect(lastfilesSB, SIGNAL(valueChanged(int)),
2577 this, SIGNAL(changed()));
2578 connect(tooltipCB, SIGNAL(toggled(bool)),
2579 this, SIGNAL(changed()));
2580 lastfilesSB->setMaximum(maxlastfiles);
2582 iconSetCO->addItem(qt_("Default"), QString());
2583 iconSetCO->addItem(qt_("Classic"), "classic");
2584 iconSetCO->addItem(qt_("Oxygen"), "oxygen");
2586 #if (!(defined Q_WS_X11 || defined(QPA_XCB)) || QT_VERSION < 0x040600)
2587 useSystemThemeIconsCB->hide();
2592 void PrefUserInterface::applyRC(LyXRC & rc) const
2594 rc.icon_set = fromqstr(iconSetCO->itemData(
2595 iconSetCO->currentIndex()).toString());
2597 rc.ui_file = internal_path(fromqstr(uiFileED->text()));
2598 rc.use_system_theme_icons = useSystemThemeIconsCB->isChecked();
2599 rc.num_lastfiles = lastfilesSB->value();
2600 rc.use_tooltip = tooltipCB->isChecked();
2604 void PrefUserInterface::updateRC(LyXRC const & rc)
2606 int iconset = iconSetCO->findData(toqstr(rc.icon_set));
2609 iconSetCO->setCurrentIndex(iconset);
2610 useSystemThemeIconsCB->setChecked(rc.use_system_theme_icons);
2611 uiFileED->setText(toqstr(external_path(rc.ui_file)));
2612 lastfilesSB->setValue(rc.num_lastfiles);
2613 tooltipCB->setChecked(rc.use_tooltip);
2617 void PrefUserInterface::selectUi()
2619 QString file = form_->browseUI(internalPath(uiFileED->text()));
2620 if (!file.isEmpty())
2621 uiFileED->setText(file);
2625 /////////////////////////////////////////////////////////////////////
2627 // PrefDocumentHandling
2629 /////////////////////////////////////////////////////////////////////
2631 PrefDocHandling::PrefDocHandling(GuiPreferences * form)
2632 : PrefModule(catLookAndFeel, N_("Document Handling"), form)
2636 connect(autoSaveCB, SIGNAL(toggled(bool)),
2637 autoSaveSB, SLOT(setEnabled(bool)));
2638 connect(autoSaveCB, SIGNAL(toggled(bool)),
2639 TextLabel1, SLOT(setEnabled(bool)));
2640 connect(openDocumentsInTabsCB, SIGNAL(clicked()),
2641 this, SIGNAL(changed()));
2642 connect(singleInstanceCB, SIGNAL(clicked()),
2643 this, SIGNAL(changed()));
2644 connect(singleCloseTabButtonCB, SIGNAL(clicked()),
2645 this, SIGNAL(changed()));
2646 connect(closeLastViewCO, SIGNAL(activated(int)),
2647 this, SIGNAL(changed()));
2648 connect(restoreCursorCB, SIGNAL(clicked()),
2649 this, SIGNAL(changed()));
2650 connect(loadSessionCB, SIGNAL(clicked()),
2651 this, SIGNAL(changed()));
2652 connect(allowGeometrySessionCB, SIGNAL(clicked()),
2653 this, SIGNAL(changed()));
2654 connect(autoSaveSB, SIGNAL(valueChanged(int)),
2655 this, SIGNAL(changed()));
2656 connect(autoSaveCB, SIGNAL(clicked()),
2657 this, SIGNAL(changed()));
2658 connect(backupCB, SIGNAL(clicked()),
2659 this, SIGNAL(changed()));
2660 connect(saveCompressedCB, SIGNAL(clicked()),
2661 this, SIGNAL(changed()));
2662 connect(saveOriginCB, SIGNAL(clicked()),
2663 this, SIGNAL(changed()));
2667 void PrefDocHandling::applyRC(LyXRC & rc) const
2669 rc.use_lastfilepos = restoreCursorCB->isChecked();
2670 rc.load_session = loadSessionCB->isChecked();
2671 rc.allow_geometry_session = allowGeometrySessionCB->isChecked();
2672 rc.autosave = autoSaveCB->isChecked() ? autoSaveSB->value() * 60 : 0;
2673 rc.make_backup = backupCB->isChecked();
2674 rc.save_compressed = saveCompressedCB->isChecked();
2675 rc.save_origin = saveOriginCB->isChecked();
2676 rc.open_buffers_in_tabs = openDocumentsInTabsCB->isChecked();
2677 rc.single_instance = singleInstanceCB->isChecked();
2678 rc.single_close_tab_button = singleCloseTabButtonCB->isChecked();
2680 switch (closeLastViewCO->currentIndex()) {
2682 rc.close_buffer_with_last_view = "yes";
2685 rc.close_buffer_with_last_view = "no";
2688 rc.close_buffer_with_last_view = "ask";
2696 void PrefDocHandling::updateRC(LyXRC const & rc)
2698 restoreCursorCB->setChecked(rc.use_lastfilepos);
2699 loadSessionCB->setChecked(rc.load_session);
2700 allowGeometrySessionCB->setChecked(rc.allow_geometry_session);
2701 // convert to minutes
2702 bool autosave = rc.autosave > 0;
2703 int mins = rc.autosave / 60;
2706 autoSaveSB->setValue(mins);
2707 autoSaveCB->setChecked(autosave);
2708 autoSaveSB->setEnabled(autosave);
2709 backupCB->setChecked(rc.make_backup);
2710 saveCompressedCB->setChecked(rc.save_compressed);
2711 saveOriginCB->setChecked(rc.save_origin);
2712 openDocumentsInTabsCB->setChecked(rc.open_buffers_in_tabs);
2713 singleInstanceCB->setChecked(rc.single_instance && !rc.lyxpipes.empty());
2714 singleInstanceCB->setEnabled(!rc.lyxpipes.empty());
2715 singleCloseTabButtonCB->setChecked(rc.single_close_tab_button);
2716 if (rc.close_buffer_with_last_view == "yes")
2717 closeLastViewCO->setCurrentIndex(0);
2718 else if (rc.close_buffer_with_last_view == "no")
2719 closeLastViewCO->setCurrentIndex(1);
2720 else if (rc.close_buffer_with_last_view == "ask")
2721 closeLastViewCO->setCurrentIndex(2);
2725 void PrefDocHandling::on_clearSessionPB_clicked()
2727 guiApp->clearSession();
2732 /////////////////////////////////////////////////////////////////////
2736 /////////////////////////////////////////////////////////////////////
2738 PrefEdit::PrefEdit(GuiPreferences * form)
2739 : PrefModule(catEditing, N_("Control"), form)
2743 connect(cursorFollowsCB, SIGNAL(clicked()),
2744 this, SIGNAL(changed()));
2745 connect(scrollBelowCB, SIGNAL(clicked()),
2746 this, SIGNAL(changed()));
2747 connect(macLikeCursorMovementCB, SIGNAL(clicked()),
2748 this, SIGNAL(changed()));
2749 connect(copyCTMarkupCB, SIGNAL(clicked()),
2750 this, SIGNAL(changed()));
2751 connect(sortEnvironmentsCB, SIGNAL(clicked()),
2752 this, SIGNAL(changed()));
2753 connect(groupEnvironmentsCB, SIGNAL(clicked()),
2754 this, SIGNAL(changed()));
2755 connect(macroEditStyleCO, SIGNAL(activated(int)),
2756 this, SIGNAL(changed()));
2757 connect(cursorWidthSB, SIGNAL(valueChanged(int)),
2758 this, SIGNAL(changed()));
2759 connect(citationSearchLE, SIGNAL(textChanged(QString)),
2760 this, SIGNAL(changed()));
2761 connect(fullscreenWidthSB, SIGNAL(valueChanged(int)),
2762 this, SIGNAL(changed()));
2763 connect(toggleTabbarCB, SIGNAL(toggled(bool)),
2764 this, SIGNAL(changed()));
2765 connect(toggleMenubarCB, SIGNAL(toggled(bool)),
2766 this, SIGNAL(changed()));
2767 connect(toggleScrollbarCB, SIGNAL(toggled(bool)),
2768 this, SIGNAL(changed()));
2769 connect(toggleStatusbarCB, SIGNAL(toggled(bool)),
2770 this, SIGNAL(changed()));
2771 connect(toggleToolbarsCB, SIGNAL(toggled(bool)),
2772 this, SIGNAL(changed()));
2776 void PrefEdit::on_fullscreenLimitCB_toggled(bool const state)
2778 fullscreenWidthSB->setEnabled(state);
2779 fullscreenWidthLA->setEnabled(state);
2784 void PrefEdit::on_citationSearchCB_toggled(bool const state)
2786 citationSearchLE->setEnabled(state);
2787 citationSearchLA->setEnabled(state);
2792 void PrefEdit::applyRC(LyXRC & rc) const
2794 rc.cursor_follows_scrollbar = cursorFollowsCB->isChecked();
2795 rc.scroll_below_document = scrollBelowCB->isChecked();
2796 rc.mac_like_cursor_movement = macLikeCursorMovementCB->isChecked();
2797 rc.ct_markup_copied = copyCTMarkupCB->isChecked();
2798 rc.sort_layouts = sortEnvironmentsCB->isChecked();
2799 rc.group_layouts = groupEnvironmentsCB->isChecked();
2800 switch (macroEditStyleCO->currentIndex()) {
2801 case 0: rc.macro_edit_style = LyXRC::MACRO_EDIT_INLINE_BOX; break;
2802 case 1: rc.macro_edit_style = LyXRC::MACRO_EDIT_INLINE; break;
2803 case 2: rc.macro_edit_style = LyXRC::MACRO_EDIT_LIST; break;
2805 rc.cursor_width = cursorWidthSB->value();
2806 rc.citation_search = citationSearchCB->isChecked();
2807 rc.citation_search_pattern = fromqstr(citationSearchLE->text());
2808 rc.full_screen_toolbars = toggleToolbarsCB->isChecked();
2809 rc.full_screen_scrollbar = toggleScrollbarCB->isChecked();
2810 rc.full_screen_statusbar = toggleStatusbarCB->isChecked();
2811 rc.full_screen_tabbar = toggleTabbarCB->isChecked();
2812 rc.full_screen_menubar = toggleMenubarCB->isChecked();
2813 rc.full_screen_width = fullscreenWidthSB->value();
2814 rc.full_screen_limit = fullscreenLimitCB->isChecked();
2818 void PrefEdit::updateRC(LyXRC const & rc)
2820 cursorFollowsCB->setChecked(rc.cursor_follows_scrollbar);
2821 scrollBelowCB->setChecked(rc.scroll_below_document);
2822 macLikeCursorMovementCB->setChecked(rc.mac_like_cursor_movement);
2823 copyCTMarkupCB->setChecked(rc.ct_markup_copied);
2824 sortEnvironmentsCB->setChecked(rc.sort_layouts);
2825 groupEnvironmentsCB->setChecked(rc.group_layouts);
2826 macroEditStyleCO->setCurrentIndex(rc.macro_edit_style);
2827 cursorWidthSB->setValue(rc.cursor_width);
2828 citationSearchCB->setChecked(rc.citation_search);
2829 citationSearchLE->setText(toqstr(rc.citation_search_pattern));
2830 citationSearchLE->setEnabled(rc.citation_search);
2831 citationSearchLA->setEnabled(rc.citation_search);
2832 toggleScrollbarCB->setChecked(rc.full_screen_scrollbar);
2833 toggleStatusbarCB->setChecked(rc.full_screen_statusbar);
2834 toggleToolbarsCB->setChecked(rc.full_screen_toolbars);
2835 toggleTabbarCB->setChecked(rc.full_screen_tabbar);
2836 toggleMenubarCB->setChecked(rc.full_screen_menubar);
2837 fullscreenWidthSB->setValue(rc.full_screen_width);
2838 fullscreenLimitCB->setChecked(rc.full_screen_limit);
2839 fullscreenWidthSB->setEnabled(rc.full_screen_limit);
2840 fullscreenWidthLA->setEnabled(rc.full_screen_limit);
2844 /////////////////////////////////////////////////////////////////////
2848 /////////////////////////////////////////////////////////////////////
2851 GuiShortcutDialog::GuiShortcutDialog(QWidget * parent) : QDialog(parent)
2853 Ui::shortcutUi::setupUi(this);
2854 QDialog::setModal(true);
2855 lfunLE->setValidator(new NoNewLineValidator(lfunLE));
2859 PrefShortcuts::PrefShortcuts(GuiPreferences * form)
2860 : PrefModule(catEditing, N_("Shortcuts"), form),
2861 editItem_(nullptr), mathItem_(nullptr), bufferItem_(nullptr), layoutItem_(nullptr),
2862 systemItem_(nullptr)
2866 shortcutsTW->setColumnCount(2);
2867 shortcutsTW->headerItem()->setText(0, qt_("Function"));
2868 shortcutsTW->headerItem()->setText(1, qt_("Shortcut"));
2869 shortcutsTW->setSortingEnabled(true);
2870 // Multi-selection can be annoying.
2871 // shortcutsTW->setSelectionMode(QAbstractItemView::MultiSelection);
2873 connect(bindFilePB, SIGNAL(clicked()),
2874 this, SLOT(selectBind()));
2875 connect(bindFileED, SIGNAL(textChanged(QString)),
2876 this, SIGNAL(changed()));
2878 shortcut_ = new GuiShortcutDialog(this);
2879 shortcut_bc_.setPolicy(ButtonPolicy::OkCancelPolicy);
2880 shortcut_bc_.setOK(shortcut_->buttonBox->button(QDialogButtonBox::Ok));
2881 shortcut_bc_.setCancel(shortcut_->buttonBox->button(QDialogButtonBox::Cancel));
2883 connect(shortcut_->buttonBox, SIGNAL(accepted()),
2884 this, SIGNAL(changed()));
2885 connect(shortcut_->buttonBox, SIGNAL(rejected()),
2886 shortcut_, SLOT(reject()));
2887 connect(shortcut_->clearPB, SIGNAL(clicked()),
2888 this, SLOT(shortcutClearPressed()));
2889 connect(shortcut_->removePB, SIGNAL(clicked()),
2890 this, SLOT(shortcutRemovePressed()));
2891 connect(shortcut_->buttonBox, SIGNAL(accepted()),
2892 this, SLOT(shortcutOkPressed()));
2893 connect(shortcut_->buttonBox, SIGNAL(rejected()),
2894 this, SLOT(shortcutCancelPressed()));
2898 void PrefShortcuts::applyRC(LyXRC & rc) const
2900 rc.bind_file = internal_path(fromqstr(bindFileED->text()));
2901 // write user_bind and user_unbind to .lyx/bind/user.bind
2902 FileName bind_dir(addPath(package().user_support().absFileName(), "bind"));
2903 if (!bind_dir.exists() && !bind_dir.createDirectory(0777)) {
2904 lyxerr << "LyX could not create the user bind directory '"
2905 << bind_dir << "'. All user-defined key bindings will be lost." << endl;
2908 if (!bind_dir.isDirWritable()) {
2909 lyxerr << "LyX could not write to the user bind directory '"
2910 << bind_dir << "'. All user-defined key bindings will be lost." << endl;
2913 FileName user_bind_file(bind_dir.absFileName() + "/user.bind");
2914 user_unbind_.write(user_bind_file.toFilesystemEncoding(), false, true);
2915 user_bind_.write(user_bind_file.toFilesystemEncoding(), true, false);
2916 // immediately apply the keybindings. Why this is not done before?
2917 // The good thing is that the menus are updated automatically.
2918 theTopLevelKeymap().clear();
2919 theTopLevelKeymap().read("site");
2920 theTopLevelKeymap().read(rc.bind_file, nullptr, KeyMap::Fallback);
2921 theTopLevelKeymap().read("user", nullptr, KeyMap::MissingOK);
2925 void PrefShortcuts::updateRC(LyXRC const & rc)
2927 bindFileED->setText(toqstr(external_path(rc.bind_file)));
2929 system_bind_.clear();
2931 user_unbind_.clear();
2932 system_bind_.read("site");
2933 system_bind_.read(rc.bind_file);
2934 // \unbind in user.bind is added to user_unbind_
2935 user_bind_.read("user", &user_unbind_, KeyMap::MissingOK);
2936 updateShortcutsTW();
2940 void PrefShortcuts::updateShortcutsTW()
2942 shortcutsTW->clear();
2944 editItem_ = new QTreeWidgetItem(shortcutsTW);
2945 editItem_->setText(0, qt_("Cursor, Mouse and Editing Functions"));
2946 editItem_->setFlags(editItem_->flags() & ~Qt::ItemIsSelectable);
2948 mathItem_ = new QTreeWidgetItem(shortcutsTW);
2949 mathItem_->setText(0, qt_("Mathematical Symbols"));
2950 mathItem_->setFlags(mathItem_->flags() & ~Qt::ItemIsSelectable);
2952 bufferItem_ = new QTreeWidgetItem(shortcutsTW);
2953 bufferItem_->setText(0, qt_("Document and Window"));
2954 bufferItem_->setFlags(bufferItem_->flags() & ~Qt::ItemIsSelectable);
2956 layoutItem_ = new QTreeWidgetItem(shortcutsTW);
2957 layoutItem_->setText(0, qt_("Font, Layouts and Textclasses"));
2958 layoutItem_->setFlags(layoutItem_->flags() & ~Qt::ItemIsSelectable);
2960 systemItem_ = new QTreeWidgetItem(shortcutsTW);
2961 systemItem_->setText(0, qt_("System and Miscellaneous"));
2962 systemItem_->setFlags(systemItem_->flags() & ~Qt::ItemIsSelectable);
2964 // listBindings(unbound=true) lists all bound and unbound lfuns
2965 // Items in this list is tagged by its source.
2966 KeyMap::BindingList bindinglist = system_bind_.listBindings(true,
2968 KeyMap::BindingList user_bindinglist = user_bind_.listBindings(false,
2970 KeyMap::BindingList user_unbindinglist = user_unbind_.listBindings(false,
2971 KeyMap::UserUnbind);
2972 bindinglist.insert(bindinglist.end(), user_bindinglist.begin(),
2973 user_bindinglist.end());
2974 bindinglist.insert(bindinglist.end(), user_unbindinglist.begin(),
2975 user_unbindinglist.end());
2977 KeyMap::BindingList::const_iterator it = bindinglist.begin();
2978 KeyMap::BindingList::const_iterator it_end = bindinglist.end();
2979 for (; it != it_end; ++it)
2980 insertShortcutItem(it->request, it->sequence, it->tag);
2982 shortcutsTW->sortItems(0, Qt::AscendingOrder);
2983 on_shortcutsTW_itemSelectionChanged();
2984 on_searchLE_textEdited();
2985 shortcutsTW->resizeColumnToContents(0);
2990 KeyMap::ItemType PrefShortcuts::itemType(QTreeWidgetItem & item)
2992 return static_cast<KeyMap::ItemType>(item.data(0, Qt::UserRole).toInt());
2997 bool PrefShortcuts::isAlwaysHidden(QTreeWidgetItem & item)
2999 // Hide rebound system settings that are empty
3000 return itemType(item) == KeyMap::UserUnbind && item.text(1).isEmpty();
3004 void PrefShortcuts::setItemType(QTreeWidgetItem * item, KeyMap::ItemType tag)
3006 item->setData(0, Qt::UserRole, QVariant(tag));
3010 case KeyMap::System:
3012 case KeyMap::UserBind:
3015 case KeyMap::UserUnbind:
3016 font.setStrikeOut(true);
3018 // this item is not displayed now.
3019 case KeyMap::UserExtraUnbind:
3020 font.setStrikeOut(true);
3023 item->setHidden(isAlwaysHidden(*item));
3024 item->setFont(1, font);
3028 QTreeWidgetItem * PrefShortcuts::insertShortcutItem(FuncRequest const & lfun,
3029 KeySequence const & seq, KeyMap::ItemType tag)
3031 FuncCode const action = lfun.action();
3032 string const action_name = lyxaction.getActionName(action);
3033 QString const lfun_name = toqstr(from_utf8(action_name)
3034 + ' ' + lfun.argument());
3035 QString const shortcut = toqstr(seq.print(KeySequence::ForGui));
3037 QTreeWidgetItem * newItem = nullptr;
3038 // for unbind items, try to find an existing item in the system bind list
3039 if (tag == KeyMap::UserUnbind) {
3040 QList<QTreeWidgetItem*> const items = shortcutsTW->findItems(lfun_name,
3041 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 0);
3042 for (auto const & item : items) {
3043 if (item->text(1) == shortcut) {
3048 // if not found, this unbind item is KeyMap::UserExtraUnbind
3049 // Such an item is not displayed to avoid confusion (what is
3050 // unmatched removed?).
3056 switch(lyxaction.getActionType(action)) {
3057 case LyXAction::Hidden:
3059 case LyXAction::Edit:
3060 newItem = new QTreeWidgetItem(editItem_);
3062 case LyXAction::Math:
3063 newItem = new QTreeWidgetItem(mathItem_);
3065 case LyXAction::Buffer:
3066 newItem = new QTreeWidgetItem(bufferItem_);
3068 case LyXAction::Layout:
3069 newItem = new QTreeWidgetItem(layoutItem_);
3071 case LyXAction::System:
3072 newItem = new QTreeWidgetItem(systemItem_);
3075 // this should not happen
3076 newItem = new QTreeWidgetItem(shortcutsTW);
3080 newItem->setText(0, lfun_name);
3081 newItem->setText(1, shortcut);
3082 // record BindFile representation to recover KeySequence when needed.
3083 newItem->setData(1, Qt::UserRole, toqstr(seq.print(KeySequence::BindFile)));
3084 setItemType(newItem, tag);
3089 void PrefShortcuts::on_shortcutsTW_itemSelectionChanged()
3091 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
3092 removePB->setEnabled(!items.isEmpty() && !items[0]->text(1).isEmpty());
3093 modifyPB->setEnabled(!items.isEmpty());
3094 if (items.isEmpty())
3097 if (itemType(*items[0]) == KeyMap::UserUnbind)
3098 removePB->setText(qt_("Res&tore"));
3100 removePB->setText(qt_("Remo&ve"));
3104 void PrefShortcuts::on_shortcutsTW_itemDoubleClicked()
3110 void PrefShortcuts::modifyShortcut()
3112 QTreeWidgetItem * item = shortcutsTW->currentItem();
3113 if (item->flags() & Qt::ItemIsSelectable) {
3114 shortcut_->lfunLE->setText(item->text(0));
3115 save_lfun_ = item->text(0).trimmed();
3116 shortcut_->shortcutWG->setText(item->text(1));
3118 seq.parse(fromqstr(item->data(1, Qt::UserRole).toString()));
3119 shortcut_->shortcutWG->setKeySequence(seq);
3120 shortcut_->shortcutWG->setFocus();
3126 void PrefShortcuts::unhideEmpty(QString const & lfun, bool select)
3128 // list of items that match lfun
3129 QList<QTreeWidgetItem*> items = shortcutsTW->findItems(lfun,
3130 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 0);
3131 for (auto const & item : items) {
3132 if (isAlwaysHidden(*item)) {
3133 setItemType(item, KeyMap::System);
3135 shortcutsTW->setCurrentItem(item);
3142 void PrefShortcuts::removeShortcut()
3144 // it seems that only one item can be selected, but I am
3145 // removing all selected items anyway.
3146 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
3147 for (auto & item : items) {
3148 string shortcut = fromqstr(item->data(1, Qt::UserRole).toString());
3149 string lfun = fromqstr(item->text(0));
3150 FuncRequest func = lyxaction.lookupFunc(lfun);
3152 switch (itemType(*item)) {
3153 case KeyMap::System: {
3154 // for system bind, we do not touch the item
3155 // but add an user unbind item
3156 user_unbind_.bind(shortcut, func);
3157 setItemType(item, KeyMap::UserUnbind);
3158 removePB->setText(qt_("Res&tore"));
3161 case KeyMap::UserBind: {
3162 // for user_bind, we remove this bind
3163 QTreeWidgetItem * parent = item->parent();
3164 int itemIdx = parent->indexOfChild(item);
3165 parent->takeChild(itemIdx);
3167 shortcutsTW->scrollToItem(parent->child(itemIdx - 1));
3169 shortcutsTW->scrollToItem(parent);
3170 user_bind_.unbind(shortcut, func);
3171 // If this user binding hid an empty system binding, unhide the
3172 // latter and select it.
3173 unhideEmpty(item->text(0), true);
3176 case KeyMap::UserUnbind: {
3177 // for user_unbind, we remove the unbind, and the item
3178 // become KeyMap::System again.
3180 seq.parse(shortcut);
3181 // Ask the user to replace current binding
3182 if (!validateNewShortcut(func, seq, QString()))
3184 user_unbind_.unbind(shortcut, func);
3185 setItemType(item, KeyMap::System);
3186 removePB->setText(qt_("Remo&ve"));
3189 case KeyMap::UserExtraUnbind: {
3190 // for user unbind that is not in system bind file,
3191 // remove this unbind file
3192 QTreeWidgetItem * parent = item->parent();
3193 parent->takeChild(parent->indexOfChild(item));
3194 user_unbind_.unbind(shortcut, func);
3201 void PrefShortcuts::deactivateShortcuts(QList<QTreeWidgetItem*> const & items)
3203 for (auto item : items) {
3204 string shortcut = fromqstr(item->data(1, Qt::UserRole).toString());
3205 string lfun = fromqstr(item->text(0));
3206 FuncRequest func = lyxaction.lookupFunc(lfun);
3208 switch (itemType(*item)) {
3209 case KeyMap::System:
3210 // for system bind, we do not touch the item
3211 // but add an user unbind item
3212 user_unbind_.bind(shortcut, func);
3213 setItemType(item, KeyMap::UserUnbind);
3216 case KeyMap::UserBind: {
3217 // for user_bind, we remove this bind
3218 QTreeWidgetItem * parent = item->parent();
3219 int itemIdx = parent->indexOfChild(item);
3220 parent->takeChild(itemIdx);
3221 user_bind_.unbind(shortcut, func);
3222 unhideEmpty(item->text(0), false);
3232 void PrefShortcuts::selectBind()
3234 QString file = form_->browsebind(internalPath(bindFileED->text()));
3235 if (!file.isEmpty()) {
3236 bindFileED->setText(file);
3237 system_bind_ = KeyMap();
3238 system_bind_.read(fromqstr(file));
3239 updateShortcutsTW();
3244 void PrefShortcuts::on_modifyPB_pressed()
3250 void PrefShortcuts::on_newPB_pressed()
3252 shortcut_->lfunLE->clear();
3253 shortcut_->shortcutWG->reset();
3254 save_lfun_ = QString();
3259 void PrefShortcuts::on_removePB_pressed()
3266 void PrefShortcuts::on_searchLE_textEdited()
3268 if (searchLE->text().isEmpty()) {
3269 // show all hidden items
3270 QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Hidden);
3272 (*it)->setHidden(isAlwaysHidden(**it));
3273 // close all categories
3274 for (int i = 0; i < shortcutsTW->topLevelItemCount(); ++i)
3275 shortcutsTW->collapseItem(shortcutsTW->topLevelItem(i));
3278 // search both columns
3279 QList<QTreeWidgetItem *> matched = shortcutsTW->findItems(searchLE->text(),
3280 Qt::MatchFlags(Qt::MatchContains | Qt::MatchRecursive), 0);
3281 matched += shortcutsTW->findItems(searchLE->text(),
3282 Qt::MatchFlags(Qt::MatchContains | Qt::MatchRecursive), 1);
3284 // hide everyone (to avoid searching in matched QList repeatedly
3285 QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Selectable);
3287 (*it++)->setHidden(true);
3288 // show matched items
3289 for (auto & item : matched)
3290 if (!isAlwaysHidden(*item)) {
3291 item->setHidden(false);
3293 item->parent()->setExpanded(true);
3298 docstring makeCmdString(FuncRequest const & f)
3300 docstring actionStr = from_ascii(lyxaction.getActionName(f.action()));
3301 if (!f.argument().empty())
3302 actionStr += " " + f.argument();
3307 FuncRequest PrefShortcuts::currentBinding(KeySequence const & k)
3309 FuncRequest res = user_bind_.getBinding(k);
3310 if (res.action() != LFUN_UNKNOWN_ACTION)
3312 res = system_bind_.getBinding(k);
3313 // Check if it is unbound. Note: user_unbind_ can only unbind one
3314 // FuncRequest per key sequence.
3315 if (user_unbind_.getBinding(k) == res)
3316 return FuncRequest::unknown;
3321 bool PrefShortcuts::validateNewShortcut(FuncRequest const & func,
3322 KeySequence const & k,
3323 QString const & lfun_to_modify)
3325 if (func.action() == LFUN_UNKNOWN_ACTION) {
3326 Alert::error(_("Failed to create shortcut"),
3327 _("Unknown or invalid LyX function"));
3331 // It is not currently possible to bind Hidden lfuns such as self-insert. In
3332 // the future, to remove this limitation, see GuiPrefs::insertShortcutItem
3333 // and how it is used in GuiPrefs::shortcutOkPressed.
3334 if (lyxaction.getActionType(func.action()) == LyXAction::Hidden) {
3335 Alert::error(_("Failed to create shortcut"),
3336 _("This LyX function is hidden and cannot be bound."));
3340 if (k.length() == 0) {
3341 Alert::error(_("Failed to create shortcut"),
3342 _("Invalid or empty key sequence"));
3346 FuncRequest oldBinding = currentBinding(k);
3347 if (oldBinding == func)
3348 // nothing to change
3351 // make sure this key isn't already bound---and, if so, prompt user
3352 // (exclude the lfun the user already wants to modify)
3353 docstring const action_string = makeCmdString(oldBinding);
3354 if (oldBinding.action() != LFUN_UNKNOWN_ACTION
3355 && lfun_to_modify != toqstr(action_string)) {
3356 docstring const new_action_string = makeCmdString(func);
3357 docstring const text = bformat(_("Shortcut `%1$s' is already bound to "
3359 "Are you sure you want to unbind the "
3360 "current shortcut and bind it to %3$s?"),
3361 k.print(KeySequence::ForGui), action_string,
3363 int ret = Alert::prompt(_("Redefine shortcut?"),
3364 text, 0, 1, _("&Redefine"), _("&Cancel"));
3367 QString const sequence_text = toqstr(k.print(KeySequence::ForGui));
3368 QList<QTreeWidgetItem*> items = shortcutsTW->findItems(sequence_text,
3369 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 1);
3370 deactivateShortcuts(items);
3376 void PrefShortcuts::shortcutOkPressed()
3378 QString const new_lfun = shortcut_->lfunLE->text();
3379 FuncRequest func = lyxaction.lookupFunc(fromqstr(new_lfun));
3380 KeySequence k = shortcut_->shortcutWG->getKeySequence();
3382 // save_lfun_ contains the text of the lfun to modify, if the user clicked
3383 // "modify", or is empty if they clicked "new" (which I do not really like)
3384 if (!validateNewShortcut(func, k, save_lfun_))
3387 if (!save_lfun_.isEmpty()) {
3388 // real modification of the lfun's shortcut,
3389 // so remove the previous one
3390 QList<QTreeWidgetItem*> to_modify = shortcutsTW->selectedItems();
3391 deactivateShortcuts(to_modify);
3394 shortcut_->accept();
3396 QTreeWidgetItem * item = insertShortcutItem(func, k, KeyMap::UserBind);
3398 user_bind_.bind(&k, func);
3399 shortcutsTW->sortItems(0, Qt::AscendingOrder);
3400 item->parent()->setExpanded(true);
3401 shortcutsTW->setCurrentItem(item);
3402 shortcutsTW->scrollToItem(item);
3404 Alert::error(_("Failed to create shortcut"),
3405 _("Can not insert shortcut to the list"));
3411 void PrefShortcuts::shortcutCancelPressed()
3413 shortcut_->shortcutWG->reset();
3417 void PrefShortcuts::shortcutClearPressed()
3419 shortcut_->shortcutWG->reset();
3423 void PrefShortcuts::shortcutRemovePressed()
3425 shortcut_->shortcutWG->removeFromSequence();
3429 /////////////////////////////////////////////////////////////////////
3433 /////////////////////////////////////////////////////////////////////
3435 PrefIdentity::PrefIdentity(GuiPreferences * form)
3436 : PrefModule(QString(), N_("Identity"), form)
3440 connect(nameED, SIGNAL(textChanged(QString)),
3441 this, SIGNAL(changed()));
3442 connect(emailED, SIGNAL(textChanged(QString)),
3443 this, SIGNAL(changed()));
3444 connect(initialsED, SIGNAL(textChanged(QString)),
3445 this, SIGNAL(changed()));
3447 nameED->setValidator(new NoNewLineValidator(nameED));
3448 emailED->setValidator(new NoNewLineValidator(emailED));
3449 initialsED->setValidator(new NoNewLineValidator(initialsED));
3453 void PrefIdentity::applyRC(LyXRC & rc) const
3455 rc.user_name = fromqstr(nameED->text());
3456 rc.user_email = fromqstr(emailED->text());
3457 rc.user_initials = fromqstr(initialsED->text());
3461 void PrefIdentity::updateRC(LyXRC const & rc)
3463 nameED->setText(toqstr(rc.user_name));
3464 emailED->setText(toqstr(rc.user_email));
3465 initialsED->setText(toqstr(rc.user_initials));
3470 /////////////////////////////////////////////////////////////////////
3474 /////////////////////////////////////////////////////////////////////
3476 GuiPreferences::GuiPreferences(GuiView & lv)
3477 : GuiDialog(lv, "prefs", qt_("Preferences"))
3481 QDialog::setModal(false);
3483 connect(buttonBox, SIGNAL(clicked(QAbstractButton *)),
3484 this, SLOT(slotButtonBox(QAbstractButton *)));
3486 addModule(new PrefUserInterface(this));
3487 addModule(new PrefDocHandling(this));
3488 addModule(new PrefEdit(this));
3489 addModule(new PrefShortcuts(this));
3490 PrefScreenFonts * screenfonts = new PrefScreenFonts(this);
3491 connect(this, SIGNAL(prefsApplied(LyXRC const &)),
3492 screenfonts, SLOT(updateScreenFontSizes(LyXRC const &)));
3493 addModule(screenfonts);
3494 addModule(new PrefColors(this));
3495 addModule(new PrefDisplay(this));
3496 addModule(new PrefInput(this));
3497 addModule(new PrefCompletion(this));
3499 addModule(new PrefPaths(this));
3501 addModule(new PrefIdentity(this));
3503 addModule(new PrefLanguage(this));
3504 addModule(new PrefSpellchecker(this));
3506 PrefOutput * output = new PrefOutput(this);
3508 addModule(new PrefLatex(this));
3510 PrefConverters * converters = new PrefConverters(this);
3511 PrefFileformats * formats = new PrefFileformats(this);
3512 connect(formats, SIGNAL(formatsChanged()),
3513 converters, SLOT(updateGui()));
3514 addModule(converters);
3517 prefsPS->setCurrentPanel("User Interface");
3518 // FIXME: hack to work around resizing bug in Qt >= 4.2
3519 // bug verified with Qt 4.2.{0-3} (JSpitzm)
3520 #if QT_VERSION >= 0x040200
3521 prefsPS->updateGeometry();
3524 bc().setPolicy(ButtonPolicy::PreferencesPolicy);
3525 bc().setOK(buttonBox->button(QDialogButtonBox::Ok));
3526 bc().setApply(buttonBox->button(QDialogButtonBox::Apply));
3527 bc().setCancel(buttonBox->button(QDialogButtonBox::Cancel));
3528 bc().setRestore(buttonBox->button(QDialogButtonBox::Reset));
3530 guilyxfiles_ = new GuiLyXFiles(lv);
3531 connect(guilyxfiles_, SIGNAL(fileSelected(QString)),
3532 this, SLOT(slotFileSelected(QString)));
3536 void GuiPreferences::addModule(PrefModule * module)
3538 LASSERT(module, return);
3539 if (module->category().isEmpty())
3540 prefsPS->addPanel(module, module->title());
3542 prefsPS->addPanel(module, module->title(), module->category());
3543 connect(module, SIGNAL(changed()), this, SLOT(change_adaptor()));
3544 modules_.push_back(module);
3548 void GuiPreferences::change_adaptor()
3554 void GuiPreferences::applyRC(LyXRC & rc) const
3556 size_t end = modules_.size();
3557 for (size_t i = 0; i != end; ++i)
3558 modules_[i]->applyRC(rc);
3562 void GuiPreferences::updateRC(LyXRC const & rc)
3564 size_t const end = modules_.size();
3565 for (size_t i = 0; i != end; ++i)
3566 modules_[i]->updateRC(rc);
3570 void GuiPreferences::applyView()
3576 bool GuiPreferences::initialiseParams(string const &)
3579 formats_ = theFormats();
3580 converters_ = theConverters();
3581 converters_.update(formats_);
3582 movers_ = theMovers();
3586 // Make sure that the bc is in the INITIAL state
3587 if (bc().policy().buttonStatus(ButtonPolicy::RESTORE))
3594 void GuiPreferences::dispatchParams()
3597 rc_.write(ss, true);
3598 dispatch(FuncRequest(LFUN_LYXRC_APPLY, ss.str()));
3599 // issue prefsApplied signal. This will update the
3600 // localized screen font sizes.
3602 // FIXME: these need lfuns
3604 Author const & author =
3605 Author(from_utf8(rc_.user_name), from_utf8(rc_.user_email),
3606 from_utf8(rc_.user_initials));
3607 theBufferList().recordCurrentAuthor(author);
3609 theFormats() = formats_;
3611 theConverters() = converters_;
3612 theConverters().update(formats_);
3613 theConverters().buildGraph();
3614 theBufferList().invalidateConverterCache();
3616 theMovers() = movers_;
3618 for (string const & color : colors_)
3619 dispatch(FuncRequest(LFUN_SET_COLOR, color));
3623 if (!tempSaveCB->isChecked())
3624 dispatch(FuncRequest(LFUN_PREFERENCES_SAVE));
3628 void GuiPreferences::setColor(ColorCode col, QString const & hex)
3630 colors_.push_back(lcolor.getLyXName(col) + ' ' + fromqstr(hex));
3634 void GuiPreferences::slotFileSelected(QString const file)
3640 QString GuiPreferences::browseLibFile(QString const & dir,
3641 QString const & name, QString const & ext)
3645 guilyxfiles_->passParams(fromqstr(dir));
3646 guilyxfiles_->selectItem(name);
3647 guilyxfiles_->exec();
3649 QString const result = uifile_;
3651 // remove the extension if it is the default one
3652 QString noextresult;
3653 if (getExtension(result) == ext)
3654 noextresult = removeExtension(result);
3656 noextresult = result;
3658 // remove the directory, if it is the default one
3659 QString const file = onlyFileName(noextresult);
3660 if (toqstr(libFileSearch(dir, file, ext).absFileName()) == result)
3667 QString GuiPreferences::browsebind(QString const & file)
3669 return browseLibFile("bind", file, "bind");
3673 QString GuiPreferences::browseUI(QString const & file)
3675 return browseLibFile("ui", file, "ui");
3679 QString GuiPreferences::browsekbmap(QString const & file)
3681 return browseLibFile("kbd", file, "kmap");
3685 QString GuiPreferences::browse(QString const & file,
3686 QString const & title) const
3688 return browseFile(file, title, QStringList(), true);
3692 Dialog * createGuiPreferences(GuiView & lv) { return new GuiPreferences(lv); }
3695 } // namespace frontend
3698 #include "moc_GuiPrefs.cpp"