QShortcut: add pmf ctor overloads

Provide pointer to member function overloads for the QShortcut ctor. The
ctor with two functors but no contexts is not provided since it creates
ambiguousness.

[ChangeLog][QtWidgets][QShortcut] QShortcut ctor has now pmf overloads

Fixes: QTBUG-77816
Change-Id: Ic9a759cde5150dbb94c2fd351b88ee8e447e0852
Reviewed-by: Paul Wicking <paul.wicking@qt.io>
Reviewed-by: Samuel Gaist <samuel.gaist@idiap.ch>
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
This commit is contained in:
Christian Ehrlicher 2019-09-25 19:54:49 +02:00
parent 41702d8455
commit a4751f8824
3 changed files with 170 additions and 4 deletions

View File

@ -419,6 +419,76 @@ static bool correctActionContext(Qt::ShortcutContext context, QAction *a, QWidge
\sa activated()
*/
/*!
\fn template<typename Functor>
QShortcut(const QKeySequence &key, QWidget *parent,
Functor functor,
Qt::ShortcutContext shortcutContext = Qt::WindowShortcut);
\since 5.15
\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(const QKeySequence &key, QWidget *parent,
const QObject *context, Functor functor,
Qt::ShortcutContext shortcutContext = Qt::WindowShortcut);
\since 5.15
\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(const QKeySequence &key, QWidget *parent,
const QObject *context1, Functor functor,
FunctorAmbiguous functorAmbiguous,
Qt::ShortcutContext shortcutContext = Qt::WindowShortcut);
\since 5.15
\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(const QKeySequence &key, QWidget *parent,
const QObject *context1, Functor functor,
const QObject *context2, FunctorAmbiguous functorAmbiguous,
Qt::ShortcutContext shortcutContext = Qt::WindowShortcut);
\since 5.15
\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.
*/
/*
\internal
Private data accessed through d-pointer.
@ -479,13 +549,13 @@ QShortcut::QShortcut(QWidget *parent)
*/
QShortcut::QShortcut(const QKeySequence &key, QWidget *parent,
const char *member, const char *ambiguousMember,
Qt::ShortcutContext context)
Qt::ShortcutContext shortcutContext)
: QShortcut(parent)
{
QAPP_CHECK("QShortcut");
Q_D(QShortcut);
d->sc_context = context;
d->sc_context = shortcutContext;
d->sc_sequence = key;
d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap);
if (member)

View File

@ -61,9 +61,65 @@ class Q_WIDGETS_EXPORT QShortcut : public QObject
Q_PROPERTY(Qt::ShortcutContext context READ context WRITE setContext)
public:
explicit QShortcut(QWidget *parent);
QShortcut(const QKeySequence& key, QWidget *parent,
QShortcut(const QKeySequence &key, QWidget *parent,
const char *member = nullptr, const char *ambiguousMember = nullptr,
Qt::ShortcutContext context = Qt::WindowShortcut);
Qt::ShortcutContext shortcutContext = Qt::WindowShortcut);
#ifdef Q_CLANG_QDOC
template<typename Functor>
QShortcut(const QKeySequence &key, QWidget *parent,
Functor functor,
Qt::ShortcutContext shortcutContext = Qt::WindowShortcut);
template<typename Functor>
QShortcut(const QKeySequence &key, QWidget *parent,
const QObject *context, Functor functor,
Qt::ShortcutContext shortcutContext = Qt::WindowShortcut);
template<typename Functor, typename FunctorAmbiguous>
QShortcut(const QKeySequence &key, QWidget *parent,
const QObject *context1, Functor functor,
FunctorAmbiguous functorAmbiguous,
Qt::ShortcutContext shortcutContext = Qt::WindowShortcut);
template<typename Functor, typename FunctorAmbiguous>
QShortcut(const QKeySequence &key, QWidget *parent,
const QObject *context1, Functor functor,
const QObject *context2, FunctorAmbiguous functorAmbiguous,
Qt::ShortcutContext shortcutContext = Qt::WindowShortcut);
#else
template<typename Func1>
QShortcut(const QKeySequence &key, QWidget *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(const QKeySequence &key, QWidget *parent,
const Obj1 *object1, 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, object1, std::move(slot1));
}
template<class Obj1, typename Func1, typename Func2>
QShortcut(const QKeySequence &key, QWidget *parent,
const Obj1 *object1, Func1 slot1, Func2 slot2,
Qt::ShortcutContext context = Qt::WindowShortcut)
: 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(const QKeySequence &key, QWidget *parent,
const Obj1 *object1, Func1 slot1,
const Obj2 *object2, Func2 slot2,
Qt::ShortcutContext context = Qt::WindowShortcut)
: 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);

View File

@ -103,6 +103,7 @@ public slots:
private slots:
void cleanup();
void pmf_connect();
void number_data();
void number();
void text_data();
@ -203,6 +204,45 @@ void tst_QShortcut::cleanup()
QVERIFY(QApplication::topLevelWidgets().size() <= 1); // The data driven tests keep a widget around
}
void tst_QShortcut::pmf_connect()
{
class MyObject : public QObject
{
public:
using QObject::QObject;
void onActivated() { ++activated; }
void onAmbiguous() { ++ambiguous; }
void reset() { activated = 0; ambiguous = 0; }
int activated = 0;
int ambiguous = 0;
} myObject;
QWidget parent;
auto runCheck = [&myObject](QShortcut *sc, int activated, int ambiguous)
{
myObject.reset();
sc->activated();
sc->activatedAmbiguously();
delete sc;
QCOMPARE(myObject.activated, activated);
QCOMPARE(myObject.ambiguous, ambiguous);
};
runCheck(new QShortcut(QKeySequence(), &parent,
[&myObject]() { ++myObject.activated; }),
1, 0);
runCheck(new QShortcut(QKeySequence(), &parent,
&myObject, &MyObject::onActivated),
1, 0);
runCheck(new QShortcut(QKeySequence(), &parent,
&myObject, &MyObject::onActivated, &MyObject::onAmbiguous),
1, 1);
runCheck(new QShortcut(QKeySequence(), &parent, &myObject,
&MyObject::onActivated, &myObject, &MyObject::onAmbiguous),
1, 1);
}
Qt::KeyboardModifiers tst_QShortcut::toButtons( int key )
{
Qt::KeyboardModifiers result = Qt::NoModifier;