Add multi key bindings to QShortcut
This makes it feature comparable with QAction, and makes it possible to use as a backend for QAction, and fixes a few missing alternative keybindings in qtwidgets. Change-Id: Iaefc630b96c4743fc5ef429dc841870ddd99fc64 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
parent
8fa93272f0
commit
b26fa9722f
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
@ -275,19 +310,77 @@ QShortcut::QShortcut(const QKeySequence &key, QObject *parent,
|
||||
will not be called.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\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)
|
||||
{
|
||||
Q_D(QShortcut);
|
||||
if (d->sc_sequence == key)
|
||||
return;
|
||||
QAPP_CHECK("setKey");
|
||||
d->sc_sequence = key;
|
||||
d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap);
|
||||
if (key.isEmpty())
|
||||
setKeys({});
|
||||
else
|
||||
setKeys({ key });
|
||||
}
|
||||
|
||||
QKeySequence QShortcut::key() const
|
||||
{
|
||||
Q_D(const QShortcut);
|
||||
return d->sc_sequence;
|
||||
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_sequences == keys)
|
||||
return;
|
||||
QAPP_CHECK("setKeys");
|
||||
d->sc_sequences = keys;
|
||||
d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap);
|
||||
}
|
||||
|
||||
/*!
|
||||
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_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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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"
|
||||
|
Loading…
x
Reference in New Issue
Block a user