3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
9 * Full author contact details are available in file CREDITS.
16 #include "ColorCache.h"
17 #include "FileDialog.h"
18 #include "GuiApplication.h"
19 #include "GuiFontExample.h"
20 #include "GuiFontLoader.h"
21 #include "GuiKeySymbol.h"
22 #include "qt_helpers.h"
23 #include "Validator.h"
26 #include "BufferList.h"
29 #include "ConverterCache.h"
30 #include "FontEnums.h"
31 #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 /** Wrapper around browseFile which tries to provide a filename
129 * relative to the user or system directory. The dir, name and ext
130 * parameters have the same meaning as in the
131 * support::LibFileSearch function.
133 QString browseLibFile(QString const & dir,
134 QString const & name,
136 QString const & title,
137 QStringList const & filters)
140 QString const label1 = qt_("&System files");
142 toqstr(addName(package().system_support().absFileName(), fromqstr(dir)));
144 QString const label2 = qt_("&User files");
146 toqstr(addName(package().user_support().absFileName(), fromqstr(dir)));
148 QString const result = browseFile(toqstr(
149 libFileSearch(dir, name, ext).absFileName()),
150 title, filters, false, dir1, dir2, QString(), QString(), dir1);
152 // remove the extension if it is the default one
154 if (getExtension(result) == ext)
155 noextresult = removeExtension(result);
157 noextresult = result;
159 // remove the directory, if it is the default one
160 QString const file = onlyFileName(noextresult);
161 if (toqstr(libFileSearch(dir, file, ext).absFileName()) == result)
168 /** Launch a file dialog and return the chosen directory.
169 pathname: a suggested pathname.
170 title: the title of the dialog.
171 dir1 = (name, dir), dir2 = (name, dir): extra buttons on the dialog.
173 QString browseDir(QString const & pathname,
174 QString const & title,
175 QString const & label1 = QString(),
176 QString const & dir1 = QString(),
177 QString const & label2 = QString(),
178 QString const & dir2 = QString())
180 QString lastPath = ".";
181 if (!pathname.isEmpty())
182 lastPath = onlyPath(pathname);
184 FileDialog dlg(title);
185 dlg.setButton1(label1, dir1);
186 dlg.setButton2(label2, dir2);
188 FileDialog::Result const result =
189 dlg.opendir(lastPath, onlyFileName(pathname));
191 return result.second;
195 } // namespace frontend
198 QString browseRelToParent(QString const & filename, QString const & relpath,
199 QString const & title, QStringList const & filters, bool save,
200 QString const & label1, QString const & dir1,
201 QString const & label2, QString const & dir2)
203 QString const fname = makeAbsPath(filename, relpath);
205 QString const outname =
206 frontend::browseFile(fname, title, filters, save, label1, dir1, label2, dir2);
208 QString const reloutname =
209 toqstr(makeRelPath(qstring_to_ucs4(outname), qstring_to_ucs4(relpath)));
211 if (reloutname.startsWith("../"))
218 QString browseRelToSub(QString const & filename, QString const & relpath,
219 QString const & title, QStringList const & filters, bool save,
220 QString const & label1, QString const & dir1,
221 QString const & label2, QString const & dir2)
223 QString const fname = makeAbsPath(filename, relpath);
225 QString const outname =
226 frontend::browseFile(fname, title, filters, save, label1, dir1, label2, dir2);
228 QString const reloutname =
229 toqstr(makeRelPath(qstring_to_ucs4(outname), qstring_to_ucs4(relpath)));
231 QString testname = reloutname;
232 testname.remove(QRegExp("^(\\.\\./)+"));
234 if (testname.contains("/"))
242 /////////////////////////////////////////////////////////////////////
246 /////////////////////////////////////////////////////////////////////
250 QString const catLookAndFeel = N_("Look & Feel");
251 QString const catEditing = N_("Editing");
252 QString const catLanguage = N_("Language Settings");
253 QString const catOutput = N_("Output");
254 QString const catFiles = N_("File Handling");
256 static void parseFontName(QString const & mangled0,
257 string & name, string & foundry)
259 string mangled = fromqstr(mangled0);
260 size_t const idx = mangled.find('[');
261 if (idx == string::npos || idx == 0) {
265 name = mangled.substr(0, idx - 1),
266 foundry = mangled.substr(idx + 1, mangled.size() - idx - 2);
271 static void setComboxFont(QComboBox * cb, string const & family,
272 string const & foundry)
274 QString fontname = toqstr(family);
275 if (!foundry.empty())
276 fontname += " [" + toqstr(foundry) + ']';
278 for (int i = 0; i != cb->count(); ++i) {
279 if (cb->itemText(i) == fontname) {
280 cb->setCurrentIndex(i);
285 // Try matching without foundry name
287 // We count in reverse in order to prefer the Xft foundry
288 for (int i = cb->count(); --i >= 0;) {
289 string name, fnt_foundry;
290 parseFontName(cb->itemText(i), name, fnt_foundry);
291 if (compare_ascii_no_case(name, family) == 0) {
292 cb->setCurrentIndex(i);
297 // family alone can contain e.g. "Helvetica [Adobe]"
298 string tmpname, tmpfoundry;
299 parseFontName(toqstr(family), tmpname, tmpfoundry);
301 // We count in reverse in order to prefer the Xft foundry
302 for (int i = cb->count(); --i >= 0; ) {
303 string name, fnt_foundry;
304 parseFontName(cb->itemText(i), name, fnt_foundry);
305 if (compare_ascii_no_case(name, fnt_foundry) == 0) {
306 cb->setCurrentIndex(i);
311 // Bleh, default fonts, and the names couldn't be found. Hack
316 QString const font_family = toqstr(family);
317 if (font_family == guiApp->romanFontName()) {
318 font.setStyleHint(QFont::Serif);
319 font.setFamily(font_family);
320 } else if (font_family == guiApp->sansFontName()) {
321 font.setStyleHint(QFont::SansSerif);
322 font.setFamily(font_family);
323 } else if (font_family == guiApp->typewriterFontName()) {
324 font.setStyleHint(QFont::TypeWriter);
325 font.setFamily(font_family);
327 LYXERR0("FAILED to find the default font: '"
328 << foundry << "', '" << family << '\'');
332 QFontInfo info(font);
333 string default_font_name, dummyfoundry;
334 parseFontName(info.family(), default_font_name, dummyfoundry);
335 LYXERR0("Apparent font is " << default_font_name);
337 for (int i = 0; i < cb->count(); ++i) {
338 LYXERR0("Looking at " << cb->itemText(i));
339 if (compare_ascii_no_case(fromqstr(cb->itemText(i)),
340 default_font_name) == 0) {
341 cb->setCurrentIndex(i);
346 LYXERR0("FAILED to find the font: '"
347 << foundry << "', '" << family << '\'');
351 /////////////////////////////////////////////////////////////////////
355 /////////////////////////////////////////////////////////////////////
357 PrefOutput::PrefOutput(GuiPreferences * form)
358 : PrefModule(catOutput, N_("General"), form)
362 dviCB->setValidator(new NoNewLineValidator(dviCB));
363 pdfCB->setValidator(new NoNewLineValidator(pdfCB));
365 connect(plaintextLinelengthSB, SIGNAL(valueChanged(int)),
366 this, SIGNAL(changed()));
367 connect(overwriteCO, SIGNAL(activated(int)),
368 this, SIGNAL(changed()));
369 connect(dviCB, SIGNAL(editTextChanged(QString)),
370 this, SIGNAL(changed()));
371 connect(pdfCB, SIGNAL(editTextChanged(QString)),
372 this, SIGNAL(changed()));
373 connect(printerPaperTypeED, SIGNAL(textChanged(QString)),
374 this, SIGNAL(changed()));
375 connect(printerLandscapeED, SIGNAL(textChanged(QString)),
376 this, SIGNAL(changed()));
377 connect(printerPaperSizeED, SIGNAL(textChanged(QString)),
378 this, SIGNAL(changed()));
380 printerPaperTypeED->setValidator(new NoNewLineValidator(printerPaperTypeED));
381 printerLandscapeED->setValidator(new NoNewLineValidator(printerLandscapeED));
382 printerPaperSizeED->setValidator(new NoNewLineValidator(printerPaperSizeED));
385 dviCB->addItem("xdvi -sourceposition '$$n:\\ $$t' $$o");
386 dviCB->addItem("yap -1 -s \"$$n $$t\" $$o");
387 dviCB->addItem("okular --unique \"$$o#src:$$n $$f\"");
388 dviCB->addItem("synctex view -i $$n:0:$$t -o $$o -x \"evince -i %{page+1} $$o\"");
390 pdfCB->addItem("CMCDDE SUMATRA control [ForwardSearch(\\\"$$o\\\",\\\"$$t\\\",$$n,0,0,1)]");
391 pdfCB->addItem("SumatraPDF -reuse-instance \"$$o\" -forward-search \"$$t\" $$n");
392 pdfCB->addItem("synctex view -i $$n:0:$$t -o $$o -x \"xpdf -raise -remote $$t.tmp $$o %{page+1}\"");
393 pdfCB->addItem("okular --unique \"$$o#src:$$n $$f\"");
394 pdfCB->addItem("qpdfview --unique \"$$o#src:$$f:$$n:0\"");
395 pdfCB->addItem("synctex view -i $$n:0:$$t -o $$o -x \"evince -i %{page+1} $$o\"");
396 pdfCB->addItem("/Applications/Skim.app/Contents/SharedSupport/displayline $$n $$o $$t");
400 void PrefOutput::applyRC(LyXRC & rc) const
402 rc.plaintext_linelen = plaintextLinelengthSB->value();
403 rc.forward_search_dvi = fromqstr(dviCB->currentText());
404 rc.forward_search_pdf = fromqstr(pdfCB->currentText());
406 switch (overwriteCO->currentIndex()) {
408 rc.export_overwrite = NO_FILES;
411 rc.export_overwrite = MAIN_FILE;
414 rc.export_overwrite = ALL_FILES;
418 rc.print_paper_flag = fromqstr(printerPaperTypeED->text());
419 rc.print_landscape_flag = fromqstr(printerLandscapeED->text());
420 rc.print_paper_dimension_flag = fromqstr(printerPaperSizeED->text());
424 void PrefOutput::updateRC(LyXRC const & rc)
426 plaintextLinelengthSB->setValue(rc.plaintext_linelen);
427 dviCB->setEditText(toqstr(rc.forward_search_dvi));
428 pdfCB->setEditText(toqstr(rc.forward_search_pdf));
430 switch (rc.export_overwrite) {
432 overwriteCO->setCurrentIndex(0);
435 overwriteCO->setCurrentIndex(1);
438 overwriteCO->setCurrentIndex(2);
442 printerPaperTypeED->setText(toqstr(rc.print_paper_flag));
443 printerLandscapeED->setText(toqstr(rc.print_landscape_flag));
444 printerPaperSizeED->setText(toqstr(rc.print_paper_dimension_flag));
448 /////////////////////////////////////////////////////////////////////
452 /////////////////////////////////////////////////////////////////////
454 PrefInput::PrefInput(GuiPreferences * form)
455 : PrefModule(catEditing, N_("Keyboard/Mouse"), form)
459 connect(keymapCB, SIGNAL(clicked()),
460 this, SIGNAL(changed()));
461 connect(firstKeymapED, SIGNAL(textChanged(QString)),
462 this, SIGNAL(changed()));
463 connect(secondKeymapED, SIGNAL(textChanged(QString)),
464 this, SIGNAL(changed()));
465 connect(mouseWheelSpeedSB, SIGNAL(valueChanged(double)),
466 this, SIGNAL(changed()));
467 connect(scrollzoomEnableCB, SIGNAL(clicked()),
468 this, SIGNAL(changed()));
469 connect(scrollzoomValueCO, SIGNAL(activated(int)),
470 this, SIGNAL(changed()));
471 connect(dontswapCB, SIGNAL(toggled(bool)),
472 this, SIGNAL(changed()));
473 connect(mmPasteCB, SIGNAL(toggled(bool)),
474 this, SIGNAL(changed()));
476 // reveal checkbox for switching Ctrl and Meta on Mac:
479 #if QT_VERSION > 0x040600
483 dontswapCB->setVisible(swapcb);
487 void PrefInput::applyRC(LyXRC & rc) const
489 // FIXME: can derive CB from the two EDs
490 rc.use_kbmap = keymapCB->isChecked();
491 rc.primary_kbmap = internal_path(fromqstr(firstKeymapED->text()));
492 rc.secondary_kbmap = internal_path(fromqstr(secondKeymapED->text()));
493 rc.mouse_wheel_speed = mouseWheelSpeedSB->value();
494 if (scrollzoomEnableCB->isChecked()) {
495 switch (scrollzoomValueCO->currentIndex()) {
497 rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_CTRL;
500 rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_SHIFT;
503 rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_ALT;
507 rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_OFF;
509 rc.mac_dontswap_ctrl_meta = dontswapCB->isChecked();
510 rc.mouse_middlebutton_paste = mmPasteCB->isChecked();
514 void PrefInput::updateRC(LyXRC const & rc)
516 // FIXME: can derive CB from the two EDs
517 keymapCB->setChecked(rc.use_kbmap);
518 firstKeymapED->setText(toqstr(external_path(rc.primary_kbmap)));
519 secondKeymapED->setText(toqstr(external_path(rc.secondary_kbmap)));
520 mouseWheelSpeedSB->setValue(rc.mouse_wheel_speed);
521 switch (rc.scroll_wheel_zoom) {
522 case LyXRC::SCROLL_WHEEL_ZOOM_OFF:
523 scrollzoomEnableCB->setChecked(false);
525 case LyXRC::SCROLL_WHEEL_ZOOM_CTRL:
526 scrollzoomEnableCB->setChecked(true);
527 scrollzoomValueCO->setCurrentIndex(0);
529 case LyXRC::SCROLL_WHEEL_ZOOM_SHIFT:
530 scrollzoomEnableCB->setChecked(true);
531 scrollzoomValueCO->setCurrentIndex(1);
533 case LyXRC::SCROLL_WHEEL_ZOOM_ALT:
534 scrollzoomEnableCB->setChecked(true);
535 scrollzoomValueCO->setCurrentIndex(2);
538 dontswapCB->setChecked(rc.mac_dontswap_ctrl_meta);
539 mmPasteCB->setChecked(rc.mouse_middlebutton_paste);
543 QString PrefInput::testKeymap(QString const & keymap)
545 return form_->browsekbmap(internalPath(keymap));
549 void PrefInput::on_firstKeymapPB_clicked(bool)
551 QString const file = testKeymap(firstKeymapED->text());
553 firstKeymapED->setText(file);
557 void PrefInput::on_secondKeymapPB_clicked(bool)
559 QString const file = testKeymap(secondKeymapED->text());
561 secondKeymapED->setText(file);
565 void PrefInput::on_keymapCB_toggled(bool keymap)
567 firstKeymapLA->setEnabled(keymap);
568 secondKeymapLA->setEnabled(keymap);
569 firstKeymapED->setEnabled(keymap);
570 secondKeymapED->setEnabled(keymap);
571 firstKeymapPB->setEnabled(keymap);
572 secondKeymapPB->setEnabled(keymap);
576 void PrefInput::on_scrollzoomEnableCB_toggled(bool enabled)
578 scrollzoomValueCO->setEnabled(enabled);
582 /////////////////////////////////////////////////////////////////////
586 /////////////////////////////////////////////////////////////////////
588 PrefCompletion::PrefCompletion(GuiPreferences * form)
589 : PrefModule(catEditing, N_("Input Completion"), form)
593 connect(inlineDelaySB, SIGNAL(valueChanged(double)),
594 this, SIGNAL(changed()));
595 connect(inlineMathCB, SIGNAL(clicked()),
596 this, SIGNAL(changed()));
597 connect(inlineTextCB, SIGNAL(clicked()),
598 this, SIGNAL(changed()));
599 connect(inlineDotsCB, SIGNAL(clicked()),
600 this, SIGNAL(changed()));
601 connect(popupDelaySB, SIGNAL(valueChanged(double)),
602 this, SIGNAL(changed()));
603 connect(popupMathCB, SIGNAL(clicked()),
604 this, SIGNAL(changed()));
605 connect(autocorrectionCB, SIGNAL(clicked()),
606 this, SIGNAL(changed()));
607 connect(popupTextCB, SIGNAL(clicked()),
608 this, SIGNAL(changed()));
609 connect(popupAfterCompleteCB, SIGNAL(clicked()),
610 this, SIGNAL(changed()));
611 connect(cursorTextCB, SIGNAL(clicked()),
612 this, SIGNAL(changed()));
613 connect(minlengthSB, SIGNAL(valueChanged(int)),
614 this, SIGNAL(changed()));
618 void PrefCompletion::on_inlineTextCB_clicked()
624 void PrefCompletion::on_popupTextCB_clicked()
630 void PrefCompletion::enableCB()
632 cursorTextCB->setEnabled(
633 popupTextCB->isChecked() || inlineTextCB->isChecked());
637 void PrefCompletion::applyRC(LyXRC & rc) const
639 rc.completion_inline_delay = inlineDelaySB->value();
640 rc.completion_inline_math = inlineMathCB->isChecked();
641 rc.completion_inline_text = inlineTextCB->isChecked();
642 rc.completion_inline_dots = inlineDotsCB->isChecked() ? 13 : -1;
643 rc.completion_popup_delay = popupDelaySB->value();
644 rc.completion_popup_math = popupMathCB->isChecked();
645 rc.autocorrection_math = autocorrectionCB->isChecked();
646 rc.completion_popup_text = popupTextCB->isChecked();
647 rc.completion_cursor_text = cursorTextCB->isChecked();
648 rc.completion_popup_after_complete =
649 popupAfterCompleteCB->isChecked();
650 rc.completion_minlength = minlengthSB->value();
654 void PrefCompletion::updateRC(LyXRC const & rc)
656 inlineDelaySB->setValue(rc.completion_inline_delay);
657 inlineMathCB->setChecked(rc.completion_inline_math);
658 inlineTextCB->setChecked(rc.completion_inline_text);
659 inlineDotsCB->setChecked(rc.completion_inline_dots != -1);
660 popupDelaySB->setValue(rc.completion_popup_delay);
661 popupMathCB->setChecked(rc.completion_popup_math);
662 autocorrectionCB->setChecked(rc.autocorrection_math);
663 popupTextCB->setChecked(rc.completion_popup_text);
664 cursorTextCB->setChecked(rc.completion_cursor_text);
665 popupAfterCompleteCB->setChecked(rc.completion_popup_after_complete);
667 minlengthSB->setValue(rc.completion_minlength);
672 /////////////////////////////////////////////////////////////////////
676 /////////////////////////////////////////////////////////////////////
678 PrefLatex::PrefLatex(GuiPreferences * form)
679 : PrefModule(catOutput, N_("LaTeX"), form)
683 latexDviPaperED->setValidator(new NoNewLineValidator(latexDviPaperED));
684 latexBibtexED->setValidator(new NoNewLineValidator(latexBibtexED));
685 latexJBibtexED->setValidator(new NoNewLineValidator(latexJBibtexED));
686 latexIndexED->setValidator(new NoNewLineValidator(latexIndexED));
687 latexJIndexED->setValidator(new NoNewLineValidator(latexJIndexED));
688 latexNomenclED->setValidator(new NoNewLineValidator(latexNomenclED));
689 latexChecktexED->setValidator(new NoNewLineValidator(latexChecktexED));
691 connect(latexChecktexED, SIGNAL(textChanged(QString)),
692 this, SIGNAL(changed()));
693 connect(latexBibtexCO, SIGNAL(activated(int)),
694 this, SIGNAL(changed()));
695 connect(latexBibtexED, SIGNAL(textChanged(QString)),
696 this, SIGNAL(changed()));
697 connect(latexJBibtexCO, SIGNAL(activated(int)),
698 this, SIGNAL(changed()));
699 connect(latexJBibtexED, SIGNAL(textChanged(QString)),
700 this, SIGNAL(changed()));
701 connect(latexIndexCO, SIGNAL(activated(int)),
702 this, SIGNAL(changed()));
703 connect(latexIndexED, SIGNAL(textChanged(QString)),
704 this, SIGNAL(changed()));
705 connect(latexJIndexED, SIGNAL(textChanged(QString)),
706 this, SIGNAL(changed()));
707 connect(latexAutoresetCB, SIGNAL(clicked()),
708 this, SIGNAL(changed()));
709 connect(latexDviPaperED, SIGNAL(textChanged(QString)),
710 this, SIGNAL(changed()));
711 connect(latexNomenclED, SIGNAL(textChanged(QString)),
712 this, SIGNAL(changed()));
714 #if defined(__CYGWIN__) || defined(_WIN32)
715 pathCB->setVisible(true);
716 connect(pathCB, SIGNAL(clicked()),
717 this, SIGNAL(changed()));
719 pathCB->setVisible(false);
724 void PrefLatex::on_latexBibtexCO_activated(int n)
726 QString const bibtex = latexBibtexCO->itemData(n).toString();
727 if (bibtex.isEmpty()) {
728 latexBibtexED->clear();
729 latexBibtexOptionsLA->setText(qt_("C&ommand:"));
732 for (LyXRC::CommandSet::const_iterator it = bibtex_alternatives.begin();
733 it != bibtex_alternatives.end(); ++it) {
734 QString const bib = toqstr(*it);
735 int ind = bib.indexOf(" ");
736 QString sel_command = bib.left(ind);
737 QString sel_options = ind < 0 ? QString() : bib.mid(ind + 1);
738 if (bibtex == sel_command) {
740 latexBibtexED->clear();
742 latexBibtexED->setText(sel_options.trimmed());
745 latexBibtexOptionsLA->setText(qt_("&Options:"));
749 void PrefLatex::on_latexJBibtexCO_activated(int n)
751 QString const jbibtex = latexJBibtexCO->itemData(n).toString();
752 if (jbibtex.isEmpty()) {
753 latexJBibtexED->clear();
754 latexJBibtexOptionsLA->setText(qt_("Co&mmand:"));
757 for (LyXRC::CommandSet::const_iterator it = jbibtex_alternatives.begin();
758 it != jbibtex_alternatives.end(); ++it) {
759 QString const bib = toqstr(*it);
760 int ind = bib.indexOf(" ");
761 QString sel_command = bib.left(ind);
762 QString sel_options = ind < 0 ? QString() : bib.mid(ind + 1);
763 if (jbibtex == sel_command) {
765 latexJBibtexED->clear();
767 latexJBibtexED->setText(sel_options.trimmed());
770 latexJBibtexOptionsLA->setText(qt_("Opt&ions:"));
774 void PrefLatex::on_latexIndexCO_activated(int n)
776 QString const index = latexIndexCO->itemData(n).toString();
777 if (index.isEmpty()) {
778 latexIndexED->clear();
779 latexIndexOptionsLA->setText(qt_("Co&mmand:"));
782 for (LyXRC::CommandSet::const_iterator it = index_alternatives.begin();
783 it != index_alternatives.end(); ++it) {
784 QString const idx = toqstr(*it);
785 int ind = idx.indexOf(" ");
786 QString sel_command = idx.left(ind);
787 QString sel_options = ind < 0 ? QString() : idx.mid(ind + 1);
788 if (index == sel_command) {
790 latexIndexED->clear();
792 latexIndexED->setText(sel_options.trimmed());
795 latexIndexOptionsLA->setText(qt_("Op&tions:"));
799 void PrefLatex::applyRC(LyXRC & rc) const
801 // If bibtex is not empty, bibopt contains the options, otherwise
802 // it is a customized bibtex command with options.
803 QString const bibtex = latexBibtexCO->itemData(
804 latexBibtexCO->currentIndex()).toString();
805 QString const bibopt = latexBibtexED->text();
806 if (bibtex.isEmpty())
807 rc.bibtex_command = fromqstr(bibopt);
808 else if (bibopt.isEmpty())
809 rc.bibtex_command = fromqstr(bibtex);
811 rc.bibtex_command = fromqstr(bibtex) + " " + fromqstr(bibopt);
813 // If jbibtex is not empty, jbibopt contains the options, otherwise
814 // it is a customized bibtex command with options.
815 QString const jbibtex = latexJBibtexCO->itemData(
816 latexJBibtexCO->currentIndex()).toString();
817 QString const jbibopt = latexJBibtexED->text();
818 if (jbibtex.isEmpty())
819 rc.jbibtex_command = fromqstr(jbibopt);
820 else if (jbibopt.isEmpty())
821 rc.jbibtex_command = fromqstr(jbibtex);
823 rc.jbibtex_command = fromqstr(jbibtex) + " " + fromqstr(jbibopt);
825 // If index is not empty, idxopt contains the options, otherwise
826 // it is a customized index command with options.
827 QString const index = latexIndexCO->itemData(
828 latexIndexCO->currentIndex()).toString();
829 QString const idxopt = latexIndexED->text();
831 rc.index_command = fromqstr(idxopt);
832 else if (idxopt.isEmpty())
833 rc.index_command = fromqstr(index);
835 rc.index_command = fromqstr(index) + " " + fromqstr(idxopt);
837 rc.chktex_command = fromqstr(latexChecktexED->text());
838 rc.jindex_command = fromqstr(latexJIndexED->text());
839 rc.nomencl_command = fromqstr(latexNomenclED->text());
840 rc.auto_reset_options = latexAutoresetCB->isChecked();
841 rc.view_dvi_paper_option = fromqstr(latexDviPaperED->text());
842 #if defined(__CYGWIN__) || defined(_WIN32)
843 rc.windows_style_tex_paths = pathCB->isChecked();
848 void PrefLatex::updateRC(LyXRC const & rc)
850 latexBibtexCO->clear();
852 latexBibtexCO->addItem(qt_("Automatic"), "automatic");
853 latexBibtexCO->addItem(qt_("Custom"), QString());
854 for (LyXRC::CommandSet::const_iterator it = rc.bibtex_alternatives.begin();
855 it != rc.bibtex_alternatives.end(); ++it) {
856 QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
857 latexBibtexCO->addItem(command, command);
860 bibtex_alternatives = rc.bibtex_alternatives;
862 QString const bib = toqstr(rc.bibtex_command);
863 int ind = bib.indexOf(" ");
864 QString sel_command = bib.left(ind);
865 QString sel_options = ind < 0 ? QString() : bib.mid(ind + 1);
867 int pos = latexBibtexCO->findData(sel_command);
869 latexBibtexCO->setCurrentIndex(pos);
870 latexBibtexED->setText(sel_options.trimmed());
871 latexBibtexOptionsLA->setText(qt_("&Options:"));
873 latexBibtexED->setText(toqstr(rc.bibtex_command));
874 latexBibtexCO->setCurrentIndex(0);
875 latexBibtexOptionsLA->setText(qt_("C&ommand:"));
878 latexJBibtexCO->clear();
880 latexJBibtexCO->addItem(qt_("Automatic"), "automatic");
881 latexJBibtexCO->addItem(qt_("Custom"), QString());
882 for (LyXRC::CommandSet::const_iterator it = rc.jbibtex_alternatives.begin();
883 it != rc.jbibtex_alternatives.end(); ++it) {
884 QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
885 latexJBibtexCO->addItem(command, command);
888 jbibtex_alternatives = rc.jbibtex_alternatives;
890 QString const jbib = toqstr(rc.jbibtex_command);
891 ind = jbib.indexOf(" ");
892 sel_command = jbib.left(ind);
893 sel_options = ind < 0 ? QString() : jbib.mid(ind + 1);
895 pos = latexJBibtexCO->findData(sel_command);
897 latexJBibtexCO->setCurrentIndex(pos);
898 latexJBibtexED->setText(sel_options.trimmed());
899 latexJBibtexOptionsLA->setText(qt_("Opt&ions:"));
901 latexJBibtexED->setText(toqstr(rc.bibtex_command));
902 latexJBibtexCO->setCurrentIndex(0);
903 latexJBibtexOptionsLA->setText(qt_("Co&mmand:"));
906 latexIndexCO->clear();
908 latexIndexCO->addItem(qt_("Custom"), QString());
909 for (LyXRC::CommandSet::const_iterator it = rc.index_alternatives.begin();
910 it != rc.index_alternatives.end(); ++it) {
911 QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
912 latexIndexCO->addItem(command, command);
915 index_alternatives = rc.index_alternatives;
917 QString const idx = toqstr(rc.index_command);
918 ind = idx.indexOf(" ");
919 sel_command = idx.left(ind);
920 sel_options = ind < 0 ? QString() : idx.mid(ind + 1);
922 pos = latexIndexCO->findData(sel_command);
924 latexIndexCO->setCurrentIndex(pos);
925 latexIndexED->setText(sel_options.trimmed());
926 latexIndexOptionsLA->setText(qt_("Op&tions:"));
928 latexIndexED->setText(toqstr(rc.index_command));
929 latexIndexCO->setCurrentIndex(0);
930 latexIndexOptionsLA->setText(qt_("Co&mmand:"));
933 latexChecktexED->setText(toqstr(rc.chktex_command));
934 latexJIndexED->setText(toqstr(rc.jindex_command));
935 latexNomenclED->setText(toqstr(rc.nomencl_command));
936 latexAutoresetCB->setChecked(rc.auto_reset_options);
937 latexDviPaperED->setText(toqstr(rc.view_dvi_paper_option));
938 #if defined(__CYGWIN__) || defined(_WIN32)
939 pathCB->setChecked(rc.windows_style_tex_paths);
944 /////////////////////////////////////////////////////////////////////
948 /////////////////////////////////////////////////////////////////////
950 PrefScreenFonts::PrefScreenFonts(GuiPreferences * form)
951 : PrefModule(catLookAndFeel, N_("Screen Fonts"), form)
955 connect(screenRomanCO, SIGNAL(activated(QString)),
956 this, SLOT(selectRoman(QString)));
957 connect(screenSansCO, SIGNAL(activated(QString)),
958 this, SLOT(selectSans(QString)));
959 connect(screenTypewriterCO, SIGNAL(activated(QString)),
960 this, SLOT(selectTypewriter(QString)));
962 QFontDatabase fontdb;
963 QStringList families(fontdb.families());
964 for (QStringList::Iterator it = families.begin(); it != families.end(); ++it) {
965 screenRomanCO->addItem(*it);
966 screenSansCO->addItem(*it);
967 screenTypewriterCO->addItem(*it);
969 connect(screenRomanCO, SIGNAL(activated(QString)),
970 this, SIGNAL(changed()));
971 connect(screenSansCO, SIGNAL(activated(QString)),
972 this, SIGNAL(changed()));
973 connect(screenTypewriterCO, SIGNAL(activated(QString)),
974 this, SIGNAL(changed()));
975 connect(screenZoomSB, SIGNAL(valueChanged(int)),
976 this, SIGNAL(changed()));
977 connect(screenTinyED, SIGNAL(textChanged(QString)),
978 this, SIGNAL(changed()));
979 connect(screenSmallestED, SIGNAL(textChanged(QString)),
980 this, SIGNAL(changed()));
981 connect(screenSmallerED, SIGNAL(textChanged(QString)),
982 this, SIGNAL(changed()));
983 connect(screenSmallED, SIGNAL(textChanged(QString)),
984 this, SIGNAL(changed()));
985 connect(screenNormalED, SIGNAL(textChanged(QString)),
986 this, SIGNAL(changed()));
987 connect(screenLargeED, SIGNAL(textChanged(QString)),
988 this, SIGNAL(changed()));
989 connect(screenLargerED, SIGNAL(textChanged(QString)),
990 this, SIGNAL(changed()));
991 connect(screenLargestED, SIGNAL(textChanged(QString)),
992 this, SIGNAL(changed()));
993 connect(screenHugeED, SIGNAL(textChanged(QString)),
994 this, SIGNAL(changed()));
995 connect(screenHugerED, SIGNAL(textChanged(QString)),
996 this, SIGNAL(changed()));
998 screenTinyED->setValidator(new QDoubleValidator(screenTinyED));
999 screenSmallestED->setValidator(new QDoubleValidator(screenSmallestED));
1000 screenSmallerED->setValidator(new QDoubleValidator(screenSmallerED));
1001 screenSmallED->setValidator(new QDoubleValidator(screenSmallED));
1002 screenNormalED->setValidator(new QDoubleValidator(screenNormalED));
1003 screenLargeED->setValidator(new QDoubleValidator(screenLargeED));
1004 screenLargerED->setValidator(new QDoubleValidator(screenLargerED));
1005 screenLargestED->setValidator(new QDoubleValidator(screenLargestED));
1006 screenHugeED->setValidator(new QDoubleValidator(screenHugeED));
1007 screenHugerED->setValidator(new QDoubleValidator(screenHugerED));
1011 void PrefScreenFonts::applyRC(LyXRC & rc) const
1013 LyXRC const oldrc = rc;
1015 parseFontName(screenRomanCO->currentText(),
1016 rc.roman_font_name, rc.roman_font_foundry);
1017 parseFontName(screenSansCO->currentText(),
1018 rc.sans_font_name, rc.sans_font_foundry);
1019 parseFontName(screenTypewriterCO->currentText(),
1020 rc.typewriter_font_name, rc.typewriter_font_foundry);
1022 rc.defaultZoom = screenZoomSB->value();
1023 rc.font_sizes[FONT_SIZE_TINY] = widgetToDoubleStr(screenTinyED);
1024 rc.font_sizes[FONT_SIZE_SCRIPT] = widgetToDoubleStr(screenSmallestED);
1025 rc.font_sizes[FONT_SIZE_FOOTNOTE] = widgetToDoubleStr(screenSmallerED);
1026 rc.font_sizes[FONT_SIZE_SMALL] = widgetToDoubleStr(screenSmallED);
1027 rc.font_sizes[FONT_SIZE_NORMAL] = widgetToDoubleStr(screenNormalED);
1028 rc.font_sizes[FONT_SIZE_LARGE] = widgetToDoubleStr(screenLargeED);
1029 rc.font_sizes[FONT_SIZE_LARGER] = widgetToDoubleStr(screenLargerED);
1030 rc.font_sizes[FONT_SIZE_LARGEST] = widgetToDoubleStr(screenLargestED);
1031 rc.font_sizes[FONT_SIZE_HUGE] = widgetToDoubleStr(screenHugeED);
1032 rc.font_sizes[FONT_SIZE_HUGER] = widgetToDoubleStr(screenHugerED);
1034 if (rc.font_sizes != oldrc.font_sizes
1035 || rc.roman_font_name != oldrc.roman_font_name
1036 || rc.sans_font_name != oldrc.sans_font_name
1037 || rc.typewriter_font_name != oldrc.typewriter_font_name
1038 || rc.defaultZoom != oldrc.defaultZoom) {
1039 guiApp->fontLoader().update();
1040 form_->updateScreenFonts();
1045 void PrefScreenFonts::updateRC(LyXRC const & rc)
1047 setComboxFont(screenRomanCO, rc.roman_font_name,
1048 rc.roman_font_foundry);
1049 setComboxFont(screenSansCO, rc.sans_font_name,
1050 rc.sans_font_foundry);
1051 setComboxFont(screenTypewriterCO, rc.typewriter_font_name,
1052 rc.typewriter_font_foundry);
1054 selectRoman(screenRomanCO->currentText());
1055 selectSans(screenSansCO->currentText());
1056 selectTypewriter(screenTypewriterCO->currentText());
1058 screenZoomSB->setValue(rc.defaultZoom);
1059 updateScreenFontSizes(rc);
1063 void PrefScreenFonts::updateScreenFontSizes(LyXRC const & rc)
1065 doubleToWidget(screenTinyED, rc.font_sizes[FONT_SIZE_TINY]);
1066 doubleToWidget(screenSmallestED, rc.font_sizes[FONT_SIZE_SCRIPT]);
1067 doubleToWidget(screenSmallerED, rc.font_sizes[FONT_SIZE_FOOTNOTE]);
1068 doubleToWidget(screenSmallED, rc.font_sizes[FONT_SIZE_SMALL]);
1069 doubleToWidget(screenNormalED, rc.font_sizes[FONT_SIZE_NORMAL]);
1070 doubleToWidget(screenLargeED, rc.font_sizes[FONT_SIZE_LARGE]);
1071 doubleToWidget(screenLargerED, rc.font_sizes[FONT_SIZE_LARGER]);
1072 doubleToWidget(screenLargestED, rc.font_sizes[FONT_SIZE_LARGEST]);
1073 doubleToWidget(screenHugeED, rc.font_sizes[FONT_SIZE_HUGE]);
1074 doubleToWidget(screenHugerED, rc.font_sizes[FONT_SIZE_HUGER]);
1078 void PrefScreenFonts::selectRoman(const QString & name)
1080 screenRomanFE->set(QFont(name), name);
1084 void PrefScreenFonts::selectSans(const QString & name)
1086 screenSansFE->set(QFont(name), name);
1090 void PrefScreenFonts::selectTypewriter(const QString & name)
1092 screenTypewriterFE->set(QFont(name), name);
1096 /////////////////////////////////////////////////////////////////////
1100 /////////////////////////////////////////////////////////////////////
1103 PrefColors::PrefColors(GuiPreferences * form)
1104 : PrefModule(catLookAndFeel, N_("Colors"), form)
1108 // FIXME: all of this initialization should be put into the controller.
1109 // See http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg113301.html
1110 // for some discussion of why that is not trivial.
1111 QPixmap icon(32, 32);
1112 for (int i = 0; i < Color_ignore; ++i) {
1113 ColorCode lc = static_cast<ColorCode>(i);
1114 if (lc == Color_none
1115 || lc == Color_black
1116 || lc == Color_white
1118 || lc == Color_brown
1120 || lc == Color_darkgray
1122 || lc == Color_green
1123 || lc == Color_lightgray
1125 || lc == Color_magenta
1126 || lc == Color_olive
1127 || lc == Color_orange
1129 || lc == Color_purple
1132 || lc == Color_violet
1133 || lc == Color_yellow
1134 || lc == Color_inherit
1135 || lc == Color_ignore)
1137 lcolors_.push_back(lc);
1139 qSort(lcolors_.begin(), lcolors_.end(), ColorSorter);
1140 vector<ColorCode>::const_iterator cit = lcolors_.begin();
1141 vector<ColorCode>::const_iterator const end = lcolors_.end();
1142 for (; cit != end; ++cit) {
1143 (void) new QListWidgetItem(QIcon(icon),
1144 toqstr(lcolor.getGUIName(*cit)), lyxObjectsLW);
1146 curcolors_.resize(lcolors_.size());
1147 newcolors_.resize(lcolors_.size());
1148 // End initialization
1150 connect(colorChangePB, SIGNAL(clicked()),
1151 this, SLOT(changeColor()));
1152 connect(colorResetPB, SIGNAL(clicked()),
1153 this, SLOT(resetColor()));
1154 connect(colorResetAllPB, SIGNAL(clicked()),
1155 this, SLOT(resetAllColor()));
1156 connect(lyxObjectsLW, SIGNAL(itemSelectionChanged()),
1157 this, SLOT(changeLyxObjectsSelection()));
1158 connect(lyxObjectsLW, SIGNAL(itemActivated(QListWidgetItem*)),
1159 this, SLOT(changeColor()));
1160 connect(syscolorsCB, SIGNAL(toggled(bool)),
1161 this, SIGNAL(changed()));
1162 connect(syscolorsCB, SIGNAL(toggled(bool)),
1163 this, SLOT(changeSysColor()));
1167 void PrefColors::applyRC(LyXRC & rc) const
1171 for (unsigned int i = 0; i < lcolors_.size(); ++i)
1172 if (curcolors_[i] != newcolors_[i])
1173 form_->setColor(lcolors_[i], newcolors_[i]);
1174 rc.use_system_colors = syscolorsCB->isChecked();
1176 if (oldrc.use_system_colors != rc.use_system_colors)
1177 guiApp->colorCache().clear();
1181 void PrefColors::updateRC(LyXRC const & rc)
1183 for (size_type i = 0; i < lcolors_.size(); ++i) {
1184 QColor color = QColor(guiApp->colorCache().get(lcolors_[i], false));
1185 QPixmap coloritem(32, 32);
1186 coloritem.fill(color);
1187 lyxObjectsLW->item(int(i))->setIcon(QIcon(coloritem));
1188 newcolors_[i] = curcolors_[i] = color.name();
1190 syscolorsCB->setChecked(rc.use_system_colors);
1191 changeLyxObjectsSelection();
1193 setDisabledResets();
1197 void PrefColors::changeColor()
1199 int const row = lyxObjectsLW->currentRow();
1205 QString const color = newcolors_[size_t(row)];
1206 QColor const c = QColorDialog::getColor(QColor(color), qApp->focusWidget());
1208 if (setColor(row, c, color)) {
1209 setDisabledResets();
1216 void PrefColors::resetColor()
1218 int const row = lyxObjectsLW->currentRow();
1224 QString const color = newcolors_[size_t(row)];
1225 QColor const c = getDefaultColorByRow(row);
1227 if (setColor(row, c, color)) {
1228 setDisabledResets();
1235 void PrefColors::resetAllColor()
1237 bool isChanged = false;
1239 colorResetAllPB->setDisabled(true);
1241 for (int irow = 0, count = lyxObjectsLW->count(); irow < count; ++irow) {
1242 QString const color = newcolors_[size_t(irow)];
1243 QColor const c = getDefaultColorByRow(irow);
1245 if (setColor(irow, c, color))
1250 setDisabledResets();
1257 bool PrefColors::setColor(int const row, QColor const new_color,
1258 QString const old_color)
1260 if (new_color.isValid() && new_color.name() != old_color) {
1261 newcolors_[size_t(row)] = new_color.name();
1262 QPixmap coloritem(32, 32);
1263 coloritem.fill(new_color);
1264 lyxObjectsLW->item(row)->setIcon(QIcon(coloritem));
1271 void PrefColors::setDisabledResets()
1273 int const row = lyxObjectsLW->currentRow();
1274 // set disable reset buttons ...
1276 colorResetPB->setDisabled(isDefaultColor(row, newcolors_[size_t(row)]));
1278 colorResetAllPB->setDisabled(true);
1280 // ... in between process qt events to give quicker visual feedback to the user ...
1281 guiApp->processEvents();
1283 // ... set disable Reset All button
1284 for (int irow = 0, count = lyxObjectsLW->count(); irow < count; ++irow) {
1285 if (!isDefaultColor(irow, newcolors_[size_t(irow)])) {
1286 colorResetAllPB->setDisabled(false);
1287 // the break condition might hide performance issues
1288 // if a non-default color is at the top of the list
1295 bool PrefColors::isDefaultColor(int const row, QString const color)
1297 return color == getDefaultColorByRow(row).name();
1301 QColor PrefColors::getDefaultColorByRow(int const row)
1303 ColorSet const defaultcolor;
1304 return defaultcolor.getX11Name(lcolors_[size_t(row)]).c_str();
1308 void PrefColors::changeSysColor()
1310 for (int row = 0 ; row < lyxObjectsLW->count() ; ++row) {
1311 // skip colors that are taken from system palette
1312 bool const disable = syscolorsCB->isChecked()
1313 && guiApp->colorCache().isSystem(lcolors_[size_t(row)]);
1315 QListWidgetItem * const item = lyxObjectsLW->item(row);
1316 Qt::ItemFlags const flags = item->flags();
1319 item->setFlags(flags & ~Qt::ItemIsEnabled);
1321 item->setFlags(flags | Qt::ItemIsEnabled);
1326 void PrefColors::changeLyxObjectsSelection()
1328 int currentRow = lyxObjectsLW->currentRow();
1329 colorChangePB->setDisabled(currentRow < 0);
1332 colorResetPB->setDisabled(true);
1334 colorResetPB->setDisabled(
1335 isDefaultColor(currentRow, newcolors_[size_t(currentRow)]));
1339 /////////////////////////////////////////////////////////////////////
1343 /////////////////////////////////////////////////////////////////////
1345 PrefDisplay::PrefDisplay(GuiPreferences * form)
1346 : PrefModule(catLookAndFeel, N_("Display"), form)
1349 connect(displayGraphicsCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1350 connect(instantPreviewCO, SIGNAL(activated(int)), this, SIGNAL(changed()));
1351 connect(previewSizeSB, SIGNAL(valueChanged(double)), this, SIGNAL(changed()));
1352 connect(paragraphMarkerCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1356 void PrefDisplay::on_instantPreviewCO_currentIndexChanged(int index)
1358 previewSizeSB->setEnabled(index != 0);
1362 void PrefDisplay::applyRC(LyXRC & rc) const
1364 switch (instantPreviewCO->currentIndex()) {
1366 rc.preview = LyXRC::PREVIEW_OFF;
1369 if (rc.preview != LyXRC::PREVIEW_NO_MATH) {
1370 rc.preview = LyXRC::PREVIEW_NO_MATH;
1371 form_->updatePreviews();
1375 if (rc.preview != LyXRC::PREVIEW_ON) {
1376 rc.preview = LyXRC::PREVIEW_ON;
1377 form_->updatePreviews();
1382 rc.display_graphics = displayGraphicsCB->isChecked();
1383 rc.preview_scale_factor = previewSizeSB->value();
1384 rc.paragraph_markers = paragraphMarkerCB->isChecked();
1386 // FIXME!! The graphics cache no longer has a changeDisplay method.
1388 if (old_value != rc.display_graphics) {
1389 graphics::GCache & gc = graphics::GCache::get();
1396 void PrefDisplay::updateRC(LyXRC const & rc)
1398 switch (rc.preview) {
1399 case LyXRC::PREVIEW_OFF:
1400 instantPreviewCO->setCurrentIndex(0);
1402 case LyXRC::PREVIEW_NO_MATH :
1403 instantPreviewCO->setCurrentIndex(1);
1405 case LyXRC::PREVIEW_ON :
1406 instantPreviewCO->setCurrentIndex(2);
1410 displayGraphicsCB->setChecked(rc.display_graphics);
1411 previewSizeSB->setValue(rc.preview_scale_factor);
1412 paragraphMarkerCB->setChecked(rc.paragraph_markers);
1413 previewSizeSB->setEnabled(
1415 && rc.preview != LyXRC::PREVIEW_OFF);
1419 /////////////////////////////////////////////////////////////////////
1423 /////////////////////////////////////////////////////////////////////
1425 PrefPaths::PrefPaths(GuiPreferences * form)
1426 : PrefModule(QString(), N_("Paths"), form)
1430 connect(workingDirPB, SIGNAL(clicked()), this, SLOT(selectWorkingdir()));
1431 connect(workingDirED, SIGNAL(textChanged(QString)),
1432 this, SIGNAL(changed()));
1434 connect(templateDirPB, SIGNAL(clicked()), this, SLOT(selectTemplatedir()));
1435 connect(templateDirED, SIGNAL(textChanged(QString)),
1436 this, SIGNAL(changed()));
1438 connect(exampleDirPB, SIGNAL(clicked()), this, SLOT(selectExampledir()));
1439 connect(exampleDirED, SIGNAL(textChanged(QString)),
1440 this, SIGNAL(changed()));
1442 connect(backupDirPB, SIGNAL(clicked()), this, SLOT(selectBackupdir()));
1443 connect(backupDirED, SIGNAL(textChanged(QString)),
1444 this, SIGNAL(changed()));
1446 connect(lyxserverDirPB, SIGNAL(clicked()), this, SLOT(selectLyxPipe()));
1447 connect(lyxserverDirED, SIGNAL(textChanged(QString)),
1448 this, SIGNAL(changed()));
1450 connect(thesaurusDirPB, SIGNAL(clicked()), this, SLOT(selectThesaurusdir()));
1451 connect(thesaurusDirED, SIGNAL(textChanged(QString)),
1452 this, SIGNAL(changed()));
1454 connect(tempDirPB, SIGNAL(clicked()), this, SLOT(selectTempdir()));
1455 connect(tempDirED, SIGNAL(textChanged(QString)),
1456 this, SIGNAL(changed()));
1458 #if defined(USE_HUNSPELL)
1459 connect(hunspellDirPB, SIGNAL(clicked()), this, SLOT(selectHunspelldir()));
1460 connect(hunspellDirED, SIGNAL(textChanged(QString)),
1461 this, SIGNAL(changed()));
1463 hunspellDirPB->setEnabled(false);
1464 hunspellDirED->setEnabled(false);
1467 connect(pathPrefixED, SIGNAL(textChanged(QString)),
1468 this, SIGNAL(changed()));
1470 connect(texinputsPrefixED, SIGNAL(textChanged(QString)),
1471 this, SIGNAL(changed()));
1473 pathPrefixED->setValidator(new NoNewLineValidator(pathPrefixED));
1474 texinputsPrefixED->setValidator(new NoNewLineValidator(texinputsPrefixED));
1478 void PrefPaths::applyRC(LyXRC & rc) const
1480 rc.document_path = internal_path(fromqstr(workingDirED->text()));
1481 rc.example_path = internal_path(fromqstr(exampleDirED->text()));
1482 rc.template_path = internal_path(fromqstr(templateDirED->text()));
1483 rc.backupdir_path = internal_path(fromqstr(backupDirED->text()));
1484 rc.tempdir_path = internal_path(fromqstr(tempDirED->text()));
1485 rc.thesaurusdir_path = internal_path(fromqstr(thesaurusDirED->text()));
1486 rc.hunspelldir_path = internal_path(fromqstr(hunspellDirED->text()));
1487 rc.path_prefix = internal_path_list(fromqstr(pathPrefixED->text()));
1488 rc.texinputs_prefix = internal_path_list(fromqstr(texinputsPrefixED->text()));
1489 // FIXME: should be a checkbox only
1490 rc.lyxpipes = internal_path(fromqstr(lyxserverDirED->text()));
1494 void PrefPaths::updateRC(LyXRC const & rc)
1496 workingDirED->setText(toqstr(external_path(rc.document_path)));
1497 exampleDirED->setText(toqstr(external_path(rc.example_path)));
1498 templateDirED->setText(toqstr(external_path(rc.template_path)));
1499 backupDirED->setText(toqstr(external_path(rc.backupdir_path)));
1500 tempDirED->setText(toqstr(external_path(rc.tempdir_path)));
1501 thesaurusDirED->setText(toqstr(external_path(rc.thesaurusdir_path)));
1502 hunspellDirED->setText(toqstr(external_path(rc.hunspelldir_path)));
1503 pathPrefixED->setText(toqstr(external_path_list(rc.path_prefix)));
1504 texinputsPrefixED->setText(toqstr(external_path_list(rc.texinputs_prefix)));
1505 // FIXME: should be a checkbox only
1506 lyxserverDirED->setText(toqstr(external_path(rc.lyxpipes)));
1510 void PrefPaths::selectExampledir()
1512 QString file = browseDir(internalPath(exampleDirED->text()),
1513 qt_("Select directory for example files"));
1514 if (!file.isEmpty())
1515 exampleDirED->setText(file);
1519 void PrefPaths::selectTemplatedir()
1521 QString file = browseDir(internalPath(templateDirED->text()),
1522 qt_("Select a document templates directory"));
1523 if (!file.isEmpty())
1524 templateDirED->setText(file);
1528 void PrefPaths::selectTempdir()
1530 QString file = browseDir(internalPath(tempDirED->text()),
1531 qt_("Select a temporary directory"));
1532 if (!file.isEmpty())
1533 tempDirED->setText(file);
1537 void PrefPaths::selectBackupdir()
1539 QString file = browseDir(internalPath(backupDirED->text()),
1540 qt_("Select a backups directory"));
1541 if (!file.isEmpty())
1542 backupDirED->setText(file);
1546 void PrefPaths::selectWorkingdir()
1548 QString file = browseDir(internalPath(workingDirED->text()),
1549 qt_("Select a document directory"));
1550 if (!file.isEmpty())
1551 workingDirED->setText(file);
1555 void PrefPaths::selectThesaurusdir()
1557 QString file = browseDir(internalPath(thesaurusDirED->text()),
1558 qt_("Set the path to the thesaurus dictionaries"));
1559 if (!file.isEmpty())
1560 thesaurusDirED->setText(file);
1564 void PrefPaths::selectHunspelldir()
1566 QString file = browseDir(internalPath(hunspellDirED->text()),
1567 qt_("Set the path to the Hunspell dictionaries"));
1568 if (!file.isEmpty())
1569 hunspellDirED->setText(file);
1573 void PrefPaths::selectLyxPipe()
1575 QString file = form_->browse(internalPath(lyxserverDirED->text()),
1576 qt_("Give a filename for the LyX server pipe"));
1577 if (!file.isEmpty())
1578 lyxserverDirED->setText(file);
1582 /////////////////////////////////////////////////////////////////////
1586 /////////////////////////////////////////////////////////////////////
1588 PrefSpellchecker::PrefSpellchecker(GuiPreferences * form)
1589 : PrefModule(catLanguage, N_("Spellchecker"), form)
1593 // FIXME: this check should test the target platform (darwin)
1594 #if defined(USE_MACOSX_PACKAGING)
1595 spellcheckerCB->addItem(qt_("Native"), QString("native"));
1596 #define CONNECT_APPLESPELL
1598 #undef CONNECT_APPLESPELL
1600 #if defined(USE_ASPELL)
1601 spellcheckerCB->addItem(qt_("Aspell"), QString("aspell"));
1603 #if defined(USE_ENCHANT)
1604 spellcheckerCB->addItem(qt_("Enchant"), QString("enchant"));
1606 #if defined(USE_HUNSPELL)
1607 spellcheckerCB->addItem(qt_("Hunspell"), QString("hunspell"));
1610 #if defined(CONNECT_APPLESPELL) || defined(USE_ASPELL) || defined(USE_ENCHANT) || defined(USE_HUNSPELL)
1611 connect(spellcheckerCB, SIGNAL(currentIndexChanged(int)),
1612 this, SIGNAL(changed()));
1613 connect(altLanguageED, SIGNAL(textChanged(QString)),
1614 this, SIGNAL(changed()));
1615 connect(escapeCharactersED, SIGNAL(textChanged(QString)),
1616 this, SIGNAL(changed()));
1617 connect(compoundWordCB, SIGNAL(clicked()),
1618 this, SIGNAL(changed()));
1619 connect(spellcheckContinuouslyCB, SIGNAL(clicked()),
1620 this, SIGNAL(changed()));
1621 connect(spellcheckNotesCB, SIGNAL(clicked()),
1622 this, SIGNAL(changed()));
1624 altLanguageED->setValidator(new NoNewLineValidator(altLanguageED));
1625 escapeCharactersED->setValidator(new NoNewLineValidator(escapeCharactersED));
1627 spellcheckerCB->setEnabled(false);
1628 altLanguageED->setEnabled(false);
1629 escapeCharactersED->setEnabled(false);
1630 compoundWordCB->setEnabled(false);
1631 spellcheckContinuouslyCB->setEnabled(false);
1632 spellcheckNotesCB->setEnabled(false);
1637 void PrefSpellchecker::applyRC(LyXRC & rc) const
1639 string const speller = fromqstr(spellcheckerCB->
1640 itemData(spellcheckerCB->currentIndex()).toString());
1641 if (!speller.empty())
1642 rc.spellchecker = speller;
1643 rc.spellchecker_alt_lang = fromqstr(altLanguageED->text());
1644 rc.spellchecker_esc_chars = fromqstr(escapeCharactersED->text());
1645 rc.spellchecker_accept_compound = compoundWordCB->isChecked();
1646 rc.spellcheck_continuously = spellcheckContinuouslyCB->isChecked();
1647 rc.spellcheck_notes = spellcheckNotesCB->isChecked();
1651 void PrefSpellchecker::updateRC(LyXRC const & rc)
1653 spellcheckerCB->setCurrentIndex(
1654 spellcheckerCB->findData(toqstr(rc.spellchecker)));
1655 altLanguageED->setText(toqstr(rc.spellchecker_alt_lang));
1656 escapeCharactersED->setText(toqstr(rc.spellchecker_esc_chars));
1657 compoundWordCB->setChecked(rc.spellchecker_accept_compound);
1658 spellcheckContinuouslyCB->setChecked(rc.spellcheck_continuously);
1659 spellcheckNotesCB->setChecked(rc.spellcheck_notes);
1663 void PrefSpellchecker::on_spellcheckerCB_currentIndexChanged(int index)
1665 QString spellchecker = spellcheckerCB->itemData(index).toString();
1667 compoundWordCB->setEnabled(spellchecker == QString("aspell"));
1672 /////////////////////////////////////////////////////////////////////
1676 /////////////////////////////////////////////////////////////////////
1679 PrefConverters::PrefConverters(GuiPreferences * form)
1680 : PrefModule(catFiles, N_("Converters"), form)
1684 connect(converterNewPB, SIGNAL(clicked()),
1685 this, SLOT(updateConverter()));
1686 connect(converterRemovePB, SIGNAL(clicked()),
1687 this, SLOT(removeConverter()));
1688 connect(converterModifyPB, SIGNAL(clicked()),
1689 this, SLOT(updateConverter()));
1690 connect(convertersLW, SIGNAL(currentRowChanged(int)),
1691 this, SLOT(switchConverter()));
1692 connect(converterFromCO, SIGNAL(activated(QString)),
1693 this, SLOT(changeConverter()));
1694 connect(converterToCO, SIGNAL(activated(QString)),
1695 this, SLOT(changeConverter()));
1696 connect(converterED, SIGNAL(textEdited(QString)),
1697 this, SLOT(changeConverter()));
1698 connect(converterFlagED, SIGNAL(textEdited(QString)),
1699 this, SLOT(changeConverter()));
1700 connect(converterNewPB, SIGNAL(clicked()),
1701 this, SIGNAL(changed()));
1702 connect(converterRemovePB, SIGNAL(clicked()),
1703 this, SIGNAL(changed()));
1704 connect(converterModifyPB, SIGNAL(clicked()),
1705 this, SIGNAL(changed()));
1706 connect(maxAgeLE, SIGNAL(textEdited(QString)),
1707 this, SIGNAL(changed()));
1708 connect(needauthForbiddenCB, SIGNAL(toggled(bool)),
1709 this, SIGNAL(changed()));
1711 converterED->setValidator(new NoNewLineValidator(converterED));
1712 converterFlagED->setValidator(new NoNewLineValidator(converterFlagED));
1713 maxAgeLE->setValidator(new QDoubleValidator(0, HUGE_VAL, 6, maxAgeLE));
1714 //converterDefGB->setFocusProxy(convertersLW);
1718 void PrefConverters::applyRC(LyXRC & rc) const
1720 rc.use_converter_cache = cacheCB->isChecked();
1721 rc.use_converter_needauth_forbidden = needauthForbiddenCB->isChecked();
1722 rc.use_converter_needauth = needauthCB->isChecked();
1723 rc.converter_cache_maxage = int(widgetToDouble(maxAgeLE) * 86400.0);
1727 static void setCheckboxBlockSignals(QCheckBox *cb, bool checked) {
1728 cb->blockSignals(true);
1729 cb->setChecked(checked);
1730 cb->blockSignals(false);
1734 void PrefConverters::updateRC(LyXRC const & rc)
1736 cacheCB->setChecked(rc.use_converter_cache);
1737 needauthForbiddenCB->setChecked(rc.use_converter_needauth_forbidden);
1738 setCheckboxBlockSignals(needauthCB, rc.use_converter_needauth);
1740 doubleToWidget(maxAgeLE, (double(rc.converter_cache_maxage) / 86400.0), 'g', 6);
1745 void PrefConverters::updateGui()
1747 QString const pattern("%1 -> %2");
1748 form_->formats().sort();
1749 form_->converters().update(form_->formats());
1750 // save current selection
1753 .arg(converterFromCO->currentText())
1754 .arg(converterToCO->currentText());
1756 converterFromCO->clear();
1757 converterToCO->clear();
1759 for (Format const & f : form_->formats()) {
1760 QString const name = toqstr(translateIfPossible(f.prettyname()));
1761 converterFromCO->addItem(name);
1762 converterToCO->addItem(name);
1765 // currentRowChanged(int) is also triggered when updating the listwidget
1766 // block signals to avoid unnecessary calls to switchConverter()
1767 convertersLW->blockSignals(true);
1768 convertersLW->clear();
1770 for (Converter const & c : form_->converters()) {
1771 QString const name =
1773 .arg(toqstr(translateIfPossible(c.From()->prettyname())))
1774 .arg(toqstr(translateIfPossible(c.To()->prettyname())));
1775 int type = form_->converters().getNumber(c.From()->name(),
1777 new QListWidgetItem(name, convertersLW, type);
1779 convertersLW->sortItems(Qt::AscendingOrder);
1780 convertersLW->blockSignals(false);
1782 // restore selection
1783 if (current != pattern.arg(QString()).arg(QString())) {
1784 QList<QListWidgetItem *> const item =
1785 convertersLW->findItems(current, Qt::MatchExactly);
1786 if (!item.isEmpty())
1787 convertersLW->setCurrentItem(item.at(0));
1790 // select first element if restoring failed
1791 if (convertersLW->currentRow() == -1)
1792 convertersLW->setCurrentRow(0);
1798 void PrefConverters::switchConverter()
1800 int const cnr = convertersLW->currentItem()->type();
1801 Converter const & c(form_->converters().get(cnr));
1802 converterFromCO->setCurrentIndex(form_->formats().getNumber(c.from()));
1803 converterToCO->setCurrentIndex(form_->formats().getNumber(c.to()));
1804 converterED->setText(toqstr(c.command()));
1805 converterFlagED->setText(toqstr(c.flags()));
1811 void PrefConverters::changeConverter()
1817 void PrefConverters::updateButtons()
1819 if (form_->formats().empty())
1821 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1822 Format const & to = form_->formats().get(converterToCO->currentIndex());
1823 int const sel = form_->converters().getNumber(from.name(), to.name());
1824 bool const known = sel >= 0;
1825 bool const valid = !(converterED->text().isEmpty()
1826 || from.name() == to.name());
1831 if (convertersLW->count() > 0) {
1832 int const cnr = convertersLW->currentItem()->type();
1833 Converter const & c = form_->converters().get(cnr);
1834 old_command = c.command();
1835 old_flag = c.flags();
1838 string const new_command = fromqstr(converterED->text());
1839 string const new_flag = fromqstr(converterFlagED->text());
1841 bool modified = (old_command != new_command || old_flag != new_flag);
1843 converterModifyPB->setEnabled(valid && known && modified);
1844 converterNewPB->setEnabled(valid && !known);
1845 converterRemovePB->setEnabled(known);
1847 maxAgeLE->setEnabled(cacheCB->isChecked());
1848 maxAgeLA->setEnabled(cacheCB->isChecked());
1853 // specify unique from/to or it doesn't appear. This is really bad UI
1854 // this is why we can use the same function for both new and modify
1855 void PrefConverters::updateConverter()
1857 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1858 Format const & to = form_->formats().get(converterToCO->currentIndex());
1859 string const flags = fromqstr(converterFlagED->text());
1860 string const command = fromqstr(converterED->text());
1862 Converter const * old =
1863 form_->converters().getConverter(from.name(), to.name());
1864 form_->converters().add(from.name(), to.name(), command, flags);
1867 form_->converters().updateLast(form_->formats());
1871 // Remove all files created by this converter from the cache, since
1872 // the modified converter might create different files.
1873 ConverterCache::get().remove_all(from.name(), to.name());
1877 void PrefConverters::removeConverter()
1879 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1880 Format const & to = form_->formats().get(converterToCO->currentIndex());
1881 form_->converters().erase(from.name(), to.name());
1885 // Remove all files created by this converter from the cache, since
1886 // a possible new converter might create different files.
1887 ConverterCache::get().remove_all(from.name(), to.name());
1891 void PrefConverters::on_cacheCB_stateChanged(int state)
1893 maxAgeLE->setEnabled(state == Qt::Checked);
1894 maxAgeLA->setEnabled(state == Qt::Checked);
1899 void PrefConverters::on_needauthForbiddenCB_toggled(bool checked)
1901 needauthCB->setEnabled(!checked);
1905 void PrefConverters::on_needauthCB_toggled(bool checked)
1912 int ret = frontend::Alert::prompt(
1913 _("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!"),
1914 0, 0, _("&No"), _("&Yes"));
1918 setCheckboxBlockSignals(needauthCB, true);
1922 /////////////////////////////////////////////////////////////////////
1926 /////////////////////////////////////////////////////////////////////
1928 class FormatValidator : public QValidator
1931 FormatValidator(QWidget *, Formats const & f);
1932 void fixup(QString & input) const;
1933 QValidator::State validate(QString & input, int & pos) const;
1935 virtual QString toString(Format const & format) const = 0;
1937 Formats const & formats_;
1941 FormatValidator::FormatValidator(QWidget * parent, Formats const & f)
1942 : QValidator(parent), formats_(f)
1947 void FormatValidator::fixup(QString & input) const
1949 Formats::const_iterator cit = formats_.begin();
1950 Formats::const_iterator end = formats_.end();
1951 for (; cit != end; ++cit) {
1952 QString const name = toString(*cit);
1953 if (distance(formats_.begin(), cit) == nr()) {
1961 QValidator::State FormatValidator::validate(QString & input, int & /*pos*/) const
1963 Formats::const_iterator cit = formats_.begin();
1964 Formats::const_iterator end = formats_.end();
1965 bool unknown = true;
1966 for (; unknown && cit != end; ++cit) {
1967 QString const name = toString(*cit);
1968 if (distance(formats_.begin(), cit) != nr())
1969 unknown = name != input;
1972 if (unknown && !input.isEmpty())
1973 return QValidator::Acceptable;
1975 return QValidator::Intermediate;
1979 int FormatValidator::nr() const
1981 QComboBox * p = qobject_cast<QComboBox *>(parent());
1982 return p->itemData(p->currentIndex()).toInt();
1986 /////////////////////////////////////////////////////////////////////
1988 // FormatNameValidator
1990 /////////////////////////////////////////////////////////////////////
1992 class FormatNameValidator : public FormatValidator
1995 FormatNameValidator(QWidget * parent, Formats const & f)
1996 : FormatValidator(parent, f)
1999 QString toString(Format const & format) const
2001 return toqstr(format.name());
2006 /////////////////////////////////////////////////////////////////////
2008 // FormatPrettynameValidator
2010 /////////////////////////////////////////////////////////////////////
2012 class FormatPrettynameValidator : public FormatValidator
2015 FormatPrettynameValidator(QWidget * parent, Formats const & f)
2016 : FormatValidator(parent, f)
2019 QString toString(Format const & format) const
2021 return toqstr(translateIfPossible(format.prettyname()));
2026 /////////////////////////////////////////////////////////////////////
2030 /////////////////////////////////////////////////////////////////////
2032 PrefFileformats::PrefFileformats(GuiPreferences * form)
2033 : PrefModule(catFiles, N_("File Formats"), form)
2037 formatED->setValidator(new FormatNameValidator(formatsCB, form_->formats()));
2038 formatsCB->setValidator(new FormatPrettynameValidator(formatsCB, form_->formats()));
2039 extensionsED->setValidator(new NoNewLineValidator(extensionsED));
2040 shortcutED->setValidator(new NoNewLineValidator(shortcutED));
2041 editorED->setValidator(new NoNewLineValidator(editorED));
2042 viewerED->setValidator(new NoNewLineValidator(viewerED));
2043 copierED->setValidator(new NoNewLineValidator(copierED));
2045 connect(documentCB, SIGNAL(clicked()),
2046 this, SLOT(setFlags()));
2047 connect(vectorCB, SIGNAL(clicked()),
2048 this, SLOT(setFlags()));
2049 connect(exportMenuCB, SIGNAL(clicked()),
2050 this, SLOT(setFlags()));
2051 connect(formatsCB->lineEdit(), SIGNAL(editingFinished()),
2052 this, SLOT(updatePrettyname()));
2053 connect(formatsCB->lineEdit(), SIGNAL(textEdited(QString)),
2054 this, SIGNAL(changed()));
2055 connect(defaultFormatCB, SIGNAL(activated(QString)),
2056 this, SIGNAL(changed()));
2057 connect(defaultOTFFormatCB, SIGNAL(activated(QString)),
2058 this, SIGNAL(changed()));
2059 connect(defaultPlatexFormatCB, SIGNAL(activated(QString)),
2060 this, SIGNAL(changed()));
2061 connect(viewerCO, SIGNAL(activated(int)),
2062 this, SIGNAL(changed()));
2063 connect(editorCO, SIGNAL(activated(int)),
2064 this, SIGNAL(changed()));
2070 string const l10n_shortcut(docstring const & prettyname, string const & shortcut)
2072 if (shortcut.empty())
2075 string l10n_format =
2076 to_utf8(_(to_utf8(prettyname) + '|' + shortcut));
2077 return split(l10n_format, '|');
2083 void PrefFileformats::applyRC(LyXRC & rc) const
2085 QString const default_format = defaultFormatCB->itemData(
2086 defaultFormatCB->currentIndex()).toString();
2087 rc.default_view_format = fromqstr(default_format);
2088 QString const default_otf_format = defaultOTFFormatCB->itemData(
2089 defaultOTFFormatCB->currentIndex()).toString();
2090 rc.default_otf_view_format = fromqstr(default_otf_format);
2091 QString const default_platex_format = defaultPlatexFormatCB->itemData(
2092 defaultPlatexFormatCB->currentIndex()).toString();
2093 rc.default_platex_view_format = fromqstr(default_platex_format);
2097 void PrefFileformats::updateRC(LyXRC const & rc)
2099 viewer_alternatives = rc.viewer_alternatives;
2100 editor_alternatives = rc.editor_alternatives;
2101 bool const init = defaultFormatCB->currentText().isEmpty();
2105 defaultFormatCB->findData(toqstr(rc.default_view_format));
2106 defaultFormatCB->setCurrentIndex(pos);
2107 pos = defaultOTFFormatCB->findData(toqstr(rc.default_otf_view_format));
2108 defaultOTFFormatCB->setCurrentIndex(pos);
2109 defaultOTFFormatCB->setCurrentIndex(pos);
2110 pos = defaultPlatexFormatCB->findData(toqstr(rc.default_platex_view_format));
2111 defaultPlatexFormatCB->setCurrentIndex(pos);
2112 defaultPlatexFormatCB->setCurrentIndex(pos);
2117 void PrefFileformats::updateView()
2119 QString const current = formatsCB->currentText();
2120 QString const current_def = defaultFormatCB->currentText();
2121 QString const current_def_otf = defaultOTFFormatCB->currentText();
2122 QString const current_def_platex = defaultPlatexFormatCB->currentText();
2124 // update comboboxes with formats
2125 formatsCB->blockSignals(true);
2126 defaultFormatCB->blockSignals(true);
2127 defaultOTFFormatCB->blockSignals(true);
2128 defaultPlatexFormatCB->blockSignals(true);
2130 defaultFormatCB->clear();
2131 defaultOTFFormatCB->clear();
2132 defaultPlatexFormatCB->clear();
2133 form_->formats().sort();
2134 for (Format const & f : form_->formats()) {
2135 QString const prettyname = toqstr(translateIfPossible(f.prettyname()));
2136 formatsCB->addItem(prettyname,
2137 QVariant(form_->formats().getNumber(f.name())));
2138 if (f.viewer().empty())
2140 if (form_->converters().isReachable("xhtml", f.name())
2141 || form_->converters().isReachable("dviluatex", f.name())
2142 || form_->converters().isReachable("luatex", f.name())
2143 || form_->converters().isReachable("xetex", f.name())) {
2144 defaultFormatCB->addItem(prettyname,
2145 QVariant(toqstr(f.name())));
2146 defaultOTFFormatCB->addItem(prettyname,
2147 QVariant(toqstr(f.name())));
2149 if (form_->converters().isReachable("latex", f.name())
2150 || form_->converters().isReachable("pdflatex", f.name()))
2151 defaultFormatCB->addItem(prettyname,
2152 QVariant(toqstr(f.name())));
2153 if (form_->converters().isReachable("platex", f.name()))
2154 defaultPlatexFormatCB->addItem(prettyname,
2155 QVariant(toqstr(f.name())));
2159 // restore selections
2160 int item = formatsCB->findText(current, Qt::MatchExactly);
2161 formatsCB->setCurrentIndex(item < 0 ? 0 : item);
2162 on_formatsCB_currentIndexChanged(item < 0 ? 0 : item);
2163 item = defaultFormatCB->findText(current_def, Qt::MatchExactly);
2164 defaultFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2165 item = defaultOTFFormatCB->findText(current_def_otf, Qt::MatchExactly);
2166 defaultOTFFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2167 item = defaultPlatexFormatCB->findText(current_def_platex, Qt::MatchExactly);
2168 defaultPlatexFormatCB->setCurrentIndex(item < 0 ? 0 : item);
2169 formatsCB->blockSignals(false);
2170 defaultFormatCB->blockSignals(false);
2171 defaultOTFFormatCB->blockSignals(false);
2172 defaultPlatexFormatCB->blockSignals(false);
2176 void PrefFileformats::on_formatsCB_currentIndexChanged(int i)
2178 if (form_->formats().empty())
2180 int const nr = formatsCB->itemData(i).toInt();
2181 Format const f = form_->formats().get(nr);
2183 formatED->setText(toqstr(f.name()));
2184 copierED->setText(toqstr(form_->movers().command(f.name())));
2185 extensionsED->setText(toqstr(f.extensions()));
2186 mimeED->setText(toqstr(f.mime()));
2187 shortcutED->setText(
2188 toqstr(l10n_shortcut(f.prettyname(), f.shortcut())));
2189 documentCB->setChecked((f.documentFormat()));
2190 vectorCB->setChecked((f.vectorFormat()));
2191 exportMenuCB->setChecked((f.inExportMenu()));
2192 exportMenuCB->setEnabled((f.documentFormat()));
2198 void PrefFileformats::setFlags()
2200 int flags = Format::none;
2201 if (documentCB->isChecked())
2202 flags |= Format::document;
2203 if (vectorCB->isChecked())
2204 flags |= Format::vector;
2205 if (exportMenuCB->isChecked())
2206 flags |= Format::export_menu;
2207 currentFormat().setFlags(flags);
2208 exportMenuCB->setEnabled(documentCB->isChecked());
2213 void PrefFileformats::on_copierED_textEdited(const QString & s)
2215 string const fmt = fromqstr(formatED->text());
2216 form_->movers().set(fmt, fromqstr(s));
2221 void PrefFileformats::on_extensionsED_textEdited(const QString & s)
2223 currentFormat().setExtensions(fromqstr(s));
2228 void PrefFileformats::on_viewerED_textEdited(const QString & s)
2230 currentFormat().setViewer(fromqstr(s));
2235 void PrefFileformats::on_editorED_textEdited(const QString & s)
2237 currentFormat().setEditor(fromqstr(s));
2242 void PrefFileformats::on_mimeED_textEdited(const QString & s)
2244 currentFormat().setMime(fromqstr(s));
2249 void PrefFileformats::on_shortcutED_textEdited(const QString & s)
2251 string const new_shortcut = fromqstr(s);
2252 if (new_shortcut == l10n_shortcut(currentFormat().prettyname(),
2253 currentFormat().shortcut()))
2255 currentFormat().setShortcut(new_shortcut);
2260 void PrefFileformats::on_formatED_editingFinished()
2262 string const newname = fromqstr(formatED->displayText());
2263 string const oldname = currentFormat().name();
2264 if (newname == oldname)
2266 if (form_->converters().formatIsUsed(oldname)) {
2267 Alert::error(_("Format in use"),
2268 _("You cannot change a format's short name "
2269 "if the format is used by a converter. "
2270 "Please remove the converter first."));
2275 currentFormat().setName(newname);
2280 void PrefFileformats::on_formatED_textChanged(const QString &)
2282 QString t = formatED->text();
2284 bool valid = formatED->validator()->validate(t, p) == QValidator::Acceptable;
2285 setValid(formatLA, valid);
2289 void PrefFileformats::on_formatsCB_editTextChanged(const QString &)
2291 QString t = formatsCB->currentText();
2293 bool valid = formatsCB->validator()->validate(t, p) == QValidator::Acceptable;
2294 setValid(formatsLA, valid);
2298 void PrefFileformats::updatePrettyname()
2300 QString const newname = formatsCB->currentText();
2301 if (newname == toqstr(translateIfPossible(currentFormat().prettyname())))
2304 currentFormat().setPrettyname(qstring_to_ucs4(newname));
2312 void updateComboBox(LyXRC::Alternatives const & alts,
2313 string const & fmt, QComboBox * combo)
2315 LyXRC::Alternatives::const_iterator it =
2317 if (it != alts.end()) {
2318 LyXRC::CommandSet const & cmds = it->second;
2319 LyXRC::CommandSet::const_iterator sit =
2321 LyXRC::CommandSet::const_iterator const sen =
2323 for (; sit != sen; ++sit) {
2324 QString const qcmd = toqstr(*sit);
2325 combo->addItem(qcmd, qcmd);
2332 void PrefFileformats::updateViewers()
2334 Format const f = currentFormat();
2335 viewerCO->blockSignals(true);
2337 viewerCO->addItem(qt_("None"), QString());
2338 updateComboBox(viewer_alternatives, f.name(), viewerCO);
2339 viewerCO->addItem(qt_("Custom"), QString("custom viewer"));
2340 viewerCO->blockSignals(false);
2342 int pos = viewerCO->findData(toqstr(f.viewer()));
2345 viewerED->setEnabled(false);
2346 viewerCO->setCurrentIndex(pos);
2348 viewerED->setEnabled(true);
2349 viewerED->setText(toqstr(f.viewer()));
2350 viewerCO->setCurrentIndex(viewerCO->findData(toqstr("custom viewer")));
2355 void PrefFileformats::updateEditors()
2357 Format const f = currentFormat();
2358 editorCO->blockSignals(true);
2360 editorCO->addItem(qt_("None"), QString());
2361 updateComboBox(editor_alternatives, f.name(), editorCO);
2362 editorCO->addItem(qt_("Custom"), QString("custom editor"));
2363 editorCO->blockSignals(false);
2365 int pos = editorCO->findData(toqstr(f.editor()));
2368 editorED->setEnabled(false);
2369 editorCO->setCurrentIndex(pos);
2371 editorED->setEnabled(true);
2372 editorED->setText(toqstr(f.editor()));
2373 editorCO->setCurrentIndex(editorCO->findData(toqstr("custom editor")));
2378 void PrefFileformats::on_viewerCO_currentIndexChanged(int i)
2380 bool const custom = viewerCO->itemData(i).toString() == "custom viewer";
2381 viewerED->setEnabled(custom);
2383 currentFormat().setViewer(fromqstr(viewerCO->itemData(i).toString()));
2387 void PrefFileformats::on_editorCO_currentIndexChanged(int i)
2389 bool const custom = editorCO->itemData(i).toString() == "custom editor";
2390 editorED->setEnabled(custom);
2392 currentFormat().setEditor(fromqstr(editorCO->itemData(i).toString()));
2396 Format & PrefFileformats::currentFormat()
2398 int const i = formatsCB->currentIndex();
2399 int const nr = formatsCB->itemData(i).toInt();
2400 return form_->formats().get(nr);
2404 void PrefFileformats::on_formatNewPB_clicked()
2406 form_->formats().add("", "", docstring(), "", "", "", "", Format::none);
2408 formatsCB->setCurrentIndex(0);
2409 formatsCB->setFocus(Qt::OtherFocusReason);
2413 void PrefFileformats::on_formatRemovePB_clicked()
2415 int const i = formatsCB->currentIndex();
2416 int const nr = formatsCB->itemData(i).toInt();
2417 string const current_text = form_->formats().get(nr).name();
2418 if (form_->converters().formatIsUsed(current_text)) {
2419 Alert::error(_("Format in use"),
2420 _("Cannot remove a Format used by a Converter. "
2421 "Remove the converter first."));
2425 form_->formats().erase(current_text);
2428 on_formatsCB_editTextChanged(formatsCB->currentText());
2433 /////////////////////////////////////////////////////////////////////
2437 /////////////////////////////////////////////////////////////////////
2439 PrefLanguage::PrefLanguage(GuiPreferences * form)
2440 : PrefModule(catLanguage, N_("Language"), form)
2444 connect(visualCursorRB, SIGNAL(clicked()),
2445 this, SIGNAL(changed()));
2446 connect(logicalCursorRB, SIGNAL(clicked()),
2447 this, SIGNAL(changed()));
2448 connect(markForeignCB, SIGNAL(clicked()),
2449 this, SIGNAL(changed()));
2450 connect(autoBeginCB, SIGNAL(clicked()),
2451 this, SIGNAL(changed()));
2452 connect(autoEndCB, SIGNAL(clicked()),
2453 this, SIGNAL(changed()));
2454 connect(languagePackageCO, SIGNAL(activated(int)),
2455 this, SIGNAL(changed()));
2456 connect(languagePackageED, SIGNAL(textChanged(QString)),
2457 this, SIGNAL(changed()));
2458 connect(globalCB, SIGNAL(clicked()),
2459 this, SIGNAL(changed()));
2460 connect(startCommandED, SIGNAL(textChanged(QString)),
2461 this, SIGNAL(changed()));
2462 connect(endCommandED, SIGNAL(textChanged(QString)),
2463 this, SIGNAL(changed()));
2464 connect(uiLanguageCO, SIGNAL(activated(int)),
2465 this, SIGNAL(changed()));
2466 connect(defaultDecimalPointLE, SIGNAL(textChanged(QString)),
2467 this, SIGNAL(changed()));
2468 connect(defaultLengthUnitCO, SIGNAL(activated(int)),
2469 this, SIGNAL(changed()));
2471 languagePackageED->setValidator(new NoNewLineValidator(languagePackageED));
2472 startCommandED->setValidator(new NoNewLineValidator(startCommandED));
2473 endCommandED->setValidator(new NoNewLineValidator(endCommandED));
2475 defaultDecimalPointLE->setInputMask("X; ");
2476 defaultDecimalPointLE->setMaxLength(1);
2478 defaultLengthUnitCO->addItem(lyx::qt_(unit_name_gui[Length::CM]), Length::CM);
2479 defaultLengthUnitCO->addItem(lyx::qt_(unit_name_gui[Length::IN]), Length::IN);
2481 QAbstractItemModel * language_model = guiApp->languageModel();
2482 language_model->sort(0);
2483 uiLanguageCO->blockSignals(true);
2484 uiLanguageCO->clear();
2485 uiLanguageCO->addItem(qt_("Default"), toqstr("auto"));
2486 for (int i = 0; i != language_model->rowCount(); ++i) {
2487 QModelIndex index = language_model->index(i, 0);
2488 // Filter the list based on the available translation and add
2489 // each language code only once
2490 string const name = fromqstr(index.data(Qt::UserRole).toString());
2491 Language const * lang = languages.getLanguage(name);
2494 // never remove the currently selected language
2495 if (name != form->rc().gui_language
2496 && name != lyxrc.gui_language
2497 && (!Messages::available(lang->code())
2498 || !lang->hasGuiSupport()))
2500 uiLanguageCO->addItem(index.data(Qt::DisplayRole).toString(),
2501 index.data(Qt::UserRole).toString());
2503 uiLanguageCO->blockSignals(false);
2507 void PrefLanguage::on_uiLanguageCO_currentIndexChanged(int)
2509 QMessageBox::information(this, qt_("LyX needs to be restarted!"),
2510 qt_("The change of user interface language will be fully "
2511 "effective only after a restart."));
2515 void PrefLanguage::on_languagePackageCO_currentIndexChanged(int i)
2517 languagePackageED->setEnabled(i == 2);
2521 void PrefLanguage::applyRC(LyXRC & rc) const
2523 rc.visual_cursor = visualCursorRB->isChecked();
2524 rc.mark_foreign_language = markForeignCB->isChecked();
2525 rc.language_auto_begin = autoBeginCB->isChecked();
2526 rc.language_auto_end = autoEndCB->isChecked();
2527 int const p = languagePackageCO->currentIndex();
2529 rc.language_package_selection = LyXRC::LP_AUTO;
2531 rc.language_package_selection = LyXRC::LP_BABEL;
2533 rc.language_package_selection = LyXRC::LP_CUSTOM;
2535 rc.language_package_selection = LyXRC::LP_NONE;
2536 rc.language_custom_package = fromqstr(languagePackageED->text());
2537 rc.language_global_options = globalCB->isChecked();
2538 rc.language_command_begin = fromqstr(startCommandED->text());
2539 rc.language_command_end = fromqstr(endCommandED->text());
2540 rc.gui_language = fromqstr(
2541 uiLanguageCO->itemData(uiLanguageCO->currentIndex()).toString());
2542 rc.default_decimal_point = fromqstr(defaultDecimalPointLE->text());
2543 rc.default_length_unit = (Length::UNIT) defaultLengthUnitCO->itemData(defaultLengthUnitCO->currentIndex()).toInt();
2547 void PrefLanguage::updateRC(LyXRC const & rc)
2549 if (rc.visual_cursor)
2550 visualCursorRB->setChecked(true);
2552 logicalCursorRB->setChecked(true);
2553 markForeignCB->setChecked(rc.mark_foreign_language);
2554 autoBeginCB->setChecked(rc.language_auto_begin);
2555 autoEndCB->setChecked(rc.language_auto_end);
2556 languagePackageCO->setCurrentIndex(rc.language_package_selection);
2557 languagePackageED->setText(toqstr(rc.language_custom_package));
2558 languagePackageED->setEnabled(languagePackageCO->currentIndex() == 2);
2559 globalCB->setChecked(rc.language_global_options);
2560 startCommandED->setText(toqstr(rc.language_command_begin));
2561 endCommandED->setText(toqstr(rc.language_command_end));
2562 defaultDecimalPointLE->setText(toqstr(rc.default_decimal_point));
2563 int pos = defaultLengthUnitCO->findData(int(rc.default_length_unit));
2564 defaultLengthUnitCO->setCurrentIndex(pos);
2566 pos = uiLanguageCO->findData(toqstr(rc.gui_language));
2567 uiLanguageCO->blockSignals(true);
2568 uiLanguageCO->setCurrentIndex(pos);
2569 uiLanguageCO->blockSignals(false);
2573 /////////////////////////////////////////////////////////////////////
2575 // PrefUserInterface
2577 /////////////////////////////////////////////////////////////////////
2579 PrefUserInterface::PrefUserInterface(GuiPreferences * form)
2580 : PrefModule(catLookAndFeel, N_("User Interface"), form)
2584 connect(uiFilePB, SIGNAL(clicked()),
2585 this, SLOT(selectUi()));
2586 connect(uiFileED, SIGNAL(textChanged(QString)),
2587 this, SIGNAL(changed()));
2588 connect(iconSetCO, SIGNAL(activated(int)),
2589 this, SIGNAL(changed()));
2590 connect(useSystemThemeIconsCB, SIGNAL(clicked()),
2591 this, SIGNAL(changed()));
2592 connect(lastfilesSB, SIGNAL(valueChanged(int)),
2593 this, SIGNAL(changed()));
2594 connect(tooltipCB, SIGNAL(toggled(bool)),
2595 this, SIGNAL(changed()));
2596 lastfilesSB->setMaximum(maxlastfiles);
2598 iconSetCO->addItem(qt_("Default"), QString());
2599 iconSetCO->addItem(qt_("Classic"), "classic");
2600 iconSetCO->addItem(qt_("Oxygen"), "oxygen");
2602 #if (!(defined Q_WS_X11 || defined(QPA_XCB)) || QT_VERSION < 0x040600)
2603 useSystemThemeIconsCB->hide();
2608 void PrefUserInterface::applyRC(LyXRC & rc) const
2610 rc.icon_set = fromqstr(iconSetCO->itemData(
2611 iconSetCO->currentIndex()).toString());
2613 rc.ui_file = internal_path(fromqstr(uiFileED->text()));
2614 rc.use_system_theme_icons = useSystemThemeIconsCB->isChecked();
2615 rc.num_lastfiles = lastfilesSB->value();
2616 rc.use_tooltip = tooltipCB->isChecked();
2620 void PrefUserInterface::updateRC(LyXRC const & rc)
2622 int iconset = iconSetCO->findData(toqstr(rc.icon_set));
2625 iconSetCO->setCurrentIndex(iconset);
2626 useSystemThemeIconsCB->setChecked(rc.use_system_theme_icons);
2627 uiFileED->setText(toqstr(external_path(rc.ui_file)));
2628 lastfilesSB->setValue(rc.num_lastfiles);
2629 tooltipCB->setChecked(rc.use_tooltip);
2633 void PrefUserInterface::selectUi()
2635 QString file = form_->browseUI(internalPath(uiFileED->text()));
2636 if (!file.isEmpty())
2637 uiFileED->setText(file);
2641 /////////////////////////////////////////////////////////////////////
2643 // PrefDocumentHandling
2645 /////////////////////////////////////////////////////////////////////
2647 PrefDocHandling::PrefDocHandling(GuiPreferences * form)
2648 : PrefModule(catLookAndFeel, N_("Document Handling"), form)
2652 connect(autoSaveCB, SIGNAL(toggled(bool)),
2653 autoSaveSB, SLOT(setEnabled(bool)));
2654 connect(autoSaveCB, SIGNAL(toggled(bool)),
2655 TextLabel1, SLOT(setEnabled(bool)));
2656 connect(openDocumentsInTabsCB, SIGNAL(clicked()),
2657 this, SIGNAL(changed()));
2658 connect(singleInstanceCB, SIGNAL(clicked()),
2659 this, SIGNAL(changed()));
2660 connect(singleCloseTabButtonCB, SIGNAL(clicked()),
2661 this, SIGNAL(changed()));
2662 connect(closeLastViewCO, SIGNAL(activated(int)),
2663 this, SIGNAL(changed()));
2664 connect(restoreCursorCB, SIGNAL(clicked()),
2665 this, SIGNAL(changed()));
2666 connect(loadSessionCB, SIGNAL(clicked()),
2667 this, SIGNAL(changed()));
2668 connect(allowGeometrySessionCB, SIGNAL(clicked()),
2669 this, SIGNAL(changed()));
2670 connect(autoSaveSB, SIGNAL(valueChanged(int)),
2671 this, SIGNAL(changed()));
2672 connect(autoSaveCB, SIGNAL(clicked()),
2673 this, SIGNAL(changed()));
2674 connect(backupCB, SIGNAL(clicked()),
2675 this, SIGNAL(changed()));
2676 connect(saveCompressedCB, SIGNAL(clicked()),
2677 this, SIGNAL(changed()));
2678 connect(saveOriginCB, SIGNAL(clicked()),
2679 this, SIGNAL(changed()));
2683 void PrefDocHandling::applyRC(LyXRC & rc) const
2685 rc.use_lastfilepos = restoreCursorCB->isChecked();
2686 rc.load_session = loadSessionCB->isChecked();
2687 rc.allow_geometry_session = allowGeometrySessionCB->isChecked();
2688 rc.autosave = autoSaveCB->isChecked() ? autoSaveSB->value() * 60 : 0;
2689 rc.make_backup = backupCB->isChecked();
2690 rc.save_compressed = saveCompressedCB->isChecked();
2691 rc.save_origin = saveOriginCB->isChecked();
2692 rc.open_buffers_in_tabs = openDocumentsInTabsCB->isChecked();
2693 rc.single_instance = singleInstanceCB->isChecked();
2694 rc.single_close_tab_button = singleCloseTabButtonCB->isChecked();
2696 switch (closeLastViewCO->currentIndex()) {
2698 rc.close_buffer_with_last_view = "yes";
2701 rc.close_buffer_with_last_view = "no";
2704 rc.close_buffer_with_last_view = "ask";
2712 void PrefDocHandling::updateRC(LyXRC const & rc)
2714 restoreCursorCB->setChecked(rc.use_lastfilepos);
2715 loadSessionCB->setChecked(rc.load_session);
2716 allowGeometrySessionCB->setChecked(rc.allow_geometry_session);
2717 // convert to minutes
2718 bool autosave = rc.autosave > 0;
2719 int mins = rc.autosave / 60;
2722 autoSaveSB->setValue(mins);
2723 autoSaveCB->setChecked(autosave);
2724 autoSaveSB->setEnabled(autosave);
2725 backupCB->setChecked(rc.make_backup);
2726 saveCompressedCB->setChecked(rc.save_compressed);
2727 saveOriginCB->setChecked(rc.save_origin);
2728 openDocumentsInTabsCB->setChecked(rc.open_buffers_in_tabs);
2729 singleInstanceCB->setChecked(rc.single_instance && !rc.lyxpipes.empty());
2730 singleInstanceCB->setEnabled(!rc.lyxpipes.empty());
2731 singleCloseTabButtonCB->setChecked(rc.single_close_tab_button);
2732 if (rc.close_buffer_with_last_view == "yes")
2733 closeLastViewCO->setCurrentIndex(0);
2734 else if (rc.close_buffer_with_last_view == "no")
2735 closeLastViewCO->setCurrentIndex(1);
2736 else if (rc.close_buffer_with_last_view == "ask")
2737 closeLastViewCO->setCurrentIndex(2);
2741 void PrefDocHandling::on_clearSessionPB_clicked()
2743 guiApp->clearSession();
2748 /////////////////////////////////////////////////////////////////////
2752 /////////////////////////////////////////////////////////////////////
2754 PrefEdit::PrefEdit(GuiPreferences * form)
2755 : PrefModule(catEditing, N_("Control"), form)
2759 connect(cursorFollowsCB, SIGNAL(clicked()),
2760 this, SIGNAL(changed()));
2761 connect(scrollBelowCB, SIGNAL(clicked()),
2762 this, SIGNAL(changed()));
2763 connect(macLikeCursorMovementCB, SIGNAL(clicked()),
2764 this, SIGNAL(changed()));
2765 connect(sortEnvironmentsCB, SIGNAL(clicked()),
2766 this, SIGNAL(changed()));
2767 connect(groupEnvironmentsCB, SIGNAL(clicked()),
2768 this, SIGNAL(changed()));
2769 connect(macroEditStyleCO, SIGNAL(activated(int)),
2770 this, SIGNAL(changed()));
2771 connect(cursorWidthSB, SIGNAL(valueChanged(int)),
2772 this, SIGNAL(changed()));
2773 connect(fullscreenLimitGB, SIGNAL(clicked()),
2774 this, SIGNAL(changed()));
2775 connect(fullscreenWidthSB, SIGNAL(valueChanged(int)),
2776 this, SIGNAL(changed()));
2777 connect(toggleTabbarCB, SIGNAL(toggled(bool)),
2778 this, SIGNAL(changed()));
2779 connect(toggleMenubarCB, SIGNAL(toggled(bool)),
2780 this, SIGNAL(changed()));
2781 connect(toggleScrollbarCB, SIGNAL(toggled(bool)),
2782 this, SIGNAL(changed()));
2783 connect(toggleStatusbarCB, SIGNAL(toggled(bool)),
2784 this, SIGNAL(changed()));
2785 connect(toggleToolbarsCB, SIGNAL(toggled(bool)),
2786 this, SIGNAL(changed()));
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.sort_layouts = sortEnvironmentsCB->isChecked();
2796 rc.group_layouts = groupEnvironmentsCB->isChecked();
2797 switch (macroEditStyleCO->currentIndex()) {
2798 case 0: rc.macro_edit_style = LyXRC::MACRO_EDIT_INLINE_BOX; break;
2799 case 1: rc.macro_edit_style = LyXRC::MACRO_EDIT_INLINE; break;
2800 case 2: rc.macro_edit_style = LyXRC::MACRO_EDIT_LIST; break;
2802 rc.cursor_width = cursorWidthSB->value();
2803 rc.full_screen_toolbars = toggleToolbarsCB->isChecked();
2804 rc.full_screen_scrollbar = toggleScrollbarCB->isChecked();
2805 rc.full_screen_statusbar = toggleStatusbarCB->isChecked();
2806 rc.full_screen_tabbar = toggleTabbarCB->isChecked();
2807 rc.full_screen_menubar = toggleMenubarCB->isChecked();
2808 rc.full_screen_width = fullscreenWidthSB->value();
2809 rc.full_screen_limit = fullscreenLimitGB->isChecked();
2813 void PrefEdit::updateRC(LyXRC const & rc)
2815 cursorFollowsCB->setChecked(rc.cursor_follows_scrollbar);
2816 scrollBelowCB->setChecked(rc.scroll_below_document);
2817 macLikeCursorMovementCB->setChecked(rc.mac_like_cursor_movement);
2818 sortEnvironmentsCB->setChecked(rc.sort_layouts);
2819 groupEnvironmentsCB->setChecked(rc.group_layouts);
2820 macroEditStyleCO->setCurrentIndex(rc.macro_edit_style);
2821 cursorWidthSB->setValue(rc.cursor_width);
2822 toggleScrollbarCB->setChecked(rc.full_screen_scrollbar);
2823 toggleStatusbarCB->setChecked(rc.full_screen_statusbar);
2824 toggleToolbarsCB->setChecked(rc.full_screen_toolbars);
2825 toggleTabbarCB->setChecked(rc.full_screen_tabbar);
2826 toggleMenubarCB->setChecked(rc.full_screen_menubar);
2827 fullscreenWidthSB->setValue(rc.full_screen_width);
2828 fullscreenLimitGB->setChecked(rc.full_screen_limit);
2832 /////////////////////////////////////////////////////////////////////
2836 /////////////////////////////////////////////////////////////////////
2839 GuiShortcutDialog::GuiShortcutDialog(QWidget * parent) : QDialog(parent)
2841 Ui::shortcutUi::setupUi(this);
2842 QDialog::setModal(true);
2846 PrefShortcuts::PrefShortcuts(GuiPreferences * form)
2847 : PrefModule(catEditing, N_("Shortcuts"), form),
2848 editItem_(0), mathItem_(0), bufferItem_(0), layoutItem_(0),
2853 shortcutsTW->setColumnCount(2);
2854 shortcutsTW->headerItem()->setText(0, qt_("Function"));
2855 shortcutsTW->headerItem()->setText(1, qt_("Shortcut"));
2856 shortcutsTW->setSortingEnabled(true);
2857 // Multi-selection can be annoying.
2858 // shortcutsTW->setSelectionMode(QAbstractItemView::MultiSelection);
2860 connect(bindFilePB, SIGNAL(clicked()),
2861 this, SLOT(selectBind()));
2862 connect(bindFileED, SIGNAL(textChanged(QString)),
2863 this, SIGNAL(changed()));
2865 shortcut_ = new GuiShortcutDialog(this);
2866 shortcut_bc_.setPolicy(ButtonPolicy::OkCancelPolicy);
2867 shortcut_bc_.setOK(shortcut_->buttonBox->button(QDialogButtonBox::Ok));
2868 shortcut_bc_.setCancel(shortcut_->buttonBox->button(QDialogButtonBox::Cancel));
2870 connect(shortcut_->buttonBox, SIGNAL(accepted()),
2871 this, SIGNAL(changed()));
2872 connect(shortcut_->buttonBox, SIGNAL(rejected()),
2873 shortcut_, SLOT(reject()));
2874 connect(shortcut_->clearPB, SIGNAL(clicked()),
2875 this, SLOT(shortcutClearPressed()));
2876 connect(shortcut_->removePB, SIGNAL(clicked()),
2877 this, SLOT(shortcutRemovePressed()));
2878 connect(shortcut_->buttonBox, SIGNAL(accepted()),
2879 this, SLOT(shortcutOkPressed()));
2880 connect(shortcut_->buttonBox, SIGNAL(rejected()),
2881 this, SLOT(shortcutCancelPressed()));
2885 void PrefShortcuts::applyRC(LyXRC & rc) const
2887 rc.bind_file = internal_path(fromqstr(bindFileED->text()));
2888 // write user_bind and user_unbind to .lyx/bind/user.bind
2889 FileName bind_dir(addPath(package().user_support().absFileName(), "bind"));
2890 if (!bind_dir.exists() && !bind_dir.createDirectory(0777)) {
2891 lyxerr << "LyX could not create the user bind directory '"
2892 << bind_dir << "'. All user-defined key bindings will be lost." << endl;
2895 if (!bind_dir.isDirWritable()) {
2896 lyxerr << "LyX could not write to the user bind directory '"
2897 << bind_dir << "'. All user-defined key bindings will be lost." << endl;
2900 FileName user_bind_file(bind_dir.absFileName() + "/user.bind");
2901 user_unbind_.write(user_bind_file.toFilesystemEncoding(), false, true);
2902 user_bind_.write(user_bind_file.toFilesystemEncoding(), true, false);
2903 // immediately apply the keybindings. Why this is not done before?
2904 // The good thing is that the menus are updated automatically.
2905 theTopLevelKeymap().clear();
2906 theTopLevelKeymap().read("site");
2907 theTopLevelKeymap().read(rc.bind_file, 0, KeyMap::Fallback);
2908 theTopLevelKeymap().read("user", 0, KeyMap::MissingOK);
2912 void PrefShortcuts::updateRC(LyXRC const & rc)
2914 bindFileED->setText(toqstr(external_path(rc.bind_file)));
2916 system_bind_.clear();
2918 user_unbind_.clear();
2919 system_bind_.read("site");
2920 system_bind_.read(rc.bind_file);
2921 // \unbind in user.bind is added to user_unbind_
2922 user_bind_.read("user", &user_unbind_, KeyMap::MissingOK);
2923 updateShortcutsTW();
2927 void PrefShortcuts::updateShortcutsTW()
2929 shortcutsTW->clear();
2931 editItem_ = new QTreeWidgetItem(shortcutsTW);
2932 editItem_->setText(0, qt_("Cursor, Mouse and Editing Functions"));
2933 editItem_->setFlags(editItem_->flags() & ~Qt::ItemIsSelectable);
2935 mathItem_ = new QTreeWidgetItem(shortcutsTW);
2936 mathItem_->setText(0, qt_("Mathematical Symbols"));
2937 mathItem_->setFlags(mathItem_->flags() & ~Qt::ItemIsSelectable);
2939 bufferItem_ = new QTreeWidgetItem(shortcutsTW);
2940 bufferItem_->setText(0, qt_("Document and Window"));
2941 bufferItem_->setFlags(bufferItem_->flags() & ~Qt::ItemIsSelectable);
2943 layoutItem_ = new QTreeWidgetItem(shortcutsTW);
2944 layoutItem_->setText(0, qt_("Font, Layouts and Textclasses"));
2945 layoutItem_->setFlags(layoutItem_->flags() & ~Qt::ItemIsSelectable);
2947 systemItem_ = new QTreeWidgetItem(shortcutsTW);
2948 systemItem_->setText(0, qt_("System and Miscellaneous"));
2949 systemItem_->setFlags(systemItem_->flags() & ~Qt::ItemIsSelectable);
2951 // listBindings(unbound=true) lists all bound and unbound lfuns
2952 // Items in this list is tagged by its source.
2953 KeyMap::BindingList bindinglist = system_bind_.listBindings(true,
2955 KeyMap::BindingList user_bindinglist = user_bind_.listBindings(false,
2957 KeyMap::BindingList user_unbindinglist = user_unbind_.listBindings(false,
2958 KeyMap::UserUnbind);
2959 bindinglist.insert(bindinglist.end(), user_bindinglist.begin(),
2960 user_bindinglist.end());
2961 bindinglist.insert(bindinglist.end(), user_unbindinglist.begin(),
2962 user_unbindinglist.end());
2964 KeyMap::BindingList::const_iterator it = bindinglist.begin();
2965 KeyMap::BindingList::const_iterator it_end = bindinglist.end();
2966 for (; it != it_end; ++it)
2967 insertShortcutItem(it->request, it->sequence, it->tag);
2969 shortcutsTW->sortItems(0, Qt::AscendingOrder);
2970 on_shortcutsTW_itemSelectionChanged();
2971 on_searchLE_textEdited();
2972 shortcutsTW->resizeColumnToContents(0);
2977 KeyMap::ItemType PrefShortcuts::itemType(QTreeWidgetItem & item)
2979 return static_cast<KeyMap::ItemType>(item.data(0, Qt::UserRole).toInt());
2984 bool PrefShortcuts::isAlwaysHidden(QTreeWidgetItem & item)
2986 // Hide rebound system settings that are empty
2987 return itemType(item) == KeyMap::UserUnbind && item.text(1).isEmpty();
2991 void PrefShortcuts::setItemType(QTreeWidgetItem * item, KeyMap::ItemType tag)
2993 item->setData(0, Qt::UserRole, QVariant(tag));
2997 case KeyMap::System:
2999 case KeyMap::UserBind:
3002 case KeyMap::UserUnbind:
3003 font.setStrikeOut(true);
3005 // this item is not displayed now.
3006 case KeyMap::UserExtraUnbind:
3007 font.setStrikeOut(true);
3010 item->setHidden(isAlwaysHidden(*item));
3011 item->setFont(1, font);
3015 QTreeWidgetItem * PrefShortcuts::insertShortcutItem(FuncRequest const & lfun,
3016 KeySequence const & seq, KeyMap::ItemType tag)
3018 FuncCode const action = lfun.action();
3019 string const action_name = lyxaction.getActionName(action);
3020 QString const lfun_name = toqstr(from_utf8(action_name)
3021 + ' ' + lfun.argument());
3022 QString const shortcut = toqstr(seq.print(KeySequence::ForGui));
3024 QTreeWidgetItem * newItem = 0;
3025 // for unbind items, try to find an existing item in the system bind list
3026 if (tag == KeyMap::UserUnbind) {
3027 QList<QTreeWidgetItem*> const items = shortcutsTW->findItems(lfun_name,
3028 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 0);
3029 for (int i = 0; i < items.size(); ++i) {
3030 if (items[i]->text(1) == shortcut) {
3035 // if not found, this unbind item is KeyMap::UserExtraUnbind
3036 // Such an item is not displayed to avoid confusion (what is
3037 // unmatched removed?).
3043 switch(lyxaction.getActionType(action)) {
3044 case LyXAction::Hidden:
3046 case LyXAction::Edit:
3047 newItem = new QTreeWidgetItem(editItem_);
3049 case LyXAction::Math:
3050 newItem = new QTreeWidgetItem(mathItem_);
3052 case LyXAction::Buffer:
3053 newItem = new QTreeWidgetItem(bufferItem_);
3055 case LyXAction::Layout:
3056 newItem = new QTreeWidgetItem(layoutItem_);
3058 case LyXAction::System:
3059 newItem = new QTreeWidgetItem(systemItem_);
3062 // this should not happen
3063 newItem = new QTreeWidgetItem(shortcutsTW);
3067 newItem->setText(0, lfun_name);
3068 newItem->setText(1, shortcut);
3069 // record BindFile representation to recover KeySequence when needed.
3070 newItem->setData(1, Qt::UserRole, toqstr(seq.print(KeySequence::BindFile)));
3071 setItemType(newItem, tag);
3076 void PrefShortcuts::on_shortcutsTW_itemSelectionChanged()
3078 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
3079 removePB->setEnabled(!items.isEmpty() && !items[0]->text(1).isEmpty());
3080 modifyPB->setEnabled(!items.isEmpty());
3081 if (items.isEmpty())
3084 if (itemType(*items[0]) == KeyMap::UserUnbind)
3085 removePB->setText(qt_("Res&tore"));
3087 removePB->setText(qt_("Remo&ve"));
3091 void PrefShortcuts::on_shortcutsTW_itemDoubleClicked()
3097 void PrefShortcuts::modifyShortcut()
3099 QTreeWidgetItem * item = shortcutsTW->currentItem();
3100 if (item->flags() & Qt::ItemIsSelectable) {
3101 shortcut_->lfunLE->setText(item->text(0));
3102 save_lfun_ = item->text(0).trimmed();
3103 shortcut_->shortcutWG->setText(item->text(1));
3105 seq.parse(fromqstr(item->data(1, Qt::UserRole).toString()));
3106 shortcut_->shortcutWG->setKeySequence(seq);
3107 shortcut_->shortcutWG->setFocus();
3113 void PrefShortcuts::unhideEmpty(QString const & lfun, bool select)
3115 // list of items that match lfun
3116 QList<QTreeWidgetItem*> items = shortcutsTW->findItems(lfun,
3117 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 0);
3118 for (int i = 0; i < items.size(); ++i) {
3119 QTreeWidgetItem * item = items[i];
3120 if (isAlwaysHidden(*item)) {
3121 setItemType(item, KeyMap::System);
3123 shortcutsTW->setCurrentItem(item);
3130 void PrefShortcuts::removeShortcut()
3132 // it seems that only one item can be selected, but I am
3133 // removing all selected items anyway.
3134 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
3135 for (int i = 0; i < items.size(); ++i) {
3136 string shortcut = fromqstr(items[i]->data(1, Qt::UserRole).toString());
3137 string lfun = fromqstr(items[i]->text(0));
3138 FuncRequest func = lyxaction.lookupFunc(lfun);
3140 switch (itemType(*items[i])) {
3141 case KeyMap::System: {
3142 // for system bind, we do not touch the item
3143 // but add an user unbind item
3144 user_unbind_.bind(shortcut, func);
3145 setItemType(items[i], KeyMap::UserUnbind);
3146 removePB->setText(qt_("Res&tore"));
3149 case KeyMap::UserBind: {
3150 // for user_bind, we remove this bind
3151 QTreeWidgetItem * parent = items[i]->parent();
3152 int itemIdx = parent->indexOfChild(items[i]);
3153 parent->takeChild(itemIdx);
3155 shortcutsTW->scrollToItem(parent->child(itemIdx - 1));
3157 shortcutsTW->scrollToItem(parent);
3158 user_bind_.unbind(shortcut, func);
3159 // If this user binding hid an empty system binding, unhide the
3160 // latter and select it.
3161 unhideEmpty(items[i]->text(0), true);
3164 case KeyMap::UserUnbind: {
3165 // for user_unbind, we remove the unbind, and the item
3166 // become KeyMap::System again.
3168 seq.parse(shortcut);
3169 // Ask the user to replace current binding
3170 if (!validateNewShortcut(func, seq, QString()))
3172 user_unbind_.unbind(shortcut, func);
3173 setItemType(items[i], KeyMap::System);
3174 removePB->setText(qt_("Remo&ve"));
3177 case KeyMap::UserExtraUnbind: {
3178 // for user unbind that is not in system bind file,
3179 // remove this unbind file
3180 QTreeWidgetItem * parent = items[i]->parent();
3181 parent->takeChild(parent->indexOfChild(items[i]));
3182 user_unbind_.unbind(shortcut, func);
3189 void PrefShortcuts::deactivateShortcuts(QList<QTreeWidgetItem*> const & items)
3191 for (int i = 0; i < items.size(); ++i) {
3192 string shortcut = fromqstr(items[i]->data(1, Qt::UserRole).toString());
3193 string lfun = fromqstr(items[i]->text(0));
3194 FuncRequest func = lyxaction.lookupFunc(lfun);
3196 switch (itemType(*items[i])) {
3197 case KeyMap::System:
3198 // for system bind, we do not touch the item
3199 // but add an user unbind item
3200 user_unbind_.bind(shortcut, func);
3201 setItemType(items[i], KeyMap::UserUnbind);
3204 case KeyMap::UserBind: {
3205 // for user_bind, we remove this bind
3206 QTreeWidgetItem * parent = items[i]->parent();
3207 int itemIdx = parent->indexOfChild(items[i]);
3208 parent->takeChild(itemIdx);
3209 user_bind_.unbind(shortcut, func);
3210 unhideEmpty(items[i]->text(0), false);
3220 void PrefShortcuts::selectBind()
3222 QString file = form_->browsebind(internalPath(bindFileED->text()));
3223 if (!file.isEmpty()) {
3224 bindFileED->setText(file);
3225 system_bind_ = KeyMap();
3226 system_bind_.read(fromqstr(file));
3227 updateShortcutsTW();
3232 void PrefShortcuts::on_modifyPB_pressed()
3238 void PrefShortcuts::on_newPB_pressed()
3240 shortcut_->lfunLE->clear();
3241 shortcut_->shortcutWG->reset();
3242 save_lfun_ = QString();
3247 void PrefShortcuts::on_removePB_pressed()
3254 void PrefShortcuts::on_searchLE_textEdited()
3256 if (searchLE->text().isEmpty()) {
3257 // show all hidden items
3258 QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Hidden);
3260 shortcutsTW->setItemHidden(*it, isAlwaysHidden(**it));
3261 // close all categories
3262 for (int i = 0; i < shortcutsTW->topLevelItemCount(); ++i)
3263 shortcutsTW->collapseItem(shortcutsTW->topLevelItem(i));
3266 // search both columns
3267 QList<QTreeWidgetItem *> matched = shortcutsTW->findItems(searchLE->text(),
3268 Qt::MatchFlags(Qt::MatchContains | Qt::MatchRecursive), 0);
3269 matched += shortcutsTW->findItems(searchLE->text(),
3270 Qt::MatchFlags(Qt::MatchContains | Qt::MatchRecursive), 1);
3272 // hide everyone (to avoid searching in matched QList repeatedly
3273 QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Selectable);
3275 shortcutsTW->setItemHidden(*it++, true);
3276 // show matched items
3277 for (int i = 0; i < matched.size(); ++i)
3278 if (!isAlwaysHidden(*matched[i])) {
3279 shortcutsTW->setItemHidden(matched[i], false);
3280 shortcutsTW->setItemExpanded(matched[i]->parent(), true);
3285 docstring makeCmdString(FuncRequest const & f)
3287 docstring actionStr = from_ascii(lyxaction.getActionName(f.action()));
3288 if (!f.argument().empty())
3289 actionStr += " " + f.argument();
3294 FuncRequest PrefShortcuts::currentBinding(KeySequence const & k)
3296 FuncRequest res = user_bind_.getBinding(k);
3297 if (res.action() != LFUN_UNKNOWN_ACTION)
3299 res = system_bind_.getBinding(k);
3300 // Check if it is unbound. Note: user_unbind_ can only unbind one
3301 // FuncRequest per key sequence.
3302 if (user_unbind_.getBinding(k) == res)
3303 return FuncRequest::unknown;
3308 bool PrefShortcuts::validateNewShortcut(FuncRequest const & func,
3309 KeySequence const & k,
3310 QString const & lfun_to_modify)
3312 if (func.action() == LFUN_UNKNOWN_ACTION) {
3313 Alert::error(_("Failed to create shortcut"),
3314 _("Unknown or invalid LyX function"));
3318 // It is not currently possible to bind Hidden lfuns such as self-insert. In
3319 // the future, to remove this limitation, see GuiPrefs::insertShortcutItem
3320 // and how it is used in GuiPrefs::shortcutOkPressed.
3321 if (lyxaction.getActionType(func.action()) == LyXAction::Hidden) {
3322 Alert::error(_("Failed to create shortcut"),
3323 _("This LyX function is hidden and cannot be bound."));
3327 if (k.length() == 0) {
3328 Alert::error(_("Failed to create shortcut"),
3329 _("Invalid or empty key sequence"));
3333 FuncRequest oldBinding = currentBinding(k);
3334 if (oldBinding == func)
3335 // nothing to change
3338 // make sure this key isn't already bound---and, if so, prompt user
3339 // (exclude the lfun the user already wants to modify)
3340 docstring const action_string = makeCmdString(oldBinding);
3341 if (oldBinding.action() != LFUN_UNKNOWN_ACTION
3342 && lfun_to_modify != toqstr(action_string)) {
3343 docstring const new_action_string = makeCmdString(func);
3344 docstring const text = bformat(_("Shortcut `%1$s' is already bound to "
3346 "Are you sure you want to unbind the "
3347 "current shortcut and bind it to %3$s?"),
3348 k.print(KeySequence::ForGui), action_string,
3350 int ret = Alert::prompt(_("Redefine shortcut?"),
3351 text, 0, 1, _("&Redefine"), _("&Cancel"));
3354 QString const sequence_text = toqstr(k.print(KeySequence::ForGui));
3355 QList<QTreeWidgetItem*> items = shortcutsTW->findItems(sequence_text,
3356 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 1);
3357 deactivateShortcuts(items);
3363 void PrefShortcuts::shortcutOkPressed()
3365 QString const new_lfun = shortcut_->lfunLE->text();
3366 FuncRequest func = lyxaction.lookupFunc(fromqstr(new_lfun));
3367 KeySequence k = shortcut_->shortcutWG->getKeySequence();
3369 // save_lfun_ contains the text of the lfun to modify, if the user clicked
3370 // "modify", or is empty if they clicked "new" (which I do not really like)
3371 if (!validateNewShortcut(func, k, save_lfun_))
3374 if (!save_lfun_.isEmpty()) {
3375 // real modification of the lfun's shortcut,
3376 // so remove the previous one
3377 QList<QTreeWidgetItem*> to_modify = shortcutsTW->selectedItems();
3378 deactivateShortcuts(to_modify);
3381 shortcut_->accept();
3383 QTreeWidgetItem * item = insertShortcutItem(func, k, KeyMap::UserBind);
3385 user_bind_.bind(&k, func);
3386 shortcutsTW->sortItems(0, Qt::AscendingOrder);
3387 shortcutsTW->setItemExpanded(item->parent(), true);
3388 shortcutsTW->setCurrentItem(item);
3389 shortcutsTW->scrollToItem(item);
3391 Alert::error(_("Failed to create shortcut"),
3392 _("Can not insert shortcut to the list"));
3398 void PrefShortcuts::shortcutCancelPressed()
3400 shortcut_->shortcutWG->reset();
3404 void PrefShortcuts::shortcutClearPressed()
3406 shortcut_->shortcutWG->reset();
3410 void PrefShortcuts::shortcutRemovePressed()
3412 shortcut_->shortcutWG->removeFromSequence();
3416 /////////////////////////////////////////////////////////////////////
3420 /////////////////////////////////////////////////////////////////////
3422 PrefIdentity::PrefIdentity(GuiPreferences * form)
3423 : PrefModule(QString(), N_("Identity"), form)
3427 connect(nameED, SIGNAL(textChanged(QString)),
3428 this, SIGNAL(changed()));
3429 connect(emailED, SIGNAL(textChanged(QString)),
3430 this, SIGNAL(changed()));
3432 nameED->setValidator(new NoNewLineValidator(nameED));
3433 emailED->setValidator(new NoNewLineValidator(emailED));
3437 void PrefIdentity::applyRC(LyXRC & rc) const
3439 rc.user_name = fromqstr(nameED->text());
3440 rc.user_email = fromqstr(emailED->text());
3444 void PrefIdentity::updateRC(LyXRC const & rc)
3446 nameED->setText(toqstr(rc.user_name));
3447 emailED->setText(toqstr(rc.user_email));
3452 /////////////////////////////////////////////////////////////////////
3456 /////////////////////////////////////////////////////////////////////
3458 GuiPreferences::GuiPreferences(GuiView & lv)
3459 : GuiDialog(lv, "prefs", qt_("Preferences")), update_screen_font_(false),
3460 update_previews_(false)
3464 QDialog::setModal(false);
3466 connect(buttonBox, SIGNAL(clicked(QAbstractButton *)),
3467 this, SLOT(slotButtonBox(QAbstractButton *)));
3469 addModule(new PrefUserInterface(this));
3470 addModule(new PrefDocHandling(this));
3471 addModule(new PrefEdit(this));
3472 addModule(new PrefShortcuts(this));
3473 PrefScreenFonts * screenfonts = new PrefScreenFonts(this);
3474 connect(this, SIGNAL(prefsApplied(LyXRC const &)),
3475 screenfonts, SLOT(updateScreenFontSizes(LyXRC const &)));
3476 addModule(screenfonts);
3477 addModule(new PrefColors(this));
3478 addModule(new PrefDisplay(this));
3479 addModule(new PrefInput(this));
3480 addModule(new PrefCompletion(this));
3482 addModule(new PrefPaths(this));
3484 addModule(new PrefIdentity(this));
3486 addModule(new PrefLanguage(this));
3487 addModule(new PrefSpellchecker(this));
3489 PrefOutput * output = new PrefOutput(this);
3491 addModule(new PrefLatex(this));
3493 PrefConverters * converters = new PrefConverters(this);
3494 PrefFileformats * formats = new PrefFileformats(this);
3495 connect(formats, SIGNAL(formatsChanged()),
3496 converters, SLOT(updateGui()));
3497 addModule(converters);
3500 prefsPS->setCurrentPanel("User Interface");
3501 // FIXME: hack to work around resizing bug in Qt >= 4.2
3502 // bug verified with Qt 4.2.{0-3} (JSpitzm)
3503 #if QT_VERSION >= 0x040200
3504 prefsPS->updateGeometry();
3507 bc().setPolicy(ButtonPolicy::PreferencesPolicy);
3508 bc().setOK(buttonBox->button(QDialogButtonBox::Ok));
3509 bc().setApply(buttonBox->button(QDialogButtonBox::Apply));
3510 bc().setCancel(buttonBox->button(QDialogButtonBox::Cancel));
3511 bc().setRestore(buttonBox->button(QDialogButtonBox::Reset));
3515 void GuiPreferences::addModule(PrefModule * module)
3517 LASSERT(module, return);
3518 if (module->category().isEmpty())
3519 prefsPS->addPanel(module, module->title());
3521 prefsPS->addPanel(module, module->title(), module->category());
3522 connect(module, SIGNAL(changed()), this, SLOT(change_adaptor()));
3523 modules_.push_back(module);
3527 void GuiPreferences::change_adaptor()
3533 void GuiPreferences::applyRC(LyXRC & rc) const
3535 size_t end = modules_.size();
3536 for (size_t i = 0; i != end; ++i)
3537 modules_[i]->applyRC(rc);
3541 void GuiPreferences::updateRC(LyXRC const & rc)
3543 size_t const end = modules_.size();
3544 for (size_t i = 0; i != end; ++i)
3545 modules_[i]->updateRC(rc);
3549 void GuiPreferences::applyView()
3555 bool GuiPreferences::initialiseParams(string const &)
3558 formats_ = theFormats();
3559 converters_ = theConverters();
3560 converters_.update(formats_);
3561 movers_ = theMovers();
3563 update_screen_font_ = false;
3564 update_previews_ = false;
3567 // Make sure that the bc is in the INITIAL state
3568 if (bc().policy().buttonStatus(ButtonPolicy::RESTORE))
3575 void GuiPreferences::dispatchParams()
3578 rc_.write(ss, true);
3579 dispatch(FuncRequest(LFUN_LYXRC_APPLY, ss.str()));
3580 // issue prefsApplied signal. This will update the
3581 // localized screen font sizes.
3583 // FIXME: these need lfuns
3585 Author const & author =
3586 Author(from_utf8(rc_.user_name), from_utf8(rc_.user_email));
3587 theBufferList().recordCurrentAuthor(author);
3589 theFormats() = formats_;
3591 theConverters() = converters_;
3592 theConverters().update(formats_);
3593 theConverters().buildGraph();
3594 theBufferList().invalidateConverterCache();
3596 theMovers() = movers_;
3598 vector<string>::const_iterator it = colors_.begin();
3599 vector<string>::const_iterator const end = colors_.end();
3600 for (; it != end; ++it)
3601 dispatch(FuncRequest(LFUN_SET_COLOR, *it));
3604 if (update_screen_font_) {
3605 dispatch(FuncRequest(LFUN_SCREEN_FONT_UPDATE));
3606 // resets flag in case second apply in same dialog
3607 update_screen_font_ = false;
3610 if (update_previews_) {
3611 // resets flag in case second apply in same dialog
3612 theBufferList().updatePreviews();
3613 update_previews_ = false;
3617 if (!tempSaveCB->isChecked())
3618 dispatch(FuncRequest(LFUN_PREFERENCES_SAVE));
3622 void GuiPreferences::setColor(ColorCode col, QString const & hex)
3624 colors_.push_back(lcolor.getLyXName(col) + ' ' + fromqstr(hex));
3628 void GuiPreferences::updateScreenFonts()
3630 update_screen_font_ = true;
3634 void GuiPreferences::updatePreviews()
3636 update_previews_ = true;
3640 QString GuiPreferences::browsebind(QString const & file) const
3642 return browseLibFile("bind", file, "bind", qt_("Choose bind file"),
3643 QStringList(qt_("LyX bind files (*.bind)")));
3647 QString GuiPreferences::browseUI(QString const & file) const
3649 return browseLibFile("ui", file, "ui", qt_("Choose UI file"),
3650 QStringList(qt_("LyX UI files (*.ui)")));
3654 QString GuiPreferences::browsekbmap(QString const & file) const
3656 return browseLibFile("kbd", file, "kmap", qt_("Choose keyboard map"),
3657 QStringList(qt_("LyX keyboard maps (*.kmap)")));
3661 QString GuiPreferences::browse(QString const & file,
3662 QString const & title) const
3664 return browseFile(file, title, QStringList(), true);
3668 Dialog * createGuiPreferences(GuiView & lv) { return new GuiPreferences(lv); }
3671 } // namespace frontend
3674 #include "moc_GuiPrefs.cpp"