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"
24 #include "BufferList.h"
27 #include "ConverterCache.h"
28 #include "FontEnums.h"
29 #include "FuncRequest.h"
31 #include "KeySequence.h"
33 #include "LyXAction.h"
34 #include "PanelStack.h"
37 #include "SpellChecker.h"
39 #include "support/debug.h"
40 #include "support/FileName.h"
41 #include "support/filetools.h"
42 #include "support/foreach.h"
43 #include "support/gettext.h"
44 #include "support/lstrings.h"
45 #include "support/os.h"
46 #include "support/Package.h"
48 #include "graphics/GraphicsTypes.h"
50 #include "frontends/alert.h"
51 #include "frontends/Application.h"
52 #include "frontends/FontLoader.h"
54 #include <QAbstractItemModel>
56 #include <QColorDialog>
57 #include <QFontDatabase>
58 #include <QHeaderView>
60 #include <QMessageBox>
61 #include <QPixmapCache>
62 #include <QPushButton>
65 #include <QTreeWidget>
66 #include <QTreeWidgetItem>
76 using namespace lyx::support;
77 using namespace lyx::support::os;
82 /////////////////////////////////////////////////////////////////////
86 /////////////////////////////////////////////////////////////////////
88 /** Launch a file dialog and return the chosen file.
89 filename: a suggested filename.
90 title: the title of the dialog.
92 dir1 = (name, dir), dir2 = (name, dir): extra buttons on the dialog.
94 QString browseFile(QString const & filename,
95 QString const & title,
96 QStringList const & filters,
98 QString const & label1 = QString(),
99 QString const & dir1 = QString(),
100 QString const & label2 = QString(),
101 QString const & dir2 = QString(),
102 QString const & fallback_dir = QString())
104 QString lastPath = ".";
105 if (!filename.isEmpty())
106 lastPath = onlyPath(filename);
107 else if(!fallback_dir.isEmpty())
108 lastPath = fallback_dir;
110 FileDialog dlg(title, LFUN_SELECT_FILE_SYNC);
111 dlg.setButton2(label1, dir1);
112 dlg.setButton2(label2, dir2);
114 FileDialog::Result result;
117 result = dlg.save(lastPath, filters, onlyFilename(filename));
119 result = dlg.open(lastPath, filters, onlyFilename(filename));
121 return result.second;
125 /** Wrapper around browseFile which tries to provide a filename
126 * relative to the user or system directory. The dir, name and ext
127 * parameters have the same meaning as in the
128 * support::LibFileSearch function.
130 QString browseLibFile(QString const & dir,
131 QString const & name,
133 QString const & title,
134 QStringList const & filters)
137 QString const label1 = qt_("System files|#S#s");
139 toqstr(addName(package().system_support().absFilename(), fromqstr(dir)));
141 QString const label2 = qt_("User files|#U#u");
143 toqstr(addName(package().user_support().absFilename(), fromqstr(dir)));
145 QString const result = browseFile(toqstr(
146 libFileSearch(dir, name, ext).absFilename()),
147 title, filters, false, dir1, dir2, QString(), QString(), dir1);
149 // remove the extension if it is the default one
151 if (getExtension(result) == ext)
152 noextresult = removeExtension(result);
154 noextresult = result;
156 // remove the directory, if it is the default one
157 QString const file = onlyFilename(noextresult);
158 if (toqstr(libFileSearch(dir, file, ext).absFilename()) == result)
165 /** Launch a file dialog and return the chosen directory.
166 pathname: a suggested pathname.
167 title: the title of the dialog.
168 dir1 = (name, dir), dir2 = (name, dir): extra buttons on the dialog.
170 QString browseDir(QString const & pathname,
171 QString const & title,
172 QString const & label1 = QString(),
173 QString const & dir1 = QString(),
174 QString const & label2 = QString(),
175 QString const & dir2 = QString())
177 QString lastPath = ".";
178 if (!pathname.isEmpty())
179 lastPath = onlyPath(pathname);
181 FileDialog dlg(title, LFUN_SELECT_FILE_SYNC);
182 dlg.setButton1(label1, dir1);
183 dlg.setButton2(label2, dir2);
185 FileDialog::Result const result =
186 dlg.opendir(lastPath, onlyFilename(pathname));
188 return result.second;
192 } // namespace frontend
195 QString browseRelFile(QString const & filename, QString const & refpath,
196 QString const & title, QStringList const & filters, bool save,
197 QString const & label1, QString const & dir1,
198 QString const & label2, QString const & dir2)
200 QString const fname = makeAbsPath(filename, refpath);
203 QString const outname =
204 frontend::browseFile(fname, title, filters, save, label1, dir1, label2, dir2);
206 QString const reloutname =
207 toqstr(makeRelPath(qstring_to_ucs4(outname), qstring_to_ucs4(refpath)));
209 if (reloutname.startsWith("../"))
217 /////////////////////////////////////////////////////////////////////
221 /////////////////////////////////////////////////////////////////////
225 string const catLookAndFeel = N_("Look & Feel");
226 string const catEditing = N_("Editing");
227 string const catLanguage = N_("Language Settings");
228 string const catOutput = N_("Output");
229 string const catFiles = N_("File Handling");
231 static void parseFontName(QString const & mangled0,
232 string & name, string & foundry)
234 string mangled = fromqstr(mangled0);
235 size_t const idx = mangled.find('[');
236 if (idx == string::npos || idx == 0) {
240 name = mangled.substr(0, idx - 1),
241 foundry = mangled.substr(idx + 1, mangled.size() - idx - 2);
246 static void setComboxFont(QComboBox * cb, string const & family,
247 string const & foundry)
249 QString fontname = toqstr(family);
250 if (!foundry.empty())
251 fontname += " [" + toqstr(foundry) + ']';
253 for (int i = 0; i != cb->count(); ++i) {
254 if (cb->itemText(i) == fontname) {
255 cb->setCurrentIndex(i);
260 // Try matching without foundry name
262 // We count in reverse in order to prefer the Xft foundry
263 for (int i = cb->count(); --i >= 0;) {
264 string name, foundry;
265 parseFontName(cb->itemText(i), name, foundry);
266 if (compare_ascii_no_case(name, family) == 0) {
267 cb->setCurrentIndex(i);
272 // family alone can contain e.g. "Helvetica [Adobe]"
273 string tmpname, tmpfoundry;
274 parseFontName(toqstr(family), tmpname, tmpfoundry);
276 // We count in reverse in order to prefer the Xft foundry
277 for (int i = cb->count(); --i >= 0; ) {
278 string name, foundry;
279 parseFontName(cb->itemText(i), name, foundry);
280 if (compare_ascii_no_case(name, foundry) == 0) {
281 cb->setCurrentIndex(i);
286 // Bleh, default fonts, and the names couldn't be found. Hack
290 font.setKerning(false);
292 QString const font_family = toqstr(family);
293 if (font_family == guiApp->romanFontName()) {
294 font.setStyleHint(QFont::Serif);
295 font.setFamily(font_family);
296 } else if (font_family == guiApp->sansFontName()) {
297 font.setStyleHint(QFont::SansSerif);
298 font.setFamily(font_family);
299 } else if (font_family == guiApp->typewriterFontName()) {
300 font.setStyleHint(QFont::TypeWriter);
301 font.setFamily(font_family);
303 LYXERR0("FAILED to find the default font: '"
304 << foundry << "', '" << family << '\'');
308 QFontInfo info(font);
309 string default_font_name, dummyfoundry;
310 parseFontName(info.family(), default_font_name, dummyfoundry);
311 LYXERR0("Apparent font is " << default_font_name);
313 for (int i = 0; i < cb->count(); ++i) {
314 LYXERR0("Looking at " << cb->itemText(i));
315 if (compare_ascii_no_case(fromqstr(cb->itemText(i)),
316 default_font_name) == 0) {
317 cb->setCurrentIndex(i);
322 LYXERR0("FAILED to find the font: '"
323 << foundry << "', '" << family << '\'');
327 /////////////////////////////////////////////////////////////////////
331 /////////////////////////////////////////////////////////////////////
333 class StrftimeValidator : public QValidator
336 StrftimeValidator(QWidget *);
337 QValidator::State validate(QString & input, int & pos) const;
341 StrftimeValidator::StrftimeValidator(QWidget * parent)
347 QValidator::State StrftimeValidator::validate(QString & input, int & /*pos*/) const
349 if (is_valid_strftime(fromqstr(input)))
350 return QValidator::Acceptable;
352 return QValidator::Intermediate;
356 /////////////////////////////////////////////////////////////////////
360 /////////////////////////////////////////////////////////////////////
362 PrefOutput::PrefOutput(GuiPreferences * form)
363 : PrefModule(qt_(catOutput), qt_("General"), form)
366 DateED->setValidator(new StrftimeValidator(DateED));
367 connect(DateED, SIGNAL(textChanged(QString)),
368 this, SIGNAL(changed()));
369 connect(plaintextLinelengthSB, SIGNAL(valueChanged(int)),
370 this, SIGNAL(changed()));
371 connect(dviCB, SIGNAL(editTextChanged(QString)),
372 this, SIGNAL(changed()));
373 connect(pdfCB, SIGNAL(editTextChanged(QString)),
374 this, SIGNAL(changed()));
376 dviCB->addItem("xdvi -sourceposition $$n:$$t $$o");
377 dviCB->addItem("yap -1 -s $$n$$t $$o");
378 dviCB->addItem("okular --unique $$o#src:$$n$$t");
379 dviCB->addItem("synctex view -i $$n:0:$$t -o $$o -x \"evince -p %{page+1} $$o\"");
381 pdfCB->addItem("CMCDDE SUMATRA control [ForwardSearch(\\\"$$o\\\",\\\"$$t\\\",$$n,0,0,1)]");
382 pdfCB->addItem("synctex view -i $$n:0:$$t -o $$o -x \"xpdf -raise -remote $$t.tmp $$o %{page+1}\"");
383 pdfCB->addItem("okular --unique $$o#src:$$n$$t");
384 pdfCB->addItem("synctex view -i $$n:0:$$t -o $$o -x \"evince -p %{page+1} $$o\"");
385 pdfCB->addItem("/Applications/Skim.app/Contents/SharedSupport/displayline $$n $$o $$t");
389 void PrefOutput::on_DateED_textChanged(const QString &)
391 QString t = DateED->text();
393 bool valid = DateED->validator()->validate(t, p)
394 == QValidator::Acceptable;
395 setValid(DateLA, valid);
399 void PrefOutput::apply(LyXRC & rc) const
401 rc.date_insert_format = fromqstr(DateED->text());
402 rc.plaintext_linelen = plaintextLinelengthSB->value();
403 rc.forward_search_dvi = fromqstr(dviCB->currentText());
404 rc.forward_search_pdf = fromqstr(pdfCB->currentText());
408 void PrefOutput::update(LyXRC const & rc)
410 DateED->setText(toqstr(rc.date_insert_format));
411 plaintextLinelengthSB->setValue(rc.plaintext_linelen);
412 dviCB->setEditText(toqstr(rc.forward_search_dvi));
413 pdfCB->setEditText(toqstr(rc.forward_search_pdf));
417 /////////////////////////////////////////////////////////////////////
421 /////////////////////////////////////////////////////////////////////
423 PrefInput::PrefInput(GuiPreferences * form)
424 : PrefModule(qt_(catEditing), qt_("Keyboard/Mouse"), form)
428 connect(keymapCB, SIGNAL(clicked()),
429 this, SIGNAL(changed()));
430 connect(firstKeymapED, SIGNAL(textChanged(QString)),
431 this, SIGNAL(changed()));
432 connect(secondKeymapED, SIGNAL(textChanged(QString)),
433 this, SIGNAL(changed()));
434 connect(mouseWheelSpeedSB, SIGNAL(valueChanged(double)),
435 this, SIGNAL(changed()));
439 void PrefInput::apply(LyXRC & rc) const
441 // FIXME: can derive CB from the two EDs
442 rc.use_kbmap = keymapCB->isChecked();
443 rc.primary_kbmap = internal_path(fromqstr(firstKeymapED->text()));
444 rc.secondary_kbmap = internal_path(fromqstr(secondKeymapED->text()));
445 rc.mouse_wheel_speed = mouseWheelSpeedSB->value();
449 void PrefInput::update(LyXRC const & rc)
451 // FIXME: can derive CB from the two EDs
452 keymapCB->setChecked(rc.use_kbmap);
453 firstKeymapED->setText(toqstr(external_path(rc.primary_kbmap)));
454 secondKeymapED->setText(toqstr(external_path(rc.secondary_kbmap)));
455 mouseWheelSpeedSB->setValue(rc.mouse_wheel_speed);
459 QString PrefInput::testKeymap(QString const & keymap)
461 return form_->browsekbmap(internalPath(keymap));
465 void PrefInput::on_firstKeymapPB_clicked(bool)
467 QString const file = testKeymap(firstKeymapED->text());
469 firstKeymapED->setText(file);
473 void PrefInput::on_secondKeymapPB_clicked(bool)
475 QString const file = testKeymap(secondKeymapED->text());
477 secondKeymapED->setText(file);
481 void PrefInput::on_keymapCB_toggled(bool keymap)
483 firstKeymapLA->setEnabled(keymap);
484 secondKeymapLA->setEnabled(keymap);
485 firstKeymapED->setEnabled(keymap);
486 secondKeymapED->setEnabled(keymap);
487 firstKeymapPB->setEnabled(keymap);
488 secondKeymapPB->setEnabled(keymap);
492 /////////////////////////////////////////////////////////////////////
496 /////////////////////////////////////////////////////////////////////
498 PrefCompletion::PrefCompletion(GuiPreferences * form)
499 : PrefModule(qt_(catEditing), qt_("Input Completion"), form)
503 connect(inlineDelaySB, SIGNAL(valueChanged(double)),
504 this, SIGNAL(changed()));
505 connect(inlineMathCB, SIGNAL(clicked()),
506 this, SIGNAL(changed()));
507 connect(inlineTextCB, SIGNAL(clicked()),
508 this, SIGNAL(changed()));
509 connect(inlineDotsCB, SIGNAL(clicked()),
510 this, SIGNAL(changed()));
511 connect(popupDelaySB, SIGNAL(valueChanged(double)),
512 this, SIGNAL(changed()));
513 connect(popupMathCB, SIGNAL(clicked()),
514 this, SIGNAL(changed()));
515 connect(autocorrectionCB, SIGNAL(clicked()),
516 this, SIGNAL(changed()));
517 connect(popupTextCB, SIGNAL(clicked()),
518 this, SIGNAL(changed()));
519 connect(popupAfterCompleteCB, SIGNAL(clicked()),
520 this, SIGNAL(changed()));
521 connect(cursorTextCB, SIGNAL(clicked()),
522 this, SIGNAL(changed()));
526 void PrefCompletion::on_inlineTextCB_clicked()
532 void PrefCompletion::on_popupTextCB_clicked()
538 void PrefCompletion::enableCB()
540 cursorTextCB->setEnabled(
541 popupTextCB->isChecked() || inlineTextCB->isChecked());
545 void PrefCompletion::apply(LyXRC & rc) const
547 rc.completion_inline_delay = inlineDelaySB->value();
548 rc.completion_inline_math = inlineMathCB->isChecked();
549 rc.completion_inline_text = inlineTextCB->isChecked();
550 rc.completion_inline_dots = inlineDotsCB->isChecked() ? 13 : -1;
551 rc.completion_popup_delay = popupDelaySB->value();
552 rc.completion_popup_math = popupMathCB->isChecked();
553 rc.autocorrection_math = autocorrectionCB->isChecked();
554 rc.completion_popup_text = popupTextCB->isChecked();
555 rc.completion_cursor_text = cursorTextCB->isChecked();
556 rc.completion_popup_after_complete =
557 popupAfterCompleteCB->isChecked();
561 void PrefCompletion::update(LyXRC const & rc)
563 inlineDelaySB->setValue(rc.completion_inline_delay);
564 inlineMathCB->setChecked(rc.completion_inline_math);
565 inlineTextCB->setChecked(rc.completion_inline_text);
566 inlineDotsCB->setChecked(rc.completion_inline_dots != -1);
567 popupDelaySB->setValue(rc.completion_popup_delay);
568 popupMathCB->setChecked(rc.completion_popup_math);
569 autocorrectionCB->setChecked(rc.autocorrection_math);
570 popupTextCB->setChecked(rc.completion_popup_text);
571 cursorTextCB->setChecked(rc.completion_cursor_text);
572 popupAfterCompleteCB->setChecked(rc.completion_popup_after_complete);
578 /////////////////////////////////////////////////////////////////////
582 /////////////////////////////////////////////////////////////////////
584 PrefLatex::PrefLatex(GuiPreferences * form)
585 : PrefModule(qt_(catOutput), qt_("LaTeX"), form)
588 connect(latexEncodingCB, SIGNAL(clicked()),
589 this, SIGNAL(changed()));
590 connect(latexEncodingED, SIGNAL(textChanged(QString)),
591 this, SIGNAL(changed()));
592 connect(latexChecktexED, SIGNAL(textChanged(QString)),
593 this, SIGNAL(changed()));
594 connect(latexBibtexCO, SIGNAL(activated(int)),
595 this, SIGNAL(changed()));
596 connect(latexBibtexED, SIGNAL(textChanged(QString)),
597 this, SIGNAL(changed()));
598 connect(latexJBibtexED, SIGNAL(textChanged(QString)),
599 this, SIGNAL(changed()));
600 connect(latexIndexCO, SIGNAL(activated(int)),
601 this, SIGNAL(changed()));
602 connect(latexIndexED, SIGNAL(textChanged(QString)),
603 this, SIGNAL(changed()));
604 connect(latexJIndexED, SIGNAL(textChanged(QString)),
605 this, SIGNAL(changed()));
606 connect(latexAutoresetCB, SIGNAL(clicked()),
607 this, SIGNAL(changed()));
608 connect(latexDviPaperED, SIGNAL(textChanged(QString)),
609 this, SIGNAL(changed()));
610 connect(latexPaperSizeCO, SIGNAL(activated(int)),
611 this, SIGNAL(changed()));
613 #if defined(__CYGWIN__) || defined(_WIN32)
614 pathCB->setVisible(true);
615 connect(pathCB, SIGNAL(clicked()),
616 this, SIGNAL(changed()));
618 pathCB->setVisible(false);
623 void PrefLatex::on_latexEncodingCB_stateChanged(int state)
625 latexEncodingED->setEnabled(state == Qt::Checked);
629 void PrefLatex::on_latexBibtexCO_activated(int n)
631 QString const bibtex = latexBibtexCO->itemData(n).toString();
632 if (bibtex.isEmpty()) {
633 latexBibtexED->clear();
634 latexBibtexOptionsLA->setText(qt_("Co&mmand:"));
637 for (LyXRC::CommandSet::const_iterator it = bibtex_alternatives.begin();
638 it != bibtex_alternatives.end(); ++it) {
639 QString const bib = toqstr(*it);
640 int ind = bib.indexOf(" ");
641 QString sel_command = bib.left(ind);
642 QString sel_options = ind < 0 ? QString() : bib.mid(ind + 1);
643 if (bibtex == sel_command) {
645 latexBibtexED->clear();
647 latexBibtexED->setText(sel_options.trimmed());
650 latexBibtexOptionsLA->setText(qt_("&Options:"));
654 void PrefLatex::on_latexIndexCO_activated(int n)
656 QString const index = latexIndexCO->itemData(n).toString();
657 if (index.isEmpty()) {
658 latexIndexED->clear();
659 latexIndexOptionsLA->setText(qt_("Co&mmand:"));
662 for (LyXRC::CommandSet::const_iterator it = index_alternatives.begin();
663 it != index_alternatives.end(); ++it) {
664 QString const idx = toqstr(*it);
665 int ind = idx.indexOf(" ");
666 QString sel_command = idx.left(ind);
667 QString sel_options = ind < 0 ? QString() : idx.mid(ind + 1);
668 if (index == sel_command) {
670 latexIndexED->clear();
672 latexIndexED->setText(sel_options.trimmed());
675 latexIndexOptionsLA->setText(qt_("Op&tions:"));
679 void PrefLatex::apply(LyXRC & rc) const
681 // If bibtex is not empty, bibopt contains the options, otherwise
682 // it is a customized bibtex command with options.
683 QString const bibtex = latexBibtexCO->itemData(
684 latexBibtexCO->currentIndex()).toString();
685 QString const bibopt = latexBibtexED->text();
686 if (bibtex.isEmpty())
687 rc.bibtex_command = fromqstr(bibopt);
688 else if (bibopt.isEmpty())
689 rc.bibtex_command = fromqstr(bibtex);
691 rc.bibtex_command = fromqstr(bibtex) + " " + fromqstr(bibopt);
693 // If index is not empty, idxopt contains the options, otherwise
694 // it is a customized index command with options.
695 QString const index = latexIndexCO->itemData(
696 latexIndexCO->currentIndex()).toString();
697 QString const idxopt = latexIndexED->text();
699 rc.index_command = fromqstr(idxopt);
700 else if (idxopt.isEmpty())
701 rc.index_command = fromqstr(index);
703 rc.index_command = fromqstr(index) + " " + fromqstr(idxopt);
705 if (latexEncodingCB->isChecked())
706 rc.fontenc = fromqstr(latexEncodingED->text());
708 rc.fontenc = "default";
709 rc.chktex_command = fromqstr(latexChecktexED->text());
710 rc.jbibtex_command = fromqstr(latexJBibtexED->text());
711 rc.jindex_command = fromqstr(latexJIndexED->text());
712 rc.nomencl_command = fromqstr(latexNomenclED->text());
713 rc.auto_reset_options = latexAutoresetCB->isChecked();
714 rc.view_dvi_paper_option = fromqstr(latexDviPaperED->text());
715 rc.default_papersize =
716 form_->toPaperSize(latexPaperSizeCO->currentIndex());
717 #if defined(__CYGWIN__) || defined(_WIN32)
718 rc.windows_style_tex_paths = pathCB->isChecked();
723 void PrefLatex::update(LyXRC const & rc)
725 latexBibtexCO->clear();
727 latexBibtexCO->addItem(qt_("Custom"), QString());
728 for (LyXRC::CommandSet::const_iterator it = rc.bibtex_alternatives.begin();
729 it != rc.bibtex_alternatives.end(); ++it) {
730 QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
731 latexBibtexCO->addItem(command, command);
734 bibtex_alternatives = rc.bibtex_alternatives;
736 QString const bib = toqstr(rc.bibtex_command);
737 int ind = bib.indexOf(" ");
738 QString sel_command = bib.left(ind);
739 QString sel_options = ind < 0 ? QString() : bib.mid(ind + 1);
741 int pos = latexBibtexCO->findData(sel_command);
743 latexBibtexCO->setCurrentIndex(pos);
744 latexBibtexED->setText(sel_options.trimmed());
745 latexBibtexOptionsLA->setText(qt_("&Options:"));
747 latexBibtexED->setText(toqstr(rc.bibtex_command));
748 latexBibtexCO->setCurrentIndex(0);
749 latexBibtexOptionsLA->setText(qt_("Co&mmand:"));
752 latexIndexCO->clear();
754 latexIndexCO->addItem(qt_("Custom"), QString());
755 for (LyXRC::CommandSet::const_iterator it = rc.index_alternatives.begin();
756 it != rc.index_alternatives.end(); ++it) {
757 QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
758 latexIndexCO->addItem(command, command);
761 index_alternatives = rc.index_alternatives;
763 QString const idx = toqstr(rc.index_command);
764 ind = idx.indexOf(" ");
765 sel_command = idx.left(ind);
766 sel_options = ind < 0 ? QString() : idx.mid(ind + 1);
768 pos = latexIndexCO->findData(sel_command);
770 latexIndexCO->setCurrentIndex(pos);
771 latexIndexED->setText(sel_options.trimmed());
772 latexIndexOptionsLA->setText(qt_("Op&tions:"));
774 latexIndexED->setText(toqstr(rc.index_command));
775 latexIndexCO->setCurrentIndex(0);
776 latexIndexOptionsLA->setText(qt_("Co&mmand:"));
779 if (rc.fontenc == "default") {
780 latexEncodingCB->setChecked(false);
781 latexEncodingED->setEnabled(false);
783 latexEncodingCB->setChecked(true);
784 latexEncodingED->setEnabled(true);
785 latexEncodingED->setText(toqstr(rc.fontenc));
787 latexChecktexED->setText(toqstr(rc.chktex_command));
788 latexJBibtexED->setText(toqstr(rc.jbibtex_command));
789 latexJIndexED->setText(toqstr(rc.jindex_command));
790 latexNomenclED->setText(toqstr(rc.nomencl_command));
791 latexAutoresetCB->setChecked(rc.auto_reset_options);
792 latexDviPaperED->setText(toqstr(rc.view_dvi_paper_option));
793 latexPaperSizeCO->setCurrentIndex(
794 form_->fromPaperSize(rc.default_papersize));
795 #if defined(__CYGWIN__) || defined(_WIN32)
796 pathCB->setChecked(rc.windows_style_tex_paths);
801 /////////////////////////////////////////////////////////////////////
805 /////////////////////////////////////////////////////////////////////
807 PrefScreenFonts::PrefScreenFonts(GuiPreferences * form)
808 : PrefModule(qt_(catLookAndFeel), qt_("Screen fonts"), form)
812 connect(screenRomanCO, SIGNAL(activated(QString)),
813 this, SLOT(selectRoman(QString)));
814 connect(screenSansCO, SIGNAL(activated(QString)),
815 this, SLOT(selectSans(QString)));
816 connect(screenTypewriterCO, SIGNAL(activated(QString)),
817 this, SLOT(selectTypewriter(QString)));
819 QFontDatabase fontdb;
820 QStringList families(fontdb.families());
821 for (QStringList::Iterator it = families.begin(); it != families.end(); ++it) {
822 screenRomanCO->addItem(*it);
823 screenSansCO->addItem(*it);
824 screenTypewriterCO->addItem(*it);
826 connect(screenRomanCO, SIGNAL(activated(QString)),
827 this, SIGNAL(changed()));
828 connect(screenSansCO, SIGNAL(activated(QString)),
829 this, SIGNAL(changed()));
830 connect(screenTypewriterCO, SIGNAL(activated(QString)),
831 this, SIGNAL(changed()));
832 connect(screenZoomSB, SIGNAL(valueChanged(int)),
833 this, SIGNAL(changed()));
834 connect(screenDpiSB, SIGNAL(valueChanged(int)),
835 this, SIGNAL(changed()));
836 connect(screenTinyED, SIGNAL(textChanged(QString)),
837 this, SIGNAL(changed()));
838 connect(screenSmallestED, SIGNAL(textChanged(QString)),
839 this, SIGNAL(changed()));
840 connect(screenSmallerED, SIGNAL(textChanged(QString)),
841 this, SIGNAL(changed()));
842 connect(screenSmallED, SIGNAL(textChanged(QString)),
843 this, SIGNAL(changed()));
844 connect(screenNormalED, SIGNAL(textChanged(QString)),
845 this, SIGNAL(changed()));
846 connect(screenLargeED, SIGNAL(textChanged(QString)),
847 this, SIGNAL(changed()));
848 connect(screenLargerED, SIGNAL(textChanged(QString)),
849 this, SIGNAL(changed()));
850 connect(screenLargestED, SIGNAL(textChanged(QString)),
851 this, SIGNAL(changed()));
852 connect(screenHugeED, SIGNAL(textChanged(QString)),
853 this, SIGNAL(changed()));
854 connect(screenHugerED, SIGNAL(textChanged(QString)),
855 this, SIGNAL(changed()));
856 connect(pixmapCacheCB, SIGNAL(toggled(bool)),
857 this, SIGNAL(changed()));
859 screenTinyED->setValidator(new QDoubleValidator(screenTinyED));
860 screenSmallestED->setValidator(new QDoubleValidator(screenSmallestED));
861 screenSmallerED->setValidator(new QDoubleValidator(screenSmallerED));
862 screenSmallED->setValidator(new QDoubleValidator(screenSmallED));
863 screenNormalED->setValidator(new QDoubleValidator(screenNormalED));
864 screenLargeED->setValidator(new QDoubleValidator(screenLargeED));
865 screenLargerED->setValidator(new QDoubleValidator(screenLargerED));
866 screenLargestED->setValidator(new QDoubleValidator(screenLargestED));
867 screenHugeED->setValidator(new QDoubleValidator(screenHugeED));
868 screenHugerED->setValidator(new QDoubleValidator(screenHugerED));
872 void PrefScreenFonts::apply(LyXRC & rc) const
874 LyXRC const oldrc = rc;
876 parseFontName(screenRomanCO->currentText(),
877 rc.roman_font_name, rc.roman_font_foundry);
878 parseFontName(screenSansCO->currentText(),
879 rc.sans_font_name, rc.sans_font_foundry);
880 parseFontName(screenTypewriterCO->currentText(),
881 rc.typewriter_font_name, rc.typewriter_font_foundry);
883 rc.zoom = screenZoomSB->value();
884 rc.dpi = screenDpiSB->value();
885 rc.font_sizes[FONT_SIZE_TINY] = widgetToDoubleStr(screenTinyED);
886 rc.font_sizes[FONT_SIZE_SCRIPT] = widgetToDoubleStr(screenSmallestED);
887 rc.font_sizes[FONT_SIZE_FOOTNOTE] = widgetToDoubleStr(screenSmallerED);
888 rc.font_sizes[FONT_SIZE_SMALL] = widgetToDoubleStr(screenSmallED);
889 rc.font_sizes[FONT_SIZE_NORMAL] = widgetToDoubleStr(screenNormalED);
890 rc.font_sizes[FONT_SIZE_LARGE] = widgetToDoubleStr(screenLargeED);
891 rc.font_sizes[FONT_SIZE_LARGER] = widgetToDoubleStr(screenLargerED);
892 rc.font_sizes[FONT_SIZE_LARGEST] = widgetToDoubleStr(screenLargestED);
893 rc.font_sizes[FONT_SIZE_HUGE] = widgetToDoubleStr(screenHugeED);
894 rc.font_sizes[FONT_SIZE_HUGER] = widgetToDoubleStr(screenHugerED);
895 rc.use_pixmap_cache = pixmapCacheCB->isChecked();
897 if (rc.font_sizes != oldrc.font_sizes
898 || rc.roman_font_name != oldrc.roman_font_name
899 || rc.sans_font_name != oldrc.sans_font_name
900 || rc.typewriter_font_name != oldrc.typewriter_font_name
901 || rc.zoom != oldrc.zoom || rc.dpi != oldrc.dpi) {
902 // The global QPixmapCache is used in GuiPainter to cache text
903 // painting so we must reset it in case any of the above
904 // parameter is changed.
905 QPixmapCache::clear();
906 guiApp->fontLoader().update();
907 form_->updateScreenFonts();
912 void PrefScreenFonts::update(LyXRC const & rc)
914 setComboxFont(screenRomanCO, rc.roman_font_name,
915 rc.roman_font_foundry);
916 setComboxFont(screenSansCO, rc.sans_font_name,
917 rc.sans_font_foundry);
918 setComboxFont(screenTypewriterCO, rc.typewriter_font_name,
919 rc.typewriter_font_foundry);
921 selectRoman(screenRomanCO->currentText());
922 selectSans(screenSansCO->currentText());
923 selectTypewriter(screenTypewriterCO->currentText());
925 screenZoomSB->setValue(rc.zoom);
926 screenDpiSB->setValue(rc.dpi);
927 doubleToWidget(screenTinyED, rc.font_sizes[FONT_SIZE_TINY]);
928 doubleToWidget(screenSmallestED, rc.font_sizes[FONT_SIZE_SCRIPT]);
929 doubleToWidget(screenSmallerED, rc.font_sizes[FONT_SIZE_FOOTNOTE]);
930 doubleToWidget(screenSmallED, rc.font_sizes[FONT_SIZE_SMALL]);
931 doubleToWidget(screenNormalED, rc.font_sizes[FONT_SIZE_NORMAL]);
932 doubleToWidget(screenLargeED, rc.font_sizes[FONT_SIZE_LARGE]);
933 doubleToWidget(screenLargerED, rc.font_sizes[FONT_SIZE_LARGER]);
934 doubleToWidget(screenLargestED, rc.font_sizes[FONT_SIZE_LARGEST]);
935 doubleToWidget(screenHugeED, rc.font_sizes[FONT_SIZE_HUGE]);
936 doubleToWidget(screenHugerED, rc.font_sizes[FONT_SIZE_HUGER]);
938 pixmapCacheCB->setChecked(rc.use_pixmap_cache);
939 #if defined(Q_WS_X11)
940 pixmapCacheCB->setEnabled(false);
946 void PrefScreenFonts::selectRoman(const QString & name)
948 screenRomanFE->set(QFont(name), name);
952 void PrefScreenFonts::selectSans(const QString & name)
954 screenSansFE->set(QFont(name), name);
958 void PrefScreenFonts::selectTypewriter(const QString & name)
960 screenTypewriterFE->set(QFont(name), name);
964 /////////////////////////////////////////////////////////////////////
968 /////////////////////////////////////////////////////////////////////
974 bool operator()(ColorCode lhs, ColorCode rhs) const {
976 compare_no_case(lcolor.getGUIName(lhs), lcolor.getGUIName(rhs)) < 0;
982 PrefColors::PrefColors(GuiPreferences * form)
983 : PrefModule(qt_(catLookAndFeel), qt_("Colors"), form)
987 // FIXME: all of this initialization should be put into the controller.
988 // See http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg113301.html
989 // for some discussion of why that is not trivial.
990 QPixmap icon(32, 32);
991 for (int i = 0; i < Color_ignore; ++i) {
992 ColorCode lc = static_cast<ColorCode>(i);
1000 || lc == Color_magenta
1001 || lc == Color_yellow
1002 || lc == Color_inherit
1003 || lc == Color_ignore
1004 || lc == Color_greyedouttext
1005 || lc == Color_shadedbg) continue;
1007 lcolors_.push_back(lc);
1009 sort(lcolors_.begin(), lcolors_.end(), ColorSorter());
1010 vector<ColorCode>::const_iterator cit = lcolors_.begin();
1011 vector<ColorCode>::const_iterator const end = lcolors_.end();
1012 for (; cit != end; ++cit) {
1013 (void) new QListWidgetItem(QIcon(icon),
1014 toqstr(lcolor.getGUIName(*cit)), lyxObjectsLW);
1016 curcolors_.resize(lcolors_.size());
1017 newcolors_.resize(lcolors_.size());
1018 // End initialization
1020 connect(colorChangePB, SIGNAL(clicked()),
1021 this, SLOT(changeColor()));
1022 connect(lyxObjectsLW, SIGNAL(itemSelectionChanged()),
1023 this, SLOT(changeLyxObjectsSelection()));
1024 connect(lyxObjectsLW, SIGNAL(itemActivated(QListWidgetItem*)),
1025 this, SLOT(changeColor()));
1029 void PrefColors::apply(LyXRC & /*rc*/) const
1031 for (unsigned int i = 0; i < lcolors_.size(); ++i)
1032 if (curcolors_[i] != newcolors_[i])
1033 form_->setColor(lcolors_[i], newcolors_[i]);
1037 void PrefColors::update(LyXRC const & /*rc*/)
1039 for (unsigned int i = 0; i < lcolors_.size(); ++i) {
1040 QColor color = QColor(guiApp->colorCache().get(lcolors_[i]));
1041 QPixmap coloritem(32, 32);
1042 coloritem.fill(color);
1043 lyxObjectsLW->item(i)->setIcon(QIcon(coloritem));
1044 newcolors_[i] = curcolors_[i] = color.name();
1046 changeLyxObjectsSelection();
1050 void PrefColors::changeColor()
1052 int const row = lyxObjectsLW->currentRow();
1058 QString const color = newcolors_[row];
1059 QColor c = QColorDialog::getColor(QColor(color), qApp->focusWidget());
1061 if (c.isValid() && c.name() != color) {
1062 newcolors_[row] = c.name();
1063 QPixmap coloritem(32, 32);
1065 lyxObjectsLW->currentItem()->setIcon(QIcon(coloritem));
1071 void PrefColors::changeLyxObjectsSelection()
1073 colorChangePB->setDisabled(lyxObjectsLW->currentRow() < 0);
1077 /////////////////////////////////////////////////////////////////////
1081 /////////////////////////////////////////////////////////////////////
1083 PrefDisplay::PrefDisplay(GuiPreferences * form)
1084 : PrefModule(qt_(catLookAndFeel), qt_("Display"), form)
1087 connect(displayGraphicsCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1088 connect(instantPreviewCO, SIGNAL(activated(int)), this, SIGNAL(changed()));
1089 connect(previewSizeSB, SIGNAL(valueChanged(double)), this, SIGNAL(changed()));
1090 connect(paragraphMarkerCB, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
1091 if (instantPreviewCO->currentIndex() == 0)
1092 previewSizeSB->setEnabled(false);
1094 previewSizeSB->setEnabled(true);
1098 void PrefDisplay::on_instantPreviewCO_currentIndexChanged(int index)
1101 previewSizeSB->setEnabled(false);
1103 previewSizeSB->setEnabled(true);
1107 void PrefDisplay::apply(LyXRC & rc) const
1109 switch (instantPreviewCO->currentIndex()) {
1110 case 0: rc.preview = LyXRC::PREVIEW_OFF; break;
1111 case 1: rc.preview = LyXRC::PREVIEW_NO_MATH; break;
1112 case 2: rc.preview = LyXRC::PREVIEW_ON; break;
1115 rc.display_graphics = displayGraphicsCB->isChecked();
1116 rc.preview_scale_factor = previewSizeSB->value();
1117 rc.paragraph_markers = paragraphMarkerCB->isChecked();
1119 // FIXME!! The graphics cache no longer has a changeDisplay method.
1121 if (old_value != rc.display_graphics) {
1122 graphics::GCache & gc = graphics::GCache::get();
1129 void PrefDisplay::update(LyXRC const & rc)
1131 switch (rc.preview) {
1132 case LyXRC::PREVIEW_OFF:
1133 instantPreviewCO->setCurrentIndex(0);
1135 case LyXRC::PREVIEW_NO_MATH :
1136 instantPreviewCO->setCurrentIndex(1);
1138 case LyXRC::PREVIEW_ON :
1139 instantPreviewCO->setCurrentIndex(2);
1143 displayGraphicsCB->setChecked(rc.display_graphics);
1144 instantPreviewCO->setEnabled(rc.display_graphics);
1145 previewSizeSB->setValue(rc.preview_scale_factor);
1146 paragraphMarkerCB->setChecked(rc.paragraph_markers);
1150 /////////////////////////////////////////////////////////////////////
1154 /////////////////////////////////////////////////////////////////////
1156 PrefPaths::PrefPaths(GuiPreferences * form)
1157 : PrefModule(QString(), qt_("Paths"), form)
1161 connect(workingDirPB, SIGNAL(clicked()), this, SLOT(selectWorkingdir()));
1162 connect(workingDirED, SIGNAL(textChanged(QString)),
1163 this, SIGNAL(changed()));
1165 connect(templateDirPB, SIGNAL(clicked()), this, SLOT(selectTemplatedir()));
1166 connect(templateDirED, SIGNAL(textChanged(QString)),
1167 this, SIGNAL(changed()));
1169 connect(exampleDirPB, SIGNAL(clicked()), this, SLOT(selectExampledir()));
1170 connect(exampleDirED, SIGNAL(textChanged(QString)),
1171 this, SIGNAL(changed()));
1173 connect(backupDirPB, SIGNAL(clicked()), this, SLOT(selectBackupdir()));
1174 connect(backupDirED, SIGNAL(textChanged(QString)),
1175 this, SIGNAL(changed()));
1177 connect(lyxserverDirPB, SIGNAL(clicked()), this, SLOT(selectLyxPipe()));
1178 connect(lyxserverDirED, SIGNAL(textChanged(QString)),
1179 this, SIGNAL(changed()));
1181 connect(thesaurusDirPB, SIGNAL(clicked()), this, SLOT(selectThesaurusdir()));
1182 connect(thesaurusDirED, SIGNAL(textChanged(QString)),
1183 this, SIGNAL(changed()));
1185 connect(tempDirPB, SIGNAL(clicked()), this, SLOT(selectTempdir()));
1186 connect(tempDirED, SIGNAL(textChanged(QString)),
1187 this, SIGNAL(changed()));
1189 connect(hunspellDirPB, SIGNAL(clicked()), this, SLOT(selectHunspelldir()));
1190 connect(hunspellDirED, SIGNAL(textChanged(QString)),
1191 this, SIGNAL(changed()));
1193 connect(pathPrefixED, SIGNAL(textChanged(QString)),
1194 this, SIGNAL(changed()));
1198 void PrefPaths::apply(LyXRC & rc) const
1200 rc.document_path = internal_path(fromqstr(workingDirED->text()));
1201 rc.example_path = internal_path(fromqstr(exampleDirED->text()));
1202 rc.template_path = internal_path(fromqstr(templateDirED->text()));
1203 rc.backupdir_path = internal_path(fromqstr(backupDirED->text()));
1204 rc.tempdir_path = internal_path(fromqstr(tempDirED->text()));
1205 rc.thesaurusdir_path = internal_path(fromqstr(thesaurusDirED->text()));
1206 rc.hunspelldir_path = internal_path(fromqstr(hunspellDirED->text()));
1207 rc.path_prefix = internal_path_list(fromqstr(pathPrefixED->text()));
1208 // FIXME: should be a checkbox only
1209 rc.lyxpipes = internal_path(fromqstr(lyxserverDirED->text()));
1213 void PrefPaths::update(LyXRC const & rc)
1215 workingDirED->setText(toqstr(external_path(rc.document_path)));
1216 exampleDirED->setText(toqstr(external_path(rc.example_path)));
1217 templateDirED->setText(toqstr(external_path(rc.template_path)));
1218 backupDirED->setText(toqstr(external_path(rc.backupdir_path)));
1219 tempDirED->setText(toqstr(external_path(rc.tempdir_path)));
1220 thesaurusDirED->setText(toqstr(external_path(rc.thesaurusdir_path)));
1221 hunspellDirED->setText(toqstr(external_path(rc.hunspelldir_path)));
1222 pathPrefixED->setText(toqstr(external_path_list(rc.path_prefix)));
1223 // FIXME: should be a checkbox only
1224 lyxserverDirED->setText(toqstr(external_path(rc.lyxpipes)));
1228 void PrefPaths::selectExampledir()
1230 QString file = browseDir(internalPath(exampleDirED->text()),
1231 qt_("Select directory for example files"));
1232 if (!file.isEmpty())
1233 exampleDirED->setText(file);
1237 void PrefPaths::selectTemplatedir()
1239 QString file = browseDir(internalPath(templateDirED->text()),
1240 qt_("Select a document templates directory"));
1241 if (!file.isEmpty())
1242 templateDirED->setText(file);
1246 void PrefPaths::selectTempdir()
1248 QString file = browseDir(internalPath(tempDirED->text()),
1249 qt_("Select a temporary directory"));
1250 if (!file.isEmpty())
1251 tempDirED->setText(file);
1255 void PrefPaths::selectBackupdir()
1257 QString file = browseDir(internalPath(backupDirED->text()),
1258 qt_("Select a backups directory"));
1259 if (!file.isEmpty())
1260 backupDirED->setText(file);
1264 void PrefPaths::selectWorkingdir()
1266 QString file = browseDir(internalPath(workingDirED->text()),
1267 qt_("Select a document directory"));
1268 if (!file.isEmpty())
1269 workingDirED->setText(file);
1273 void PrefPaths::selectThesaurusdir()
1275 QString file = browseDir(internalPath(thesaurusDirED->text()),
1276 qt_("Set the path to the thesaurus dictionaries"));
1277 if (!file.isEmpty())
1278 thesaurusDirED->setText(file);
1282 void PrefPaths::selectHunspelldir()
1284 QString file = browseDir(internalPath(hunspellDirED->text()),
1285 qt_("Set the path to the Hunspell dictionaries"));
1286 if (!file.isEmpty())
1287 hunspellDirED->setText(file);
1291 void PrefPaths::selectLyxPipe()
1293 QString file = form_->browse(internalPath(lyxserverDirED->text()),
1294 qt_("Give a filename for the LyX server pipe"));
1295 if (!file.isEmpty())
1296 lyxserverDirED->setText(file);
1300 /////////////////////////////////////////////////////////////////////
1304 /////////////////////////////////////////////////////////////////////
1306 PrefSpellchecker::PrefSpellchecker(GuiPreferences * form)
1307 : PrefModule(qt_(catLanguage), qt_("Spellchecker"), form)
1311 #if defined(USE_ASPELL)
1312 spellcheckerCB->addItem(qt_("aspell"), QString("aspell"));
1314 #if defined(USE_ENCHANT)
1315 spellcheckerCB->addItem(qt_("enchant"), QString("enchant"));
1317 #if defined(USE_HUNSPELL)
1318 spellcheckerCB->addItem(qt_("hunspell"), QString("hunspell"));
1321 #if defined(USE_ASPELL) || defined(USE_ENCHANT) || defined(USE_HUNSPELL)
1322 connect(spellcheckerCB, SIGNAL(currentIndexChanged(int)),
1323 this, SIGNAL(changed()));
1324 connect(altLanguageED, SIGNAL(textChanged(QString)),
1325 this, SIGNAL(changed()));
1326 connect(escapeCharactersED, SIGNAL(textChanged(QString)),
1327 this, SIGNAL(changed()));
1328 connect(compoundWordCB, SIGNAL(clicked()),
1329 this, SIGNAL(changed()));
1330 connect(spellcheckContinuouslyCB, SIGNAL(clicked()),
1331 this, SIGNAL(changed()));
1332 connect(spellcheckNotesCB, SIGNAL(clicked()),
1333 this, SIGNAL(changed()));
1335 spellcheckerCB->setEnabled(false);
1336 altLanguageED->setEnabled(false);
1337 escapeCharactersED->setEnabled(false);
1338 compoundWordCB->setEnabled(false);
1339 spellcheckContinuouslyCB->setEnabled(false);
1340 spellcheckNotesCB->setEnabled(false);
1345 void PrefSpellchecker::apply(LyXRC & rc) const
1347 rc.spellchecker = fromqstr(spellcheckerCB->itemData(
1348 spellcheckerCB->currentIndex()).toString());
1349 rc.spellchecker_alt_lang = fromqstr(altLanguageED->text());
1350 rc.spellchecker_esc_chars = fromqstr(escapeCharactersED->text());
1351 rc.spellchecker_accept_compound = compoundWordCB->isChecked();
1352 rc.spellcheck_continuously = spellcheckContinuouslyCB->isChecked();
1353 rc.spellcheck_notes = spellcheckNotesCB->isChecked();
1357 void PrefSpellchecker::update(LyXRC const & rc)
1359 spellcheckerCB->setCurrentIndex(
1360 spellcheckerCB->findData(toqstr(rc.spellchecker)));
1361 altLanguageED->setText(toqstr(rc.spellchecker_alt_lang));
1362 escapeCharactersED->setText(toqstr(rc.spellchecker_esc_chars));
1363 compoundWordCB->setChecked(rc.spellchecker_accept_compound);
1364 spellcheckContinuouslyCB->setChecked(rc.spellcheck_continuously);
1365 spellcheckNotesCB->setChecked(rc.spellcheck_notes);
1370 /////////////////////////////////////////////////////////////////////
1374 /////////////////////////////////////////////////////////////////////
1377 PrefConverters::PrefConverters(GuiPreferences * form)
1378 : PrefModule(qt_(catFiles), qt_("Converters"), form)
1382 connect(converterNewPB, SIGNAL(clicked()),
1383 this, SLOT(updateConverter()));
1384 connect(converterRemovePB, SIGNAL(clicked()),
1385 this, SLOT(removeConverter()));
1386 connect(converterModifyPB, SIGNAL(clicked()),
1387 this, SLOT(updateConverter()));
1388 connect(convertersLW, SIGNAL(currentRowChanged(int)),
1389 this, SLOT(switchConverter()));
1390 connect(converterFromCO, SIGNAL(activated(QString)),
1391 this, SLOT(changeConverter()));
1392 connect(converterToCO, SIGNAL(activated(QString)),
1393 this, SLOT(changeConverter()));
1394 connect(converterED, SIGNAL(textEdited(QString)),
1395 this, SLOT(changeConverter()));
1396 connect(converterFlagED, SIGNAL(textEdited(QString)),
1397 this, SLOT(changeConverter()));
1398 connect(converterNewPB, SIGNAL(clicked()),
1399 this, SIGNAL(changed()));
1400 connect(converterRemovePB, SIGNAL(clicked()),
1401 this, SIGNAL(changed()));
1402 connect(converterModifyPB, SIGNAL(clicked()),
1403 this, SIGNAL(changed()));
1404 connect(maxAgeLE, SIGNAL(textEdited(QString)),
1405 this, SIGNAL(changed()));
1407 maxAgeLE->setValidator(new QDoubleValidator(maxAgeLE));
1408 //converterDefGB->setFocusProxy(convertersLW);
1412 void PrefConverters::apply(LyXRC & rc) const
1414 rc.use_converter_cache = cacheCB->isChecked();
1415 rc.converter_cache_maxage = int(widgetToDouble(maxAgeLE) * 86400.0);
1419 void PrefConverters::update(LyXRC const & rc)
1421 cacheCB->setChecked(rc.use_converter_cache);
1423 doubleToWidget(maxAgeLE, (double(rc.converter_cache_maxage) / 86400.0), 'g', 6);
1428 void PrefConverters::updateGui()
1430 form_->formats().sort();
1431 form_->converters().update(form_->formats());
1432 // save current selection
1433 QString current = converterFromCO->currentText()
1434 + " -> " + converterToCO->currentText();
1436 converterFromCO->clear();
1437 converterToCO->clear();
1439 Formats::const_iterator cit = form_->formats().begin();
1440 Formats::const_iterator end = form_->formats().end();
1441 for (; cit != end; ++cit) {
1442 converterFromCO->addItem(qt_(cit->prettyname()));
1443 converterToCO->addItem(qt_(cit->prettyname()));
1446 // currentRowChanged(int) is also triggered when updating the listwidget
1447 // block signals to avoid unnecessary calls to switchConverter()
1448 convertersLW->blockSignals(true);
1449 convertersLW->clear();
1451 Converters::const_iterator ccit = form_->converters().begin();
1452 Converters::const_iterator cend = form_->converters().end();
1453 for (; ccit != cend; ++ccit) {
1454 QString const name =
1455 qt_(ccit->From->prettyname()) + " -> " + qt_(ccit->To->prettyname());
1456 int type = form_->converters().getNumber(ccit->From->name(), ccit->To->name());
1457 new QListWidgetItem(name, convertersLW, type);
1459 convertersLW->sortItems(Qt::AscendingOrder);
1460 convertersLW->blockSignals(false);
1462 // restore selection
1463 if (!current.isEmpty()) {
1464 QList<QListWidgetItem *> const item =
1465 convertersLW->findItems(current, Qt::MatchExactly);
1466 if (!item.isEmpty())
1467 convertersLW->setCurrentItem(item.at(0));
1470 // select first element if restoring failed
1471 if (convertersLW->currentRow() == -1)
1472 convertersLW->setCurrentRow(0);
1478 void PrefConverters::switchConverter()
1480 int const cnr = convertersLW->currentItem()->type();
1481 Converter const & c(form_->converters().get(cnr));
1482 converterFromCO->setCurrentIndex(form_->formats().getNumber(c.from));
1483 converterToCO->setCurrentIndex(form_->formats().getNumber(c.to));
1484 converterED->setText(toqstr(c.command));
1485 converterFlagED->setText(toqstr(c.flags));
1491 void PrefConverters::changeConverter()
1497 void PrefConverters::updateButtons()
1499 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1500 Format const & to = form_->formats().get(converterToCO->currentIndex());
1501 int const sel = form_->converters().getNumber(from.name(), to.name());
1502 bool const known = sel >= 0;
1503 bool const valid = !(converterED->text().isEmpty()
1504 || from.name() == to.name());
1506 int const cnr = convertersLW->currentItem()->type();
1507 Converter const & c = form_->converters().get(cnr);
1508 string const old_command = c.command;
1509 string const old_flag = c.flags;
1510 string const new_command = fromqstr(converterED->text());
1511 string const new_flag = fromqstr(converterFlagED->text());
1513 bool modified = (old_command != new_command || old_flag != new_flag);
1515 converterModifyPB->setEnabled(valid && known && modified);
1516 converterNewPB->setEnabled(valid && !known);
1517 converterRemovePB->setEnabled(known);
1519 maxAgeLE->setEnabled(cacheCB->isChecked());
1520 maxAgeLA->setEnabled(cacheCB->isChecked());
1525 // specify unique from/to or it doesn't appear. This is really bad UI
1526 // this is why we can use the same function for both new and modify
1527 void PrefConverters::updateConverter()
1529 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1530 Format const & to = form_->formats().get(converterToCO->currentIndex());
1531 string const flags = fromqstr(converterFlagED->text());
1532 string const command = fromqstr(converterED->text());
1534 Converter const * old =
1535 form_->converters().getConverter(from.name(), to.name());
1536 form_->converters().add(from.name(), to.name(), command, flags);
1539 form_->converters().updateLast(form_->formats());
1543 // Remove all files created by this converter from the cache, since
1544 // the modified converter might create different files.
1545 ConverterCache::get().remove_all(from.name(), to.name());
1549 void PrefConverters::removeConverter()
1551 Format const & from = form_->formats().get(converterFromCO->currentIndex());
1552 Format const & to = form_->formats().get(converterToCO->currentIndex());
1553 form_->converters().erase(from.name(), to.name());
1557 // Remove all files created by this converter from the cache, since
1558 // a possible new converter might create different files.
1559 ConverterCache::get().remove_all(from.name(), to.name());
1563 void PrefConverters::on_cacheCB_stateChanged(int state)
1565 maxAgeLE->setEnabled(state == Qt::Checked);
1566 maxAgeLA->setEnabled(state == Qt::Checked);
1571 /////////////////////////////////////////////////////////////////////
1575 /////////////////////////////////////////////////////////////////////
1577 class FormatValidator : public QValidator
1580 FormatValidator(QWidget *, Formats const & f);
1581 void fixup(QString & input) const;
1582 QValidator::State validate(QString & input, int & pos) const;
1584 virtual QString toString(Format const & format) const = 0;
1586 Formats const & formats_;
1590 FormatValidator::FormatValidator(QWidget * parent, Formats const & f)
1591 : QValidator(parent), formats_(f)
1596 void FormatValidator::fixup(QString & input) const
1598 Formats::const_iterator cit = formats_.begin();
1599 Formats::const_iterator end = formats_.end();
1600 for (; cit != end; ++cit) {
1601 QString const name = toString(*cit);
1602 if (distance(formats_.begin(), cit) == nr()) {
1610 QValidator::State FormatValidator::validate(QString & input, int & /*pos*/) const
1612 Formats::const_iterator cit = formats_.begin();
1613 Formats::const_iterator end = formats_.end();
1614 bool unknown = true;
1615 for (; unknown && cit != end; ++cit) {
1616 QString const name = toString(*cit);
1617 if (distance(formats_.begin(), cit) != nr())
1618 unknown = name != input;
1621 if (unknown && !input.isEmpty())
1622 return QValidator::Acceptable;
1624 return QValidator::Intermediate;
1628 int FormatValidator::nr() const
1630 QComboBox * p = qobject_cast<QComboBox *>(parent());
1631 return p->itemData(p->currentIndex()).toInt();
1635 /////////////////////////////////////////////////////////////////////
1637 // FormatNameValidator
1639 /////////////////////////////////////////////////////////////////////
1641 class FormatNameValidator : public FormatValidator
1644 FormatNameValidator(QWidget * parent, Formats const & f)
1645 : FormatValidator(parent, f)
1648 QString toString(Format const & format) const
1650 return toqstr(format.name());
1655 /////////////////////////////////////////////////////////////////////
1657 // FormatPrettynameValidator
1659 /////////////////////////////////////////////////////////////////////
1661 class FormatPrettynameValidator : public FormatValidator
1664 FormatPrettynameValidator(QWidget * parent, Formats const & f)
1665 : FormatValidator(parent, f)
1668 QString toString(Format const & format) const
1670 return qt_(format.prettyname());
1675 /////////////////////////////////////////////////////////////////////
1679 /////////////////////////////////////////////////////////////////////
1681 PrefFileformats::PrefFileformats(GuiPreferences * form)
1682 : PrefModule(qt_(catFiles), qt_("File formats"), form)
1685 formatED->setValidator(new FormatNameValidator(formatsCB, form_->formats()));
1686 formatsCB->setValidator(new FormatPrettynameValidator(formatsCB, form_->formats()));
1688 connect(documentCB, SIGNAL(clicked()),
1689 this, SLOT(setFlags()));
1690 connect(vectorCB, SIGNAL(clicked()),
1691 this, SLOT(setFlags()));
1692 connect(formatsCB->lineEdit(), SIGNAL(editingFinished()),
1693 this, SLOT(updatePrettyname()));
1694 connect(formatsCB->lineEdit(), SIGNAL(textEdited(QString)),
1695 this, SIGNAL(changed()));
1696 connect(defaultFormatCB, SIGNAL(activated(QString)),
1697 this, SIGNAL(changed()));
1698 connect(viewerCO, SIGNAL(activated(int)),
1699 this, SIGNAL(changed()));
1700 connect(editorCO, SIGNAL(activated(int)),
1701 this, SIGNAL(changed()));
1707 string const l10n_shortcut(string const prettyname, string const shortcut)
1709 if (shortcut.empty())
1712 string l10n_format =
1713 to_utf8(_(prettyname + '|' + shortcut));
1714 return split(l10n_format, '|');
1717 }; // namespace anon
1720 void PrefFileformats::apply(LyXRC & rc) const
1722 QString const default_format = defaultFormatCB->itemData(
1723 defaultFormatCB->currentIndex()).toString();
1724 rc.default_view_format = fromqstr(default_format);
1728 void PrefFileformats::update(LyXRC const & rc)
1730 viewer_alternatives = rc.viewer_alternatives;
1731 editor_alternatives = rc.editor_alternatives;
1732 bool const init = defaultFormatCB->currentText().isEmpty();
1736 defaultFormatCB->findData(toqstr(rc.default_view_format));
1737 defaultFormatCB->setCurrentIndex(pos);
1742 void PrefFileformats::updateView()
1744 QString const current = formatsCB->currentText();
1745 QString const current_def = defaultFormatCB->currentText();
1747 // update comboboxes with formats
1748 formatsCB->blockSignals(true);
1749 defaultFormatCB->blockSignals(true);
1751 defaultFormatCB->clear();
1752 form_->formats().sort();
1753 Formats::const_iterator cit = form_->formats().begin();
1754 Formats::const_iterator end = form_->formats().end();
1755 for (; cit != end; ++cit) {
1756 formatsCB->addItem(qt_(cit->prettyname()),
1757 QVariant(form_->formats().getNumber(cit->name())));
1758 if (form_->converters().isReachable("latex", cit->name())
1759 || form_->converters().isReachable("pdflatex", cit->name()))
1760 defaultFormatCB->addItem(qt_(cit->prettyname()),
1761 QVariant(toqstr(cit->name())));
1764 // restore selection
1765 int item = formatsCB->findText(current, Qt::MatchExactly);
1766 formatsCB->setCurrentIndex(item < 0 ? 0 : item);
1767 on_formatsCB_currentIndexChanged(item < 0 ? 0 : item);
1768 item = defaultFormatCB->findText(current_def, Qt::MatchExactly);
1769 defaultFormatCB->setCurrentIndex(item < 0 ? 0 : item);
1770 formatsCB->blockSignals(false);
1771 defaultFormatCB->blockSignals(false);
1775 void PrefFileformats::on_formatsCB_currentIndexChanged(int i)
1777 int const nr = formatsCB->itemData(i).toInt();
1778 Format const f = form_->formats().get(nr);
1780 formatED->setText(toqstr(f.name()));
1781 copierED->setText(toqstr(form_->movers().command(f.name())));
1782 extensionED->setText(toqstr(f.extension()));
1783 shortcutED->setText(
1784 toqstr(l10n_shortcut(f.prettyname(), f.shortcut())));
1785 documentCB->setChecked((f.documentFormat()));
1786 vectorCB->setChecked((f.vectorFormat()));
1792 void PrefFileformats::setFlags()
1794 int flags = Format::none;
1795 if (documentCB->isChecked())
1796 flags |= Format::document;
1797 if (vectorCB->isChecked())
1798 flags |= Format::vector;
1799 currentFormat().setFlags(flags);
1804 void PrefFileformats::on_copierED_textEdited(const QString & s)
1806 string const fmt = fromqstr(formatED->text());
1807 form_->movers().set(fmt, fromqstr(s));
1812 void PrefFileformats::on_extensionED_textEdited(const QString & s)
1814 currentFormat().setExtension(fromqstr(s));
1818 void PrefFileformats::on_viewerED_textEdited(const QString & s)
1820 currentFormat().setViewer(fromqstr(s));
1825 void PrefFileformats::on_editorED_textEdited(const QString & s)
1827 currentFormat().setEditor(fromqstr(s));
1832 void PrefFileformats::on_shortcutED_textEdited(const QString & s)
1834 string const new_shortcut = fromqstr(s);
1835 if (new_shortcut == l10n_shortcut(currentFormat().prettyname(),
1836 currentFormat().shortcut()))
1838 currentFormat().setShortcut(new_shortcut);
1843 void PrefFileformats::on_formatED_editingFinished()
1845 string const newname = fromqstr(formatED->displayText());
1846 if (newname == currentFormat().name())
1849 currentFormat().setName(newname);
1854 void PrefFileformats::on_formatED_textChanged(const QString &)
1856 QString t = formatED->text();
1858 bool valid = formatED->validator()->validate(t, p) == QValidator::Acceptable;
1859 setValid(formatLA, valid);
1863 void PrefFileformats::on_formatsCB_editTextChanged(const QString &)
1865 QString t = formatsCB->currentText();
1867 bool valid = formatsCB->validator()->validate(t, p) == QValidator::Acceptable;
1868 setValid(formatsLA, valid);
1872 void PrefFileformats::updatePrettyname()
1874 QString const newname = formatsCB->currentText();
1875 if (newname == qt_(currentFormat().prettyname()))
1878 currentFormat().setPrettyname(fromqstr(newname));
1886 void updateComboBox(LyXRC::Alternatives const & alts,
1887 string const & fmt, QComboBox * combo)
1889 LyXRC::Alternatives::const_iterator it =
1891 if (it != alts.end()) {
1892 LyXRC::CommandSet const & cmds = it->second;
1893 LyXRC::CommandSet::const_iterator sit =
1895 LyXRC::CommandSet::const_iterator const sen =
1897 for (; sit != sen; ++sit) {
1898 QString const qcmd = toqstr(*sit);
1899 combo->addItem(qcmd, qcmd);
1906 void PrefFileformats::updateViewers()
1908 Format const f = currentFormat();
1909 viewerCO->blockSignals(true);
1911 viewerCO->addItem(qt_("None"), QString());
1912 updateComboBox(viewer_alternatives, f.name(), viewerCO);
1913 viewerCO->addItem(qt_("Custom"), QString("custom viewer"));
1914 viewerCO->blockSignals(false);
1916 int pos = viewerCO->findData(toqstr(f.viewer()));
1919 viewerED->setEnabled(false);
1920 viewerCO->setCurrentIndex(pos);
1922 viewerED->setEnabled(true);
1923 viewerED->setText(toqstr(f.viewer()));
1924 viewerCO->setCurrentIndex(viewerCO->findData(toqstr("custom viewer")));
1929 void PrefFileformats::updateEditors()
1931 Format const f = currentFormat();
1932 editorCO->blockSignals(true);
1934 editorCO->addItem(qt_("None"), QString());
1935 updateComboBox(editor_alternatives, f.name(), editorCO);
1936 editorCO->addItem(qt_("Custom"), QString("custom editor"));
1937 editorCO->blockSignals(false);
1939 int pos = editorCO->findData(toqstr(f.editor()));
1942 editorED->setEnabled(false);
1943 editorCO->setCurrentIndex(pos);
1945 editorED->setEnabled(true);
1946 editorED->setText(toqstr(f.editor()));
1947 editorCO->setCurrentIndex(editorCO->findData(toqstr("custom editor")));
1952 void PrefFileformats::on_viewerCO_currentIndexChanged(int i)
1954 bool const custom = viewerCO->itemData(i).toString() == "custom viewer";
1955 viewerED->setEnabled(custom);
1957 currentFormat().setViewer(fromqstr(viewerCO->itemData(i).toString()));
1961 void PrefFileformats::on_editorCO_currentIndexChanged(int i)
1963 bool const custom = editorCO->itemData(i).toString() == "custom editor";
1964 editorED->setEnabled(custom);
1966 currentFormat().setEditor(fromqstr(editorCO->itemData(i).toString()));
1970 Format & PrefFileformats::currentFormat()
1972 int const i = formatsCB->currentIndex();
1973 int const nr = formatsCB->itemData(i).toInt();
1974 return form_->formats().get(nr);
1978 void PrefFileformats::on_formatNewPB_clicked()
1980 form_->formats().add("", "", "", "", "", "", Format::none);
1982 formatsCB->setCurrentIndex(0);
1983 formatsCB->setFocus(Qt::OtherFocusReason);
1987 void PrefFileformats::on_formatRemovePB_clicked()
1989 int const i = formatsCB->currentIndex();
1990 int const nr = formatsCB->itemData(i).toInt();
1991 string const current_text = form_->formats().get(nr).name();
1992 if (form_->converters().formatIsUsed(current_text)) {
1993 Alert::error(_("Format in use"),
1994 _("Cannot remove a Format used by a Converter. "
1995 "Remove the converter first."));
1999 form_->formats().erase(current_text);
2002 on_formatsCB_editTextChanged(formatsCB->currentText());
2007 /////////////////////////////////////////////////////////////////////
2011 /////////////////////////////////////////////////////////////////////
2013 PrefLanguage::PrefLanguage(GuiPreferences * form)
2014 : PrefModule(qt_(catLanguage), qt_("Language"), form)
2018 connect(rtlGB, SIGNAL(clicked()),
2019 this, SIGNAL(changed()));
2020 connect(visualCursorRB, SIGNAL(clicked()),
2021 this, SIGNAL(changed()));
2022 connect(logicalCursorRB, SIGNAL(clicked()),
2023 this, SIGNAL(changed()));
2024 connect(markForeignCB, SIGNAL(clicked()),
2025 this, SIGNAL(changed()));
2026 connect(autoBeginCB, SIGNAL(clicked()),
2027 this, SIGNAL(changed()));
2028 connect(autoEndCB, SIGNAL(clicked()),
2029 this, SIGNAL(changed()));
2030 connect(useBabelCB, SIGNAL(clicked()),
2031 this, SIGNAL(changed()));
2032 connect(globalCB, SIGNAL(clicked()),
2033 this, SIGNAL(changed()));
2034 connect(languagePackageED, SIGNAL(textChanged(QString)),
2035 this, SIGNAL(changed()));
2036 connect(startCommandED, SIGNAL(textChanged(QString)),
2037 this, SIGNAL(changed()));
2038 connect(endCommandED, SIGNAL(textChanged(QString)),
2039 this, SIGNAL(changed()));
2040 connect(uiLanguageCO, SIGNAL(activated(int)),
2041 this, SIGNAL(changed()));
2043 uiLanguageCO->clear();
2045 QAbstractItemModel * language_model = guiApp->languageModel();
2046 // FIXME: it would be nice if sorting was enabled/disabled via a checkbox.
2047 language_model->sort(0);
2049 // FIXME: This is wrong, we need filter this list based on the available
2051 uiLanguageCO->blockSignals(true);
2052 uiLanguageCO->addItem(qt_("Default"), toqstr("auto"));
2053 for (int i = 0; i != language_model->rowCount(); ++i) {
2054 QModelIndex index = language_model->index(i, 0);
2055 uiLanguageCO->addItem(index.data(Qt::DisplayRole).toString(),
2056 index.data(Qt::UserRole).toString());
2058 uiLanguageCO->blockSignals(false);
2062 void PrefLanguage::on_uiLanguageCO_currentIndexChanged(int)
2064 QMessageBox::information(this, qt_("LyX needs to be restarted!"),
2065 qt_("The change of user interface language will be fully "
2066 "effective only after a restart."));
2070 void PrefLanguage::apply(LyXRC & rc) const
2072 // FIXME: remove rtl_support bool
2073 rc.rtl_support = rtlGB->isChecked();
2074 rc.visual_cursor = rtlGB->isChecked() && visualCursorRB->isChecked();
2075 rc.mark_foreign_language = markForeignCB->isChecked();
2076 rc.language_auto_begin = autoBeginCB->isChecked();
2077 rc.language_auto_end = autoEndCB->isChecked();
2078 rc.language_use_babel = useBabelCB->isChecked();
2079 rc.language_global_options = globalCB->isChecked();
2080 rc.language_package = fromqstr(languagePackageED->text());
2081 rc.language_command_begin = fromqstr(startCommandED->text());
2082 rc.language_command_end = fromqstr(endCommandED->text());
2083 rc.gui_language = fromqstr(
2084 uiLanguageCO->itemData(uiLanguageCO->currentIndex()).toString());
2088 void PrefLanguage::update(LyXRC const & rc)
2090 // FIXME: remove rtl_support bool
2091 rtlGB->setChecked(rc.rtl_support);
2092 if (rc.visual_cursor)
2093 visualCursorRB->setChecked(true);
2095 logicalCursorRB->setChecked(true);
2096 markForeignCB->setChecked(rc.mark_foreign_language);
2097 autoBeginCB->setChecked(rc.language_auto_begin);
2098 autoEndCB->setChecked(rc.language_auto_end);
2099 useBabelCB->setChecked(rc.language_use_babel);
2100 globalCB->setChecked(rc.language_global_options);
2101 languagePackageED->setText(toqstr(rc.language_package));
2102 startCommandED->setText(toqstr(rc.language_command_begin));
2103 endCommandED->setText(toqstr(rc.language_command_end));
2105 int pos = uiLanguageCO->findData(toqstr(rc.gui_language));
2106 uiLanguageCO->blockSignals(true);
2107 uiLanguageCO->setCurrentIndex(pos);
2108 uiLanguageCO->blockSignals(false);
2112 /////////////////////////////////////////////////////////////////////
2116 /////////////////////////////////////////////////////////////////////
2118 PrefPrinter::PrefPrinter(GuiPreferences * form)
2119 : PrefModule(qt_(catOutput), qt_("Printer"), form)
2123 connect(printerAdaptCB, SIGNAL(clicked()),
2124 this, SIGNAL(changed()));
2125 connect(printerCommandED, SIGNAL(textChanged(QString)),
2126 this, SIGNAL(changed()));
2127 connect(printerNameED, SIGNAL(textChanged(QString)),
2128 this, SIGNAL(changed()));
2129 connect(printerPageRangeED, SIGNAL(textChanged(QString)),
2130 this, SIGNAL(changed()));
2131 connect(printerCopiesED, SIGNAL(textChanged(QString)),
2132 this, SIGNAL(changed()));
2133 connect(printerReverseED, SIGNAL(textChanged(QString)),
2134 this, SIGNAL(changed()));
2135 connect(printerToPrinterED, SIGNAL(textChanged(QString)),
2136 this, SIGNAL(changed()));
2137 connect(printerExtensionED, SIGNAL(textChanged(QString)),
2138 this, SIGNAL(changed()));
2139 connect(printerSpoolCommandED, SIGNAL(textChanged(QString)),
2140 this, SIGNAL(changed()));
2141 connect(printerPaperTypeED, SIGNAL(textChanged(QString)),
2142 this, SIGNAL(changed()));
2143 connect(printerEvenED, SIGNAL(textChanged(QString)),
2144 this, SIGNAL(changed()));
2145 connect(printerOddED, SIGNAL(textChanged(QString)),
2146 this, SIGNAL(changed()));
2147 connect(printerCollatedED, SIGNAL(textChanged(QString)),
2148 this, SIGNAL(changed()));
2149 connect(printerLandscapeED, SIGNAL(textChanged(QString)),
2150 this, SIGNAL(changed()));
2151 connect(printerToFileED, SIGNAL(textChanged(QString)),
2152 this, SIGNAL(changed()));
2153 connect(printerExtraED, SIGNAL(textChanged(QString)),
2154 this, SIGNAL(changed()));
2155 connect(printerSpoolPrefixED, SIGNAL(textChanged(QString)),
2156 this, SIGNAL(changed()));
2157 connect(printerPaperSizeED, SIGNAL(textChanged(QString)),
2158 this, SIGNAL(changed()));
2162 void PrefPrinter::apply(LyXRC & rc) const
2164 rc.print_adapt_output = printerAdaptCB->isChecked();
2165 rc.print_command = fromqstr(printerCommandED->text());
2166 rc.printer = fromqstr(printerNameED->text());
2168 rc.print_pagerange_flag = fromqstr(printerPageRangeED->text());
2169 rc.print_copies_flag = fromqstr(printerCopiesED->text());
2170 rc.print_reverse_flag = fromqstr(printerReverseED->text());
2171 rc.print_to_printer = fromqstr(printerToPrinterED->text());
2172 rc.print_file_extension = fromqstr(printerExtensionED->text());
2173 rc.print_spool_command = fromqstr(printerSpoolCommandED->text());
2174 rc.print_paper_flag = fromqstr(printerPaperTypeED->text());
2175 rc.print_evenpage_flag = fromqstr(printerEvenED->text());
2176 rc.print_oddpage_flag = fromqstr(printerOddED->text());
2177 rc.print_collcopies_flag = fromqstr(printerCollatedED->text());
2178 rc.print_landscape_flag = fromqstr(printerLandscapeED->text());
2179 rc.print_to_file = internal_path(fromqstr(printerToFileED->text()));
2180 rc.print_extra_options = fromqstr(printerExtraED->text());
2181 rc.print_spool_printerprefix = fromqstr(printerSpoolPrefixED->text());
2182 rc.print_paper_dimension_flag = fromqstr(printerPaperSizeED->text());
2186 void PrefPrinter::update(LyXRC const & rc)
2188 printerAdaptCB->setChecked(rc.print_adapt_output);
2189 printerCommandED->setText(toqstr(rc.print_command));
2190 printerNameED->setText(toqstr(rc.printer));
2192 printerPageRangeED->setText(toqstr(rc.print_pagerange_flag));
2193 printerCopiesED->setText(toqstr(rc.print_copies_flag));
2194 printerReverseED->setText(toqstr(rc.print_reverse_flag));
2195 printerToPrinterED->setText(toqstr(rc.print_to_printer));
2196 printerExtensionED->setText(toqstr(rc.print_file_extension));
2197 printerSpoolCommandED->setText(toqstr(rc.print_spool_command));
2198 printerPaperTypeED->setText(toqstr(rc.print_paper_flag));
2199 printerEvenED->setText(toqstr(rc.print_evenpage_flag));
2200 printerOddED->setText(toqstr(rc.print_oddpage_flag));
2201 printerCollatedED->setText(toqstr(rc.print_collcopies_flag));
2202 printerLandscapeED->setText(toqstr(rc.print_landscape_flag));
2203 printerToFileED->setText(toqstr(external_path(rc.print_to_file)));
2204 printerExtraED->setText(toqstr(rc.print_extra_options));
2205 printerSpoolPrefixED->setText(toqstr(rc.print_spool_printerprefix));
2206 printerPaperSizeED->setText(toqstr(rc.print_paper_dimension_flag));
2210 /////////////////////////////////////////////////////////////////////
2212 // PrefUserInterface
2214 /////////////////////////////////////////////////////////////////////
2216 PrefUserInterface::PrefUserInterface(GuiPreferences * form)
2217 : PrefModule(qt_(catLookAndFeel), qt_("User interface"), form)
2221 connect(autoSaveCB, SIGNAL(toggled(bool)),
2222 autoSaveSB, SLOT(setEnabled(bool)));
2223 connect(autoSaveCB, SIGNAL(toggled(bool)),
2224 TextLabel1, SLOT(setEnabled(bool)));
2225 connect(openDocumentsInTabsCB, SIGNAL(clicked()),
2226 this, SIGNAL(changed()));
2227 #if QT_VERSION < 0x040500
2228 singleCloseTabButtonCB->setEnabled(false);
2230 connect(singleCloseTabButtonCB, SIGNAL(clicked()),
2231 this, SIGNAL(changed()));
2232 connect(uiFilePB, SIGNAL(clicked()),
2233 this, SLOT(selectUi()));
2234 connect(uiFileED, SIGNAL(textChanged(QString)),
2235 this, SIGNAL(changed()));
2236 connect(restoreCursorCB, SIGNAL(clicked()),
2237 this, SIGNAL(changed()));
2238 connect(loadSessionCB, SIGNAL(clicked()),
2239 this, SIGNAL(changed()));
2240 connect(allowGeometrySessionCB, SIGNAL(clicked()),
2241 this, SIGNAL(changed()));
2242 connect(autoSaveSB, SIGNAL(valueChanged(int)),
2243 this, SIGNAL(changed()));
2244 connect(autoSaveCB, SIGNAL(clicked()),
2245 this, SIGNAL(changed()));
2246 connect(backupCB, SIGNAL(clicked()),
2247 this, SIGNAL(changed()));
2248 connect(saveCompressedCB, SIGNAL(clicked()),
2249 this, SIGNAL(changed()));
2250 connect(lastfilesSB, SIGNAL(valueChanged(int)),
2251 this, SIGNAL(changed()));
2252 connect(tooltipCB, SIGNAL(toggled(bool)),
2253 this, SIGNAL(changed()));
2254 lastfilesSB->setMaximum(maxlastfiles);
2258 void PrefUserInterface::apply(LyXRC & rc) const
2260 rc.ui_file = internal_path(fromqstr(uiFileED->text()));
2261 rc.use_lastfilepos = restoreCursorCB->isChecked();
2262 rc.load_session = loadSessionCB->isChecked();
2263 rc.allow_geometry_session = allowGeometrySessionCB->isChecked();
2264 rc.autosave = autoSaveCB->isChecked() ? autoSaveSB->value() * 60 : 0;
2265 rc.make_backup = backupCB->isChecked();
2266 rc.save_compressed = saveCompressedCB->isChecked();
2267 rc.num_lastfiles = lastfilesSB->value();
2268 rc.use_tooltip = tooltipCB->isChecked();
2269 rc.open_buffers_in_tabs = openDocumentsInTabsCB->isChecked();
2270 rc.single_close_tab_button = singleCloseTabButtonCB->isChecked();
2271 #if QT_VERSION < 0x040500
2272 rc.single_close_tab_button = true;
2277 void PrefUserInterface::update(LyXRC const & rc)
2279 uiFileED->setText(toqstr(external_path(rc.ui_file)));
2280 restoreCursorCB->setChecked(rc.use_lastfilepos);
2281 loadSessionCB->setChecked(rc.load_session);
2282 allowGeometrySessionCB->setChecked(rc.allow_geometry_session);
2283 // convert to minutes
2284 bool autosave = rc.autosave > 0;
2285 int mins = rc.autosave / 60;
2288 autoSaveSB->setValue(mins);
2289 autoSaveCB->setChecked(autosave);
2290 autoSaveSB->setEnabled(autosave);
2291 backupCB->setChecked(rc.make_backup);
2292 saveCompressedCB->setChecked(rc.save_compressed);
2293 lastfilesSB->setValue(rc.num_lastfiles);
2294 tooltipCB->setChecked(rc.use_tooltip);
2295 openDocumentsInTabsCB->setChecked(rc.open_buffers_in_tabs);
2296 singleCloseTabButtonCB->setChecked(rc.single_close_tab_button);
2300 void PrefUserInterface::selectUi()
2302 QString file = form_->browseUI(internalPath(uiFileED->text()));
2303 if (!file.isEmpty())
2304 uiFileED->setText(file);
2308 void PrefUserInterface::on_clearSessionPB_clicked()
2310 guiApp->clearSession();
2315 /////////////////////////////////////////////////////////////////////
2319 /////////////////////////////////////////////////////////////////////
2321 PrefEdit::PrefEdit(GuiPreferences * form)
2322 : PrefModule(qt_(catEditing), qt_("Control"), form)
2326 connect(cursorFollowsCB, SIGNAL(clicked()),
2327 this, SIGNAL(changed()));
2328 connect(scrollBelowCB, SIGNAL(clicked()),
2329 this, SIGNAL(changed()));
2330 connect(sortEnvironmentsCB, SIGNAL(clicked()),
2331 this, SIGNAL(changed()));
2332 connect(groupEnvironmentsCB, SIGNAL(clicked()),
2333 this, SIGNAL(changed()));
2334 connect(macroEditStyleCO, SIGNAL(activated(int)),
2335 this, SIGNAL(changed()));
2336 connect(fullscreenLimitGB, SIGNAL(clicked()),
2337 this, SIGNAL(changed()));
2338 connect(fullscreenWidthSB, SIGNAL(valueChanged(int)),
2339 this, SIGNAL(changed()));
2340 connect(toggleTabbarCB, SIGNAL(toggled(bool)),
2341 this, SIGNAL(changed()));
2342 connect(toggleMenubarCB, SIGNAL(toggled(bool)),
2343 this, SIGNAL(changed()));
2344 connect(toggleScrollbarCB, SIGNAL(toggled(bool)),
2345 this, SIGNAL(changed()));
2346 connect(toggleToolbarsCB, SIGNAL(toggled(bool)),
2347 this, SIGNAL(changed()));
2351 void PrefEdit::apply(LyXRC & rc) const
2353 rc.cursor_follows_scrollbar = cursorFollowsCB->isChecked();
2354 rc.scroll_below_document = scrollBelowCB->isChecked();
2355 rc.sort_layouts = sortEnvironmentsCB->isChecked();
2356 rc.group_layouts = groupEnvironmentsCB->isChecked();
2357 switch (macroEditStyleCO->currentIndex()) {
2358 case 0: rc.macro_edit_style = LyXRC::MACRO_EDIT_INLINE_BOX; break;
2359 case 1: rc.macro_edit_style = LyXRC::MACRO_EDIT_INLINE; break;
2360 case 2: rc.macro_edit_style = LyXRC::MACRO_EDIT_LIST; break;
2362 rc.full_screen_toolbars = toggleToolbarsCB->isChecked();
2363 rc.full_screen_scrollbar = toggleScrollbarCB->isChecked();
2364 rc.full_screen_tabbar = toggleTabbarCB->isChecked();
2365 rc.full_screen_menubar = toggleMenubarCB->isChecked();
2366 rc.full_screen_width = fullscreenWidthSB->value();
2367 rc.full_screen_limit = fullscreenLimitGB->isChecked();
2371 void PrefEdit::update(LyXRC const & rc)
2373 cursorFollowsCB->setChecked(rc.cursor_follows_scrollbar);
2374 scrollBelowCB->setChecked(rc.scroll_below_document);
2375 sortEnvironmentsCB->setChecked(rc.sort_layouts);
2376 groupEnvironmentsCB->setChecked(rc.group_layouts);
2377 macroEditStyleCO->setCurrentIndex(rc.macro_edit_style);
2378 toggleScrollbarCB->setChecked(rc.full_screen_scrollbar);
2379 toggleToolbarsCB->setChecked(rc.full_screen_toolbars);
2380 toggleTabbarCB->setChecked(rc.full_screen_tabbar);
2381 toggleMenubarCB->setChecked(rc.full_screen_menubar);
2382 fullscreenWidthSB->setValue(rc.full_screen_width);
2383 fullscreenLimitGB->setChecked(rc.full_screen_limit);
2387 /////////////////////////////////////////////////////////////////////
2391 /////////////////////////////////////////////////////////////////////
2394 GuiShortcutDialog::GuiShortcutDialog(QWidget * parent) : QDialog(parent)
2396 Ui::shortcutUi::setupUi(this);
2397 QDialog::setModal(true);
2401 PrefShortcuts::PrefShortcuts(GuiPreferences * form)
2402 : PrefModule(qt_(catEditing), qt_("Shortcuts"), form)
2406 shortcutsTW->setColumnCount(2);
2407 shortcutsTW->headerItem()->setText(0, qt_("Function"));
2408 shortcutsTW->headerItem()->setText(1, qt_("Shortcut"));
2409 shortcutsTW->setSortingEnabled(true);
2410 // Multi-selection can be annoying.
2411 // shortcutsTW->setSelectionMode(QAbstractItemView::MultiSelection);
2413 connect(bindFilePB, SIGNAL(clicked()),
2414 this, SLOT(selectBind()));
2415 connect(bindFileED, SIGNAL(textChanged(QString)),
2416 this, SIGNAL(changed()));
2418 shortcut_ = new GuiShortcutDialog(this);
2419 shortcut_bc_.setPolicy(ButtonPolicy::OkCancelPolicy);
2420 shortcut_bc_.setOK(shortcut_->okPB);
2421 shortcut_bc_.setCancel(shortcut_->cancelPB);
2423 connect(shortcut_->okPB, SIGNAL(clicked()),
2424 shortcut_, SLOT(accept()));
2425 connect(shortcut_->okPB, SIGNAL(clicked()),
2426 this, SIGNAL(changed()));
2427 connect(shortcut_->cancelPB, SIGNAL(clicked()),
2428 shortcut_, SLOT(reject()));
2429 connect(shortcut_->clearPB, SIGNAL(clicked()),
2430 this, SLOT(shortcutClearPressed()));
2431 connect(shortcut_->removePB, SIGNAL(clicked()),
2432 this, SLOT(shortcutRemovePressed()));
2433 connect(shortcut_->okPB, SIGNAL(clicked()),
2434 this, SLOT(shortcutOkPressed()));
2435 connect(shortcut_->cancelPB, SIGNAL(clicked()),
2436 this, SLOT(shortcutCancelPressed()));
2440 void PrefShortcuts::apply(LyXRC & rc) const
2442 rc.bind_file = internal_path(fromqstr(bindFileED->text()));
2443 // write user_bind and user_unbind to .lyx/bind/user.bind
2444 FileName bind_dir(addPath(package().user_support().absFilename(), "bind"));
2445 if (!bind_dir.exists() && !bind_dir.createDirectory(0777)) {
2446 lyxerr << "LyX could not create the user bind directory '"
2447 << bind_dir << "'. All user-defined key bindings will be lost." << endl;
2450 if (!bind_dir.isDirWritable()) {
2451 lyxerr << "LyX could not write to the user bind directory '"
2452 << bind_dir << "'. All user-defined key bindings will be lost." << endl;
2455 FileName user_bind_file(bind_dir.absFilename() + "/user.bind");
2456 user_unbind_.write(user_bind_file.toFilesystemEncoding(), false, true);
2457 user_bind_.write(user_bind_file.toFilesystemEncoding(), true, false);
2458 // immediately apply the keybindings. Why this is not done before?
2459 // The good thing is that the menus are updated automatically.
2460 theTopLevelKeymap().clear();
2461 theTopLevelKeymap().read("site");
2462 theTopLevelKeymap().read(rc.bind_file, 0, KeyMap::Fallback);
2463 theTopLevelKeymap().read("user", 0, KeyMap::MissingOK);
2467 void PrefShortcuts::update(LyXRC const & rc)
2469 bindFileED->setText(toqstr(external_path(rc.bind_file)));
2471 system_bind_.clear();
2473 user_unbind_.clear();
2474 system_bind_.read("site");
2475 system_bind_.read(rc.bind_file);
2476 // \unbind in user.bind is added to user_unbind_
2477 user_bind_.read("user", &user_unbind_, KeyMap::MissingOK);
2478 updateShortcutsTW();
2482 void PrefShortcuts::updateShortcutsTW()
2484 shortcutsTW->clear();
2486 editItem_ = new QTreeWidgetItem(shortcutsTW);
2487 editItem_->setText(0, qt_("Cursor, Mouse and Editing functions"));
2488 editItem_->setFlags(editItem_->flags() & ~Qt::ItemIsSelectable);
2490 mathItem_ = new QTreeWidgetItem(shortcutsTW);
2491 mathItem_->setText(0, qt_("Mathematical Symbols"));
2492 mathItem_->setFlags(mathItem_->flags() & ~Qt::ItemIsSelectable);
2494 bufferItem_ = new QTreeWidgetItem(shortcutsTW);
2495 bufferItem_->setText(0, qt_("Document and Window"));
2496 bufferItem_->setFlags(bufferItem_->flags() & ~Qt::ItemIsSelectable);
2498 layoutItem_ = new QTreeWidgetItem(shortcutsTW);
2499 layoutItem_->setText(0, qt_("Font, Layouts and Textclasses"));
2500 layoutItem_->setFlags(layoutItem_->flags() & ~Qt::ItemIsSelectable);
2502 systemItem_ = new QTreeWidgetItem(shortcutsTW);
2503 systemItem_->setText(0, qt_("System and Miscellaneous"));
2504 systemItem_->setFlags(systemItem_->flags() & ~Qt::ItemIsSelectable);
2506 // listBindings(unbound=true) lists all bound and unbound lfuns
2507 // Items in this list is tagged by its source.
2508 KeyMap::BindingList bindinglist = system_bind_.listBindings(true,
2510 KeyMap::BindingList user_bindinglist = user_bind_.listBindings(false,
2512 KeyMap::BindingList user_unbindinglist = user_unbind_.listBindings(false,
2513 KeyMap::UserUnbind);
2514 bindinglist.insert(bindinglist.end(), user_bindinglist.begin(),
2515 user_bindinglist.end());
2516 bindinglist.insert(bindinglist.end(), user_unbindinglist.begin(),
2517 user_unbindinglist.end());
2519 KeyMap::BindingList::const_iterator it = bindinglist.begin();
2520 KeyMap::BindingList::const_iterator it_end = bindinglist.end();
2521 for (; it != it_end; ++it)
2522 insertShortcutItem(it->request, it->sequence, KeyMap::ItemType(it->tag));
2524 shortcutsTW->sortItems(0, Qt::AscendingOrder);
2525 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
2526 removePB->setEnabled(!items.isEmpty() && !items[0]->text(1).isEmpty());
2527 modifyPB->setEnabled(!items.isEmpty());
2529 shortcutsTW->resizeColumnToContents(0);
2533 void PrefShortcuts::setItemType(QTreeWidgetItem * item, KeyMap::ItemType tag)
2535 item->setData(0, Qt::UserRole, QVariant(tag));
2539 case KeyMap::System:
2541 case KeyMap::UserBind:
2544 case KeyMap::UserUnbind:
2545 font.setStrikeOut(true);
2547 // this item is not displayed now.
2548 case KeyMap::UserExtraUnbind:
2549 font.setStrikeOut(true);
2553 item->setFont(1, font);
2557 QTreeWidgetItem * PrefShortcuts::insertShortcutItem(FuncRequest const & lfun,
2558 KeySequence const & seq, KeyMap::ItemType tag)
2560 FuncCode const action = lfun.action();
2561 string const action_name = lyxaction.getActionName(action);
2562 QString const lfun_name = toqstr(from_utf8(action_name)
2563 + ' ' + lfun.argument());
2564 QString const shortcut = toqstr(seq.print(KeySequence::ForGui));
2565 KeyMap::ItemType item_tag = tag;
2567 QTreeWidgetItem * newItem = 0;
2568 // for unbind items, try to find an existing item in the system bind list
2569 if (tag == KeyMap::UserUnbind) {
2570 QList<QTreeWidgetItem*> const items = shortcutsTW->findItems(lfun_name,
2571 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 0);
2572 for (int i = 0; i < items.size(); ++i) {
2573 if (items[i]->text(1) == shortcut)
2577 // if not found, this unbind item is KeyMap::UserExtraUnbind
2578 // Such an item is not displayed to avoid confusion (what is
2579 // unmatched removed?).
2581 item_tag = KeyMap::UserExtraUnbind;
2586 switch(lyxaction.getActionType(action)) {
2587 case LyXAction::Hidden:
2589 case LyXAction::Edit:
2590 newItem = new QTreeWidgetItem(editItem_);
2592 case LyXAction::Math:
2593 newItem = new QTreeWidgetItem(mathItem_);
2595 case LyXAction::Buffer:
2596 newItem = new QTreeWidgetItem(bufferItem_);
2598 case LyXAction::Layout:
2599 newItem = new QTreeWidgetItem(layoutItem_);
2601 case LyXAction::System:
2602 newItem = new QTreeWidgetItem(systemItem_);
2605 // this should not happen
2606 newItem = new QTreeWidgetItem(shortcutsTW);
2610 newItem->setText(0, lfun_name);
2611 newItem->setText(1, shortcut);
2612 // record BindFile representation to recover KeySequence when needed.
2613 newItem->setData(1, Qt::UserRole, toqstr(seq.print(KeySequence::BindFile)));
2614 setItemType(newItem, item_tag);
2619 void PrefShortcuts::on_shortcutsTW_itemSelectionChanged()
2621 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
2622 removePB->setEnabled(!items.isEmpty() && !items[0]->text(1).isEmpty());
2623 modifyPB->setEnabled(!items.isEmpty());
2624 if (items.isEmpty())
2627 KeyMap::ItemType tag =
2628 static_cast<KeyMap::ItemType>(items[0]->data(0, Qt::UserRole).toInt());
2629 if (tag == KeyMap::UserUnbind)
2630 removePB->setText(qt_("Res&tore"));
2632 removePB->setText(qt_("Remo&ve"));
2636 void PrefShortcuts::on_shortcutsTW_itemDoubleClicked()
2642 void PrefShortcuts::modifyShortcut()
2644 QTreeWidgetItem * item = shortcutsTW->currentItem();
2645 if (item->flags() & Qt::ItemIsSelectable) {
2646 shortcut_->lfunLE->setText(item->text(0));
2647 save_lfun_ = item->text(0).trimmed();
2648 shortcut_->shortcutWG->setText(item->text(1));
2650 seq.parse(fromqstr(item->data(1, Qt::UserRole).toString()));
2651 shortcut_->shortcutWG->setKeySequence(seq);
2652 shortcut_->shortcutWG->setFocus();
2658 void PrefShortcuts::removeShortcut()
2660 // it seems that only one item can be selected, but I am
2661 // removing all selected items anyway.
2662 QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
2663 for (int i = 0; i < items.size(); ++i) {
2664 string shortcut = fromqstr(items[i]->data(1, Qt::UserRole).toString());
2665 string lfun = fromqstr(items[i]->text(0));
2666 FuncRequest func = lyxaction.lookupFunc(lfun);
2667 KeyMap::ItemType tag =
2668 static_cast<KeyMap::ItemType>(items[i]->data(0, Qt::UserRole).toInt());
2671 case KeyMap::System: {
2672 // for system bind, we do not touch the item
2673 // but add an user unbind item
2674 user_unbind_.bind(shortcut, func);
2675 setItemType(items[i], KeyMap::UserUnbind);
2676 removePB->setText(qt_("Res&tore"));
2679 case KeyMap::UserBind: {
2680 // for user_bind, we remove this bind
2681 QTreeWidgetItem * parent = items[i]->parent();
2682 int itemIdx = parent->indexOfChild(items[i]);
2683 parent->takeChild(itemIdx);
2685 shortcutsTW->scrollToItem(parent->child(itemIdx - 1));
2687 shortcutsTW->scrollToItem(parent);
2688 user_bind_.unbind(shortcut, func);
2691 case KeyMap::UserUnbind: {
2692 // for user_unbind, we remove the unbind, and the item
2693 // become KeyMap::System again.
2694 user_unbind_.unbind(shortcut, func);
2695 setItemType(items[i], KeyMap::System);
2696 removePB->setText(qt_("Remo&ve"));
2699 case KeyMap::UserExtraUnbind: {
2700 // for user unbind that is not in system bind file,
2701 // remove this unbind file
2702 QTreeWidgetItem * parent = items[i]->parent();
2703 parent->takeChild(parent->indexOfChild(items[i]));
2704 user_unbind_.unbind(shortcut, func);
2711 void PrefShortcuts::selectBind()
2713 QString file = form_->browsebind(internalPath(bindFileED->text()));
2714 if (!file.isEmpty()) {
2715 bindFileED->setText(file);
2716 system_bind_ = KeyMap();
2717 system_bind_.read(fromqstr(file));
2718 updateShortcutsTW();
2723 void PrefShortcuts::on_modifyPB_pressed()
2729 void PrefShortcuts::on_newPB_pressed()
2731 shortcut_->lfunLE->clear();
2732 shortcut_->shortcutWG->reset();
2733 save_lfun_ = QString();
2738 void PrefShortcuts::on_removePB_pressed()
2745 void PrefShortcuts::on_searchLE_textEdited()
2747 if (searchLE->text().isEmpty()) {
2748 // show all hidden items
2749 QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Hidden);
2751 shortcutsTW->setItemHidden(*it++, false);
2754 // search both columns
2755 QList<QTreeWidgetItem *> matched = shortcutsTW->findItems(searchLE->text(),
2756 Qt::MatchFlags(Qt::MatchContains | Qt::MatchRecursive), 0);
2757 matched += shortcutsTW->findItems(searchLE->text(),
2758 Qt::MatchFlags(Qt::MatchContains | Qt::MatchRecursive), 1);
2760 // hide everyone (to avoid searching in matched QList repeatedly
2761 QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Selectable);
2763 shortcutsTW->setItemHidden(*it++, true);
2764 // show matched items
2765 for (int i = 0; i < matched.size(); ++i) {
2766 shortcutsTW->setItemHidden(matched[i], false);
2767 shortcutsTW->setItemExpanded(matched[i]->parent(), true);
2772 docstring makeCmdString(FuncRequest const & f)
2774 docstring actionStr = from_ascii(lyxaction.getActionName(f.action()));
2775 if (!f.argument().empty())
2776 actionStr += " " + f.argument();
2781 void PrefShortcuts::shortcutOkPressed()
2783 QString const new_lfun = shortcut_->lfunLE->text();
2784 FuncRequest func = lyxaction.lookupFunc(fromqstr(new_lfun));
2786 if (func.action() == LFUN_UNKNOWN_ACTION) {
2787 Alert::error(_("Failed to create shortcut"),
2788 _("Unknown or invalid LyX function"));
2792 KeySequence k = shortcut_->shortcutWG->getKeySequence();
2793 if (k.length() == 0) {
2794 Alert::error(_("Failed to create shortcut"),
2795 _("Invalid or empty key sequence"));
2799 // check to see if there's been any change
2800 FuncRequest oldBinding = system_bind_.getBinding(k);
2801 if (oldBinding.action() == LFUN_UNKNOWN_ACTION)
2802 oldBinding = user_bind_.getBinding(k);
2803 if (oldBinding == func)
2804 // nothing has changed
2807 // make sure this key isn't already bound---and, if so, not unbound
2808 FuncCode const unbind = user_unbind_.getBinding(k).action();
2809 docstring const action_string = makeCmdString(oldBinding);
2810 if (oldBinding.action() > LFUN_NOACTION && unbind == LFUN_UNKNOWN_ACTION
2811 && save_lfun_ != toqstr(action_string)) {
2812 // FIXME Perhaps we should offer to over-write the old shortcut?
2813 // If so, we'll need to remove it from our list, etc.
2814 Alert::error(_("Failed to create shortcut"),
2815 bformat(_("Shortcut `%1$s' is already bound to:\n%2$s\n"
2816 "You need to remove that binding before creating a new one."),
2817 k.print(KeySequence::ForGui), action_string));
2821 if (!save_lfun_.isEmpty())
2822 // real modification of the lfun's shortcut,
2823 // so remove the previous one
2826 QTreeWidgetItem * item = insertShortcutItem(func, k, KeyMap::UserBind);
2828 user_bind_.bind(&k, func);
2829 shortcutsTW->sortItems(0, Qt::AscendingOrder);
2830 shortcutsTW->setItemExpanded(item->parent(), true);
2831 shortcutsTW->scrollToItem(item);
2833 Alert::error(_("Failed to create shortcut"),
2834 _("Can not insert shortcut to the list"));
2840 void PrefShortcuts::shortcutCancelPressed()
2842 shortcut_->shortcutWG->reset();
2846 void PrefShortcuts::shortcutClearPressed()
2848 shortcut_->shortcutWG->reset();
2852 void PrefShortcuts::shortcutRemovePressed()
2854 shortcut_->shortcutWG->removeFromSequence();
2858 /////////////////////////////////////////////////////////////////////
2862 /////////////////////////////////////////////////////////////////////
2864 PrefIdentity::PrefIdentity(GuiPreferences * form)
2865 : PrefModule(QString(), qt_("Identity"), form)
2869 connect(nameED, SIGNAL(textChanged(QString)),
2870 this, SIGNAL(changed()));
2871 connect(emailED, SIGNAL(textChanged(QString)),
2872 this, SIGNAL(changed()));
2876 void PrefIdentity::apply(LyXRC & rc) const
2878 rc.user_name = fromqstr(nameED->text());
2879 rc.user_email = fromqstr(emailED->text());
2883 void PrefIdentity::update(LyXRC const & rc)
2885 nameED->setText(toqstr(rc.user_name));
2886 emailED->setText(toqstr(rc.user_email));
2891 /////////////////////////////////////////////////////////////////////
2895 /////////////////////////////////////////////////////////////////////
2897 GuiPreferences::GuiPreferences(GuiView & lv)
2898 : GuiDialog(lv, "prefs", qt_("Preferences")), update_screen_font_(false)
2902 QDialog::setModal(false);
2904 connect(savePB, SIGNAL(clicked()), this, SLOT(slotOK()));
2905 connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
2906 connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
2907 connect(restorePB, SIGNAL(clicked()), this, SLOT(slotRestore()));
2909 addModule(new PrefUserInterface(this));
2910 addModule(new PrefEdit(this));
2911 addModule(new PrefShortcuts(this));
2912 addModule(new PrefScreenFonts(this));
2913 addModule(new PrefColors(this));
2914 addModule(new PrefDisplay(this));
2915 addModule(new PrefInput(this));
2916 addModule(new PrefCompletion(this));
2918 addModule(new PrefPaths(this));
2920 addModule(new PrefIdentity(this));
2922 addModule(new PrefLanguage(this));
2923 addModule(new PrefSpellchecker(this));
2925 //for strftime validator
2926 PrefOutput * output = new PrefOutput(this);
2928 addModule(new PrefPrinter(this));
2929 addModule(new PrefLatex(this));
2931 PrefConverters * converters = new PrefConverters(this);
2932 PrefFileformats * formats = new PrefFileformats(this);
2933 connect(formats, SIGNAL(formatsChanged()),
2934 converters, SLOT(updateGui()));
2935 addModule(converters);
2938 prefsPS->setCurrentPanel(qt_("User interface"));
2939 // FIXME: hack to work around resizing bug in Qt >= 4.2
2940 // bug verified with Qt 4.2.{0-3} (JSpitzm)
2941 #if QT_VERSION >= 0x040200
2942 prefsPS->updateGeometry();
2945 bc().setPolicy(ButtonPolicy::PreferencesPolicy);
2947 bc().setApply(applyPB);
2948 bc().setCancel(closePB);
2949 bc().setRestore(restorePB);
2951 // initialize the strftime validator
2952 bc().addCheckedLineEdit(output->DateED);
2956 void GuiPreferences::addModule(PrefModule * module)
2958 LASSERT(module, return);
2959 if (module->category().isEmpty())
2960 prefsPS->addPanel(module, module->title());
2962 prefsPS->addPanel(module, module->title(), module->category());
2963 connect(module, SIGNAL(changed()), this, SLOT(change_adaptor()));
2964 modules_.push_back(module);
2968 void GuiPreferences::change_adaptor()
2974 void GuiPreferences::apply(LyXRC & rc) const
2976 size_t end = modules_.size();
2977 for (size_t i = 0; i != end; ++i)
2978 modules_[i]->apply(rc);
2982 void GuiPreferences::updateRc(LyXRC const & rc)
2984 size_t const end = modules_.size();
2985 for (size_t i = 0; i != end; ++i)
2986 modules_[i]->update(rc);
2990 void GuiPreferences::applyView()
2995 bool GuiPreferences::initialiseParams(string const &)
2998 formats_ = lyx::formats;
2999 converters_ = theConverters();
3000 converters_.update(formats_);
3001 movers_ = theMovers();
3003 update_screen_font_ = false;
3006 // Make sure that the bc is in the INITIAL state
3007 if (bc().policy().buttonStatus(ButtonPolicy::RESTORE))
3014 void GuiPreferences::dispatchParams()
3017 rc_.write(ss, true);
3018 dispatch(FuncRequest(LFUN_LYXRC_APPLY, ss.str()));
3019 // FIXME: these need lfuns
3021 theBufferList().setCurrentAuthor(from_utf8(rc_.user_name), from_utf8(rc_.user_email));
3023 lyx::formats = formats_;
3025 theConverters() = converters_;
3026 theConverters().update(lyx::formats);
3027 theConverters().buildGraph();
3029 theMovers() = movers_;
3031 vector<string>::const_iterator it = colors_.begin();
3032 vector<string>::const_iterator const end = colors_.end();
3033 for (; it != end; ++it)
3034 dispatch(FuncRequest(LFUN_SET_COLOR, *it));
3037 if (update_screen_font_) {
3038 dispatch(FuncRequest(LFUN_SCREEN_FONT_UPDATE));
3039 update_screen_font_ = false;
3042 // The Save button has been pressed
3044 dispatch(FuncRequest(LFUN_PREFERENCES_SAVE));
3048 void GuiPreferences::setColor(ColorCode col, QString const & hex)
3050 colors_.push_back(lcolor.getLyXName(col) + ' ' + fromqstr(hex));
3054 void GuiPreferences::updateScreenFonts()
3056 update_screen_font_ = true;
3060 QString GuiPreferences::browsebind(QString const & file) const
3062 return browseLibFile("bind", file, "bind", qt_("Choose bind file"),
3063 QStringList(qt_("LyX bind files (*.bind)")));
3067 QString GuiPreferences::browseUI(QString const & file) const
3069 return browseLibFile("ui", file, "ui", qt_("Choose UI file"),
3070 QStringList(qt_("LyX UI files (*.ui)")));
3074 QString GuiPreferences::browsekbmap(QString const & file) const
3076 return browseLibFile("kbd", file, "kmap", qt_("Choose keyboard map"),
3077 QStringList(qt_("LyX keyboard maps (*.kmap)")));
3081 QString GuiPreferences::browse(QString const & file,
3082 QString const & title) const
3084 return browseFile(file, title, QStringList(), true);
3088 // We support less paper sizes than the document dialog
3089 // Therefore this adjustment is needed.
3090 PAPER_SIZE GuiPreferences::toPaperSize(int i) const
3094 return PAPER_DEFAULT;
3096 return PAPER_USLETTER;
3098 return PAPER_USLEGAL;
3100 return PAPER_USEXECUTIVE;
3110 // should not happen
3111 return PAPER_DEFAULT;
3116 int GuiPreferences::fromPaperSize(PAPER_SIZE papersize) const
3118 switch (papersize) {
3121 case PAPER_USLETTER:
3125 case PAPER_USEXECUTIVE:
3136 // should not happen
3142 Dialog * createGuiPreferences(GuiView & lv) { return new GuiPreferences(lv); }
3145 } // namespace frontend
3148 #include "moc_GuiPrefs.cpp"