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