]> git.lyx.org Git - features.git/commitdiff
PrefShortcuts: improve the Shortcut input dialog
authorBo Peng <bpeng@lyx.org>
Fri, 26 Oct 2007 20:43:22 +0000 (20:43 +0000)
committerBo Peng <bpeng@lyx.org>
Fri, 26 Oct 2007 20:43:22 +0000 (20:43 +0000)
* src/KeyMap.h|cpp: change interface and allow bind(KeySequence, FuncRequest)
* src/frontends/qt4/CustomizedWidgets.h|cpp: use KeySequence, add event filter from Edwin
* src/frontends/qt4/GuiPrefs.cpp: add another column, get KeySequence from the shortcut edit dialog directly

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@21220 a592a061-630c-0410-9148-cb99ea01b6c8

src/KeyMap.cpp
src/KeyMap.h
src/frontends/qt4/CustomizedWidgets.cpp
src/frontends/qt4/CustomizedWidgets.h
src/frontends/qt4/GuiPrefs.cpp

index b32bda3e4b7df8c1869d7bc72edcd9e3be83dda9..3fbd46ede4c5c82f8657591df2c7920e9cde1a99 100644 (file)
@@ -67,7 +67,7 @@ size_t KeyMap::bind(string const & seq, FuncRequest const & func)
 
        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 << "'."
@@ -84,7 +84,7 @@ size_t KeyMap::unbind(string const & seq, FuncRequest const & func)
 
        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 << "'."
@@ -336,7 +336,7 @@ docstring const KeyMap::print(bool forgui) const
 }
 
 
-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())
@@ -371,7 +371,7 @@ void KeyMap::defkey(KeySequence * seq, FuncRequest const & func, unsigned int r)
                                               << endl;
                                return;
                        } else {
-                               it->table->defkey(seq, func, r + 1);
+                               it->table->bind(seq, func, r + 1);
                                return;
                        }
                }
@@ -386,12 +386,12 @@ void KeyMap::defkey(KeySequence * seq, FuncRequest const & func, unsigned int r)
                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())
@@ -415,7 +415,7 @@ void KeyMap::delkey(KeySequence * seq, FuncRequest const & func, unsigned int r)
                                                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;
index 06caf1a37ee8e68560cb3903af5deee6f278434e..05709e69056df24072db38c5e8d84d3af9b837af 100644 (file)
@@ -36,16 +36,24 @@ class KeySequence;
 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);
@@ -141,15 +149,6 @@ private:
                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
index 0154472fb261948d41779fa856e81e37359cff9b..ed9dfee8fd3870bf16dbeeb9f068e4b519cb2227 100644 (file)
 #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:
@@ -41,45 +88,52 @@ void ShortcutLineEdit::keyPressEvent(QKeyEvent * e)
                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 ...");
index cb01094446c21f43ab671a3f24857a08cc7d22e2..495f56a3d1eefa61a35a4280bf731f9f1df3ecdf 100644 (file)
 #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_;
 };
 
 
index 99a4d4fa138b85421899d5ce5c36d00e15ae7b2f..6255e849d106dad125ba0c5c9db11b1617eefac3 100644 (file)
@@ -1711,9 +1711,10 @@ PrefShortcuts::PrefShortcuts(GuiPreferences * form, QWidget * parent)
 {
        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);
@@ -1841,24 +1842,27 @@ void PrefShortcuts::setItemType(QTreeWidgetItem * item, item_type tag)
        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
 }
 
@@ -1870,9 +1874,9 @@ QTreeWidgetItem * PrefShortcuts::insertShortcutItem(FuncRequest const & lfun,
        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;
 
@@ -1942,7 +1946,10 @@ void PrefShortcuts::on_shortcutsTW_itemDoubleClicked()
        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();
        }
 }
@@ -1965,7 +1972,7 @@ void PrefShortcuts::select_bind()
 void PrefShortcuts::on_newPB_pressed()
 {
        shortcut_->lfunLE->clear();
-       shortcut_->shortcutLE->clear();
+       shortcut_->shortcutLE->reset();
        shortcut_->exec();
 }
 
@@ -2046,21 +2053,19 @@ void PrefShortcuts::on_searchLE_textChanged()
 
 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;
        }
 
@@ -2073,7 +2078,7 @@ void PrefShortcuts::shortcut_okPB_pressed()
                
        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);
@@ -2087,7 +2092,7 @@ void PrefShortcuts::shortcut_okPB_pressed()
 
 void PrefShortcuts::shortcut_clearPB_pressed()
 {
-       shortcut_->shortcutLE->clear();
+       shortcut_->shortcutLE->reset();
        shortcut_->shortcutLE->setFocus();
 }