string::size_type const res = k.parse(seq);
if (res == string::npos) {
- defkey(&k, func);
+ bind(&k, func);
} else {
LYXERR(Debug::KBMAP) << "Parse error at position " << res
<< " in key sequence '" << seq << "'."
string::size_type const res = k.parse(seq);
if (res == string::npos)
- delkey(&k, func);
+ unbind(&k, func);
else
LYXERR(Debug::KBMAP) << "Parse error at position " << res
<< " in key sequence '" << seq << "'."
}
-void KeyMap::defkey(KeySequence * seq, FuncRequest const & func, unsigned int r)
+void KeyMap::bind(KeySequence * seq, FuncRequest const & func, unsigned int r)
{
KeySymbol code = seq->sequence[r];
if (!code.isOK())
<< endl;
return;
} else {
- it->table->defkey(seq, func, r + 1);
+ it->table->bind(seq, func, r + 1);
return;
}
}
newone->table.reset();
} else {
newone->table.reset(new KeyMap);
- newone->table->defkey(seq, func, r + 1);
+ newone->table->bind(seq, func, r + 1);
}
}
-void KeyMap::delkey(KeySequence * seq, FuncRequest const & func, unsigned int r)
+void KeyMap::unbind(KeySequence * seq, FuncRequest const & func, unsigned int r)
{
KeySymbol code = seq->sequence[r];
if (!code.isOK())
it->table.reset();
}
} else if (it->table.get()) {
- it->table->delkey(seq, func, r + 1);
+ it->table->unbind(seq, func, r + 1);
if (it->table->empty())
remove = it;
return;
class KeyMap {
public:
/**
- * Bind a key sequence to an action.
+ * Bind/Unbind a key sequence to an action.
* @return 0 on success, or position in string seq where error
* occurs.
* See KeySequence::parse for the syntax of the seq string
*/
size_t bind(std::string const & seq, FuncRequest const & func);
-
- // Unbind a key sequence
size_t unbind(std::string const & seq, FuncRequest const & func);
+ /**
+ * Define/Undefine an action for a key sequence.
+ * @param r internal recursion level
+ */
+ void bind(KeySequence * seq, FuncRequest const & func,
+ unsigned int r = 0);
+ void unbind(KeySequence * seq, FuncRequest const & func,
+ unsigned int r = 0);
+
+
// if a keybinding has been defined.
bool hasBinding(KeySequence const & seq, FuncRequest const & func,
unsigned int r = 0);
FuncRequest func;
};
- /**
- * Define an action for a key sequence.
- * @param r internal recursion level
- */
- void defkey(KeySequence * seq, FuncRequest const & func,
- unsigned int r = 0);
- void delkey(KeySequence * seq, FuncRequest const & func,
- unsigned int r = 0);
-
/**
* Given an action, find all keybindings
* @param func the action
#include "CustomizedWidgets.h"
#include "GuiKeySymbol.h"
+#include <QApplication>
+#include <QCloseEvent>
+
#include "support/qstring_helpers.h"
using lyx::KeySymbol;
+using lyx::KeySequence;
+using lyx::KeyModifier;
using lyx::toqstr;
+ShortcutLineEdit::ShortcutLineEdit(QWidget * parent)
+ : QLineEdit(parent), keysequence_()
+{
+ QApplication::instance()->installEventFilter(this);
+ has_cursor_ = false;
+}
+
+
+void ShortcutLineEdit::reset()
+{
+ clear();
+ keysequence_ = KeySequence();
+}
+
+
+bool ShortcutLineEdit::eventFilter(QObject * obj, QEvent * e)
+{
+ if (!has_cursor_)
+ return false;
+
+ switch (e->type()) {
+ // swallow these if we have focus and they come from elsewhere
+ case QEvent::Shortcut:
+ case QEvent::ShortcutOverride:
+ if (obj != this)
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+
+KeySequence const ShortcutLineEdit::getKeySequence() const
+{
+ return keysequence_;
+}
+
+
void ShortcutLineEdit::keyPressEvent(QKeyEvent * e)
{
- int keyQt = e->key();
- switch (e->key()) {
+ int const keyQt = e->key();
+ if (!keyQt)
+ return;
+
+ switch(keyQt) {
case Qt::Key_AltGr: //or else we get unicode salad
case Qt::Key_Shift:
case Qt::Key_Control:
case Qt::Key_Meta:
break;
default:
- if (keyQt) {
- uint modifierKeys = e->modifiers();
-
- QString txt;
- if (modifierKeys & Qt::SHIFT)
- txt += "S-";
- if (modifierKeys & Qt::CTRL)
- txt += "C-";
- if (modifierKeys & Qt::ALT)
- txt += "M-";
-
- KeySymbol sym;
- setKeySymbol(&sym, e);
- txt += toqstr(sym.getSymbolName());
-
- if (text().isEmpty())
- setText(txt);
- else
- setText(text() + " " + txt);
- }
+ appendToSequence(e);
+ setText(toqstr(keysequence_.print(KeySequence::BindFile)));
}
}
-//prevent Qt from special casing Tab and Backtab
-bool ShortcutLineEdit::event(QEvent* e)
+bool ShortcutLineEdit::event(QEvent * e)
{
- if (e->type() == QEvent::ShortcutOverride)
- return false;
-
- if (e->type() == QEvent::KeyPress) {
- keyPressEvent(static_cast<QKeyEvent *>(e));
- return true;
+ switch (e->type()) {
+ case QEvent::FocusOut:
+ has_cursor_ = false;
+ break;
+ case QEvent::FocusIn:
+ has_cursor_ = true;
+ break;
+ case QEvent::ShortcutOverride:
+ keyPressEvent(static_cast<QKeyEvent *>(e));
+ return true;
+ case QEvent::KeyRelease:
+ case QEvent::Shortcut:
+ case QEvent::KeyPress:
+ return true;
+ default:
+ break;
}
-
return QLineEdit::event(e);
}
+void ShortcutLineEdit::appendToSequence(QKeyEvent * e)
+{
+ KeySymbol sym;
+ setKeySymbol(&sym, e);
+
+ KeyModifier mod = lyx::NoModifier;
+ if (e->modifiers() & Qt::SHIFT)
+ mod |= lyx::ShiftModifier;
+ if (e->modifiers() & Qt::CTRL)
+ mod |= lyx::ControlModifier;
+ if (e->modifiers() & Qt::ALT | e->modifiers() & Qt::META)
+ mod |= lyx::AltModifier;
+
+ keysequence_.addkey(sym, mod, lyx::NoModifier);
+}
+
+
QString const SearchLineEdit::hintMessage() const
{
return toqstr("Search ...");
#ifndef CUSTOMIZEDWIDGETS_H
#define CUSTOMIZEDWIDGETS_H
-#include <QEvent>
-#include <QCloseEvent>
#include <QLineEdit>
+#include "KeySequence.h"
+
+class QEvent;
+class QKeyEvent;
/**
* A lineedit for inputting shortcuts
class ShortcutLineEdit : public QLineEdit {
Q_OBJECT
public:
- ShortcutLineEdit(QWidget * parent) : QLineEdit(parent) {}
+ ShortcutLineEdit(QWidget * parent);
+ void reset();
+ bool eventFilter(QObject*, QEvent* e );
+ lyx::KeySequence const getKeySequence() const;
protected Q_SLOTS:
+ bool event(QEvent* e);
void keyPressEvent(QKeyEvent * e);
- bool event(QEvent * e);
+private:
+ void appendToSequence(QKeyEvent * e);
+ lyx::KeySequence keysequence_;
+ bool has_cursor_;
};
{
setupUi(this);
- shortcutsTW->setColumnCount(2);
+ shortcutsTW->setColumnCount(3);
shortcutsTW->headerItem()->setText(0, qt_("Function"));
shortcutsTW->headerItem()->setText(1, qt_("Shortcut"));
+ shortcutsTW->headerItem()->setText(2, qt_("Type"));
shortcutsTW->setSortingEnabled(true);
// Multi-selection can be annoying.
// shortcutsTW->setSelectionMode(QAbstractItemView::MultiSelection);
switch (tag) {
case System:
color = "black";
+ item->setText(2, "System shortcut");
break;
case UserBind:
color = "green";
+ item->setText(2, "User defined shortcut");
break;
case UserUnbind:
color = "red";
+ item->setText(2, "Removed system shortcut");
break;
case UserExtraUnbind:
color = "purple";
+ item->setText(2, "Unmatched removed system shortcut");
break;
}
+ for (int col = 0; col < shortcutsTW->columnCount(); ++col)
#if QT_VERSION >= 0x040200
- item->setForeground(0, QBrush(QColor(color)));
- item->setForeground(1, QBrush(QColor(color)));
+ item->setForeground(col, QBrush(QColor(color)));
#else
- item->setTextColor(0, QColor(color));
- item->setTextColor(1, QColor(color));
+ item->setTextColor(col, QColor(color));
#endif
}
string const action_name = lyxaction.getActionName(action);
QString const lfun_name = toqstr(from_utf8(action_name)
+ " " + lfun.argument());
- // use BindFile format instead of a more verbose form Portable
- // if the Shortcut dialog can hide all the bind file stuff,
- // Portable format can be used.
+ // use BindFile format instead of a more verbose form Portable. If the
+ // Shortcut dialog can hide all the bind file stuff, and on_removePB_pressed
+ // can parse Portable format, Portable format can be used.
QString const shortcut = toqstr(seq.print(KeySequence::BindFile));
item_type item_tag = tag;
QTreeWidgetItem * item = shortcutsTW->currentItem();
if (item->flags() & Qt::ItemIsSelectable) {
shortcut_->lfunLE->setText(item->text(0));
- shortcut_->shortcutLE->setText(item->text(1));
+ // clear the shortcut because I assume that a user will enter
+ // a new shortcut.
+ shortcut_->shortcutLE->reset();
+ shortcut_->shortcutLE->setFocus();
shortcut_->exec();
}
}
void PrefShortcuts::on_newPB_pressed()
{
shortcut_->lfunLE->clear();
- shortcut_->shortcutLE->clear();
+ shortcut_->shortcutLE->reset();
shortcut_->exec();
}
void PrefShortcuts::shortcut_okPB_pressed()
{
- string shortcut = fromqstr(shortcut_->shortcutLE->text());
string lfun = fromqstr(shortcut_->lfunLE->text());
FuncRequest func = lyxaction.lookupFunc(lfun);
- if (shortcut.empty() || func.action == LFUN_UNKNOWN_ACTION) {
+ if (func.action == LFUN_UNKNOWN_ACTION) {
Alert::error(_("Failed to create shortcut"),
_("Unknown or invalid LyX function"));
return;
}
- KeySequence k(0, 0);
- string::size_type const res = k.parse(shortcut);
- if (res != string::npos) {
+ KeySequence k = shortcut_->shortcutLE->getKeySequence();
+ if (k.length() == 0) {
Alert::error(_("Failed to create shortcut"),
- _("Invalid key sequence"));
+ _("Invalid or empty key sequence"));
return;
}
QTreeWidgetItem * item = insertShortcutItem(func, k, UserBind);
if (item) {
- user_bind_.bind(shortcut, func);
+ user_bind_.bind(&k, func);
shortcutsTW->sortItems(0, Qt::AscendingOrder);
shortcutsTW->setItemExpanded(item->parent(), true);
shortcutsTW->scrollToItem(item);
void PrefShortcuts::shortcut_clearPB_pressed()
{
- shortcut_->shortcutLE->clear();
+ shortcut_->shortcutLE->reset();
shortcut_->shortcutLE->setFocus();
}