summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/widgets/itemviews/storageview/main.cpp2
-rw-r--r--src/gui/kernel/qshortcut.cpp188
-rw-r--r--src/gui/kernel/qshortcut.h69
-rw-r--r--src/gui/kernel/qshortcut_p.h6
-rw-r--r--src/widgets/dialogs/qfiledialog.cpp6
-rw-r--r--src/widgets/dialogs/qprogressdialog.cpp1
-rw-r--r--tests/auto/widgets/kernel/qshortcut/tst_qshortcut.cpp20
7 files changed, 259 insertions, 33 deletions
diff --git a/examples/widgets/itemviews/storageview/main.cpp b/examples/widgets/itemviews/storageview/main.cpp
index fe916b039d..5505d8a984 100644
--- a/examples/widgets/itemviews/storageview/main.cpp
+++ b/examples/widgets/itemviews/storageview/main.cpp
@@ -66,7 +66,7 @@ int main(int argc, char *argv[])
StorageModel *model = new StorageModel(&view);
model->refresh();
- QShortcut *refreshShortcut = new QShortcut(Qt::CTRL | Qt::Key_R, &view);
+ QShortcut *refreshShortcut = new QShortcut(QKeySequence::Refresh, &view);
QObject::connect(refreshShortcut, &QShortcut::activated, model, &StorageModel::refresh);
view.setModel(model);
diff --git a/src/gui/kernel/qshortcut.cpp b/src/gui/kernel/qshortcut.cpp
index b927f2435e..524062ef30 100644
--- a/src/gui/kernel/qshortcut.cpp
+++ b/src/gui/kernel/qshortcut.cpp
@@ -163,15 +163,23 @@ void QShortcutPrivate::redoGrab(QShortcutMap &map)
return;
}
- if (sc_id)
- map.removeShortcut(sc_id, q);
- if (sc_sequence.isEmpty())
+ for (int id : qAsConst(sc_ids))
+ map.removeShortcut(id, q);
+
+ sc_ids.clear();
+ if (sc_sequences.isEmpty())
return;
- sc_id = map.addShortcut(q, sc_sequence, sc_context, contextMatcher());
- if (!sc_enabled)
- map.setShortcutEnabled(false, sc_id, q);
- if (!sc_autorepeat)
- map.setShortcutAutoRepeat(false, sc_id, q);
+ sc_ids.reserve(sc_sequences.count());
+ for (const auto &keySequence : qAsConst(sc_sequences)) {
+ if (keySequence.isEmpty())
+ continue;
+ int id = map.addShortcut(q, keySequence, sc_context, contextMatcher());
+ sc_ids.append(id);
+ if (!sc_enabled)
+ map.setShortcutEnabled(false, id, q);
+ if (!sc_autorepeat)
+ map.setShortcutAutoRepeat(false, id, q);
+ }
}
QShortcutPrivate *QGuiApplicationPrivate::createShortcutPrivate() const
@@ -210,7 +218,34 @@ QShortcut::QShortcut(const QKeySequence &key, QObject *parent,
{
Q_D(QShortcut);
d->sc_context = context;
- d->sc_sequence = key;
+ if (!key.isEmpty()) {
+ d->sc_sequences = { key };
+ d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap);
+ }
+ if (member)
+ connect(this, SIGNAL(activated()), parent, member);
+ if (ambiguousMember)
+ connect(this, SIGNAL(activatedAmbiguously()), parent, ambiguousMember);
+}
+
+/*!
+ \since 6.0
+ Constructs a QShortcut object for the \a parent, which should be a
+ QWindow or a QWidget.
+
+ The shortcut operates on its parent, listening for \l{QShortcutEvent}s that
+ match the \a standardKey. Depending on the ambiguity of the event, the
+ shortcut will call the \a member function, or the \a ambiguousMember function,
+ if the key press was in the shortcut's \a context.
+*/
+QShortcut::QShortcut(QKeySequence::StandardKey standardKey, QObject *parent,
+ const char *member, const char *ambiguousMember,
+ Qt::ShortcutContext context)
+ : QShortcut(parent)
+{
+ Q_D(QShortcut);
+ d->sc_context = context;
+ d->sc_sequences = QKeySequence::keyBindings(standardKey);
d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap);
if (member)
connect(this, SIGNAL(activated()), parent, member);
@@ -276,18 +311,76 @@ QShortcut::QShortcut(const QKeySequence &key, QObject *parent,
*/
/*!
+ \fn template<typename Functor> QShortcut::QShortcut(QKeySequence::StandardKey key, QObject *parent, Functor functor, Qt::ShortcutContext shortcutContext = Qt::WindowShortcut)
+ \since 6.0
+ \overload
+
+ This is a QShortcut convenience constructor which connects the shortcut's
+ \l{QShortcut::activated()}{activated()} signal to the \a functor.
+*/
+/*!
+ \fn template<typename Functor> QShortcut::QShortcut(QKeySequence::StandardKey key, QObject *parent, const QObject *context, Functor functor, Qt::ShortcutContext shortcutContext = Qt::WindowShortcut)
+ \since 6.0
+ \overload
+
+ This is a QShortcut convenience constructor which connects the shortcut's
+ \l{QShortcut::activated()}{activated()} signal to the \a functor.
+
+ The \a functor can be a pointer to a member function of the \a context object.
+
+ If the \a context object is destroyed, the \a functor will not be called.
+*/
+/*!
+ \fn template<typename Functor, typename FunctorAmbiguous> QShortcut::QShortcut(QKeySequence::StandardKey key, QObject *parent, const QObject *context, Functor functor, FunctorAmbiguous functorAmbiguous, Qt::ShortcutContext shortcutContext = Qt::WindowShortcut)
+ \since 6.0
+ \overload
+
+ This is a QShortcut convenience constructor which connects the shortcut's
+ \l{QShortcut::activated()}{activated()} signal to the \a functor and
+ \l{QShortcut::activatedAmbiguously()}{activatedAmbiguously()}
+ signal to the \a functorAmbiguous.
+
+ The \a functor and \a functorAmbiguous can be a pointer to a member
+ function of the \a context object.
+
+ If the \a context object is destroyed, the \a functor and
+ \a functorAmbiguous will not be called.
+*/
+/*!
+ \fn template<typename Functor, typename FunctorAmbiguous> QShortcut::QShortcut(QKeySequence::StandardKey key, QObject *parent, const QObject *context1, Functor functor, const QObject *context2, FunctorAmbiguous functorAmbiguous, Qt::ShortcutContext shortcutContext = Qt::WindowShortcut)
+ \since 6.0
+ \overload
+
+ This is a QShortcut convenience constructor which connects the shortcut's
+ \l{QShortcut::activated()}{activated()} signal to the \a functor and
+ \l{QShortcut::activatedAmbiguously()}{activatedAmbiguously()}
+ signal to the \a functorAmbiguous.
+
+ The \a functor can be a pointer to a member function of the
+ \a context1 object.
+ The \a functorAmbiguous can be a pointer to a member function of the
+ \a context2 object.
+
+ If the \a context1 object is destroyed, the \a functor will not be called.
+ If the \a context2 object is destroyed, the \a functorAmbiguous
+ will not be called.
+*/
+
+/*!
Destroys the shortcut.
*/
QShortcut::~QShortcut()
{
Q_D(QShortcut);
- if (qApp)
- QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(d->sc_id, this);
+ if (qApp) {
+ for (int id : qAsConst(d->sc_ids))
+ QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(id, this);
+ }
}
/*!
\property QShortcut::key
- \brief the shortcut's key sequence
+ \brief the shortcut's primary key sequence
This is a key sequence with an optional combination of Shift, Ctrl,
and Alt. The key sequence may be supplied in a number of ways:
@@ -298,18 +391,61 @@ QShortcut::~QShortcut()
*/
void QShortcut::setKey(const QKeySequence &key)
{
+ if (key.isEmpty())
+ setKeys({});
+ else
+ setKeys({ key });
+}
+
+QKeySequence QShortcut::key() const
+{
+ Q_D(const QShortcut);
+ if (d->sc_sequences.isEmpty())
+ return QKeySequence();
+ return d->sc_sequences.first();
+}
+
+/*!
+ Sets \a keys as the list of key sequences that trigger the
+ shortcut.
+
+ \since 6.0
+
+ \sa key, keys()
+*/
+void QShortcut::setKeys(const QList<QKeySequence> &keys)
+{
Q_D(QShortcut);
- if (d->sc_sequence == key)
+ if (d->sc_sequences == keys)
return;
- QAPP_CHECK("setKey");
- d->sc_sequence = key;
+ QAPP_CHECK("setKeys");
+ d->sc_sequences = keys;
d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap);
}
-QKeySequence QShortcut::key() const
+/*!
+ Sets the triggers to those matching the standard key \a key.
+
+ \since 6.0
+
+ \sa key, keys()
+*/
+void QShortcut::setKeys(QKeySequence::StandardKey key)
+{
+ setKeys(QKeySequence::keyBindings(key));
+}
+
+/*!
+ Returns the list of key sequences which trigger this
+ shortcut.
+
+ \since 6.0
+ \sa key, setKeys()
+*/
+QList<QKeySequence> QShortcut::keys() const
{
Q_D(const QShortcut);
- return d->sc_sequence;
+ return d->sc_sequences;
}
/*!
@@ -334,7 +470,8 @@ void QShortcut::setEnabled(bool enable)
return;
QAPP_CHECK("setEnabled");
d->sc_enabled = enable;
- QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(enable, d->sc_id, this);
+ for (int id : d->sc_ids)
+ QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(enable, id, this);
}
bool QShortcut::isEnabled() const
@@ -387,7 +524,8 @@ void QShortcut::setAutoRepeat(bool on)
return;
QAPP_CHECK("setAutoRepeat");
d->sc_autorepeat = on;
- QGuiApplicationPrivate::instance()->shortcutMap.setShortcutAutoRepeat(on, d->sc_id, this);
+ for (int id : d->sc_ids)
+ QGuiApplicationPrivate::instance()->shortcutMap.setShortcutAutoRepeat(on, id, this);
}
bool QShortcut::autoRepeat() const
@@ -430,16 +568,20 @@ QString QShortcut::whatsThis() const
return d->sc_whatsthis;
}
+#if QT_DEPRECATED_SINCE(6,0)
/*!
- Returns the shortcut's ID.
+ Returns the primary key binding's ID.
\sa QShortcutEvent::shortcutId()
*/
int QShortcut::id() const
{
Q_D(const QShortcut);
- return d->sc_id;
+ if (d->sc_ids.isEmpty())
+ return 0;
+ return d->sc_ids.first();
}
+#endif
/*!
\fn QWidget *QShortcut::parentWidget() const
@@ -455,8 +597,8 @@ bool QShortcut::event(QEvent *e)
Q_D(QShortcut);
if (d->sc_enabled && e->type() == QEvent::Shortcut) {
auto se = static_cast<QShortcutEvent *>(e);
- if (se->shortcutId() == d->sc_id && se->key() == d->sc_sequence
- && !d->handleWhatsThis()) {
+ if (!d->handleWhatsThis()) {
+ Q_ASSERT_X(d->sc_ids.contains(se->shortcutId()), "QShortcut::event", "Received shortcut event from wrong shortcut");
if (se->isAmbiguous())
emit activatedAmbiguously();
else
diff --git a/src/gui/kernel/qshortcut.h b/src/gui/kernel/qshortcut.h
index 1b90a21925..d3db30fd4d 100644
--- a/src/gui/kernel/qshortcut.h
+++ b/src/gui/kernel/qshortcut.h
@@ -64,6 +64,9 @@ public:
explicit QShortcut(const QKeySequence& key, QObject *parent,
const char *member = nullptr, const char *ambiguousMember = nullptr,
Qt::ShortcutContext context = Qt::WindowShortcut);
+ explicit QShortcut(QKeySequence::StandardKey key, QObject *parent,
+ const char *member = nullptr, const char *ambiguousMember = nullptr,
+ Qt::ShortcutContext context = Qt::WindowShortcut);
#ifdef Q_CLANG_QDOC
template<typename Functor>
@@ -84,6 +87,25 @@ public:
const QObject *context1, Functor functor,
const QObject *context2, FunctorAmbiguous functorAmbiguous,
Qt::ShortcutContext shortcutContext = Qt::WindowShortcut);
+
+ template<typename Functor>
+ QShortcut(QKeySequence::StandardKey key, QObject *parent,
+ Functor functor,
+ Qt::ShortcutContext shortcutContext = Qt::WindowShortcut);
+ template<typename Functor>
+ QShortcut(QKeySequence::StandardKey key, QObject *parent,
+ const QObject *context, Functor functor,
+ Qt::ShortcutContext shortcutContext = Qt::WindowShortcut);
+ template<typename Functor, typename FunctorAmbiguous>
+ QShortcut(QKeySequence::StandardKey key, QObject *parent,
+ const QObject *context1, Functor functor,
+ FunctorAmbiguous functorAmbiguous,
+ Qt::ShortcutContext shortcutContext = Qt::WindowShortcut);
+ template<typename Functor, typename FunctorAmbiguous>
+ QShortcut(QKeySequence::StandardKey key, QObject *parent,
+ const QObject *context1, Functor functor,
+ const QObject *context2, FunctorAmbiguous functorAmbiguous,
+ Qt::ShortcutContext shortcutContext = Qt::WindowShortcut);
#else
template<typename Func1>
QShortcut(const QKeySequence &key, QObject *parent,
@@ -124,12 +146,55 @@ public:
connect(this, &QShortcut::activated, object1, std::move(slot1));
connect(this, &QShortcut::activatedAmbiguously, object2, std::move(slot2));
}
+
+ template<typename Func1>
+ QShortcut(QKeySequence::StandardKey key, QObject *parent,
+ Func1 slot1,
+ Qt::ShortcutContext context = Qt::WindowShortcut)
+ : QShortcut(key, parent, static_cast<const char*>(nullptr), static_cast<const char*>(nullptr), context)
+ {
+ connect(this, &QShortcut::activated, std::move(slot1));
+ }
+ template<class Obj1, typename Func1>
+ QShortcut(QKeySequence::StandardKey key, QObject *parent,
+ const Obj1 *object1, Func1 slot1,
+ Qt::ShortcutContext context = Qt::WindowShortcut,
+ typename std::enable_if<QtPrivate::IsPointerToTypeDerivedFromQObject<Obj1*>::Value>::type* = 0)
+ : QShortcut(key, parent, static_cast<const char*>(nullptr), static_cast<const char*>(nullptr), context)
+ {
+ connect(this, &QShortcut::activated, object1, std::move(slot1));
+ }
+ template<class Obj1, typename Func1, typename Func2>
+ QShortcut(QKeySequence::StandardKey key, QObject *parent,
+ const Obj1 *object1, Func1 slot1, Func2 slot2,
+ Qt::ShortcutContext context = Qt::WindowShortcut,
+ typename std::enable_if<QtPrivate::IsPointerToTypeDerivedFromQObject<Obj1*>::Value>::type* = 0)
+ : QShortcut(key, parent, static_cast<const char*>(nullptr), static_cast<const char*>(nullptr), context)
+ {
+ connect(this, &QShortcut::activated, object1, std::move(slot1));
+ connect(this, &QShortcut::activatedAmbiguously, object1, std::move(slot2));
+ }
+ template<class Obj1, typename Func1, class Obj2, typename Func2>
+ QShortcut(QKeySequence::StandardKey key, QObject *parent,
+ const Obj1 *object1, Func1 slot1,
+ const Obj2 *object2, Func2 slot2,
+ Qt::ShortcutContext context = Qt::WindowShortcut,
+ typename std::enable_if<QtPrivate::IsPointerToTypeDerivedFromQObject<Obj1*>::Value>::type* = 0,
+ typename std::enable_if<QtPrivate::IsPointerToTypeDerivedFromQObject<Obj2*>::Value>::type* = 0)
+ : QShortcut(key, parent, static_cast<const char*>(nullptr), static_cast<const char*>(nullptr), context)
+ {
+ connect(this, &QShortcut::activated, object1, std::move(slot1));
+ connect(this, &QShortcut::activatedAmbiguously, object2, std::move(slot2));
+ }
#endif
~QShortcut();
void setKey(const QKeySequence& key);
QKeySequence key() const;
+ void setKeys(QKeySequence::StandardKey key);
+ void setKeys(const QList<QKeySequence> &keys);
+ QList<QKeySequence> keys() const;
void setEnabled(bool enable);
bool isEnabled() const;
@@ -140,7 +205,9 @@ public:
void setAutoRepeat(bool on);
bool autoRepeat() const;
- int id() const;
+#if QT_DEPRECATED_SINCE(6,0)
+ Q_DECL_DEPRECATED int id() const;
+#endif
void setWhatsThis(const QString &text);
QString whatsThis() const;
diff --git a/src/gui/kernel/qshortcut_p.h b/src/gui/kernel/qshortcut_p.h
index 254745960f..f62bab0297 100644
--- a/src/gui/kernel/qshortcut_p.h
+++ b/src/gui/kernel/qshortcut_p.h
@@ -55,13 +55,13 @@
#include "qshortcut.h"
#include <QtGui/qkeysequence.h>
+#include <QtCore/qlist.h>
#include <QtCore/qstring.h>
#include <QtCore/private/qobject_p.h>
#include <private/qshortcutmap_p.h>
-
QT_BEGIN_NAMESPACE
class QShortcutMap;
@@ -79,12 +79,12 @@ public:
virtual QShortcutMap::ContextMatcher contextMatcher() const;
virtual bool handleWhatsThis() { return false; }
- QKeySequence sc_sequence;
+ QList<QKeySequence> sc_sequences;
QString sc_whatsthis;
Qt::ShortcutContext sc_context = Qt::WindowShortcut;
bool sc_enabled = true;
bool sc_autorepeat = true;
- int sc_id = 0;
+ QList<int> sc_ids;
void redoGrab(QShortcutMap &map);
};
diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp
index adbf655750..ff884d925e 100644
--- a/src/widgets/dialogs/qfiledialog.cpp
+++ b/src/widgets/dialogs/qfiledialog.cpp
@@ -3048,8 +3048,7 @@ void QFileDialogPrivate::createWidgets()
QObject::connect(qFileDialogUi->listView, SIGNAL(customContextMenuRequested(QPoint)),
q, SLOT(_q_showContextMenu(QPoint)));
#ifndef QT_NO_SHORTCUT
- QShortcut *shortcut = new QShortcut(qFileDialogUi->listView);
- shortcut->setKey(QKeySequence(QLatin1String("Delete")));
+ QShortcut *shortcut = new QShortcut(QKeySequence::Delete, qFileDialogUi->listView);
QObject::connect(shortcut, SIGNAL(activated()), q, SLOT(_q_deleteCurrent()));
#endif
@@ -3088,8 +3087,7 @@ void QFileDialogPrivate::createWidgets()
QObject::connect(qFileDialogUi->treeView, SIGNAL(customContextMenuRequested(QPoint)),
q, SLOT(_q_showContextMenu(QPoint)));
#ifndef QT_NO_SHORTCUT
- shortcut = new QShortcut(qFileDialogUi->treeView);
- shortcut->setKey(QKeySequence(QLatin1String("Delete")));
+ shortcut = new QShortcut(QKeySequence::Delete, qFileDialogUi->treeView);
QObject::connect(shortcut, SIGNAL(activated()), q, SLOT(_q_deleteCurrent()));
#endif
diff --git a/src/widgets/dialogs/qprogressdialog.cpp b/src/widgets/dialogs/qprogressdialog.cpp
index 645ca1013a..32834291b8 100644
--- a/src/widgets/dialogs/qprogressdialog.cpp
+++ b/src/widgets/dialogs/qprogressdialog.cpp
@@ -403,7 +403,6 @@ void QProgressDialog::setCancelButton(QPushButton *cancelButton)
if (cancelButton) {
connect(d->cancel, SIGNAL(clicked()), this, SIGNAL(canceled()));
#ifndef QT_NO_SHORTCUT
- // FIXME: This only registers the primary key sequence of the cancel action
d->escapeShortcut = new QShortcut(QKeySequence::Cancel, this, SIGNAL(canceled()));
#endif
} else {
diff --git a/tests/auto/widgets/kernel/qshortcut/tst_qshortcut.cpp b/tests/auto/widgets/kernel/qshortcut/tst_qshortcut.cpp
index 64e054f7f4..3abec08f09 100644
--- a/tests/auto/widgets/kernel/qshortcut/tst_qshortcut.cpp
+++ b/tests/auto/widgets/kernel/qshortcut/tst_qshortcut.cpp
@@ -117,6 +117,7 @@ private slots:
void duplicatedShortcutOverride();
void shortcutToFocusProxy();
void deleteLater();
+ void keys();
protected:
static Qt::KeyboardModifiers toButtons( int key );
@@ -1344,6 +1345,25 @@ void tst_QShortcut::deleteLater()
QTRY_VERIFY(!sc);
}
+void tst_QShortcut::keys()
+{
+ QLineEdit le;
+ QShortcut *sc = new QShortcut(QKeySequence::InsertParagraphSeparator, &le);
+ QVERIFY(sc->keys().contains(QKeySequence(Qt::Key_Enter)));
+ QVERIFY(sc->keys().contains(QKeySequence(Qt::Key_Return)));
+
+ QSignalSpy spy(sc, &QShortcut::activated);
+ le.setFocus();
+ le.show();
+ QVERIFY(QTest::qWaitForWindowActive(&le));
+ QCOMPARE(QApplication::focusWidget(), &le);
+
+ QTest::keyEvent(QTest::Press, QApplication::focusWidget(), Qt::Key_Enter);
+ QTRY_COMPARE(spy.count(), 1);
+
+ QTest::keyEvent(QTest::Press, QApplication::focusWidget(), Qt::Key_Return);
+ QTRY_COMPARE(spy.count(), 2);
+}
QTEST_MAIN(tst_QShortcut)
#include "tst_qshortcut.moc"