Port Closure to variadic templates.
This commit is contained in:
parent
d6b84558f6
commit
8171192df5
@ -19,80 +19,47 @@
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
#include "core/logging.h"
|
||||
#include "core/timeconstants.h"
|
||||
|
||||
namespace _detail {
|
||||
|
||||
Closure::Closure(QObject* sender,
|
||||
const char* signal,
|
||||
QObject* receiver,
|
||||
const char* slot,
|
||||
const ClosureArgumentWrapper* val0,
|
||||
const ClosureArgumentWrapper* val1,
|
||||
const ClosureArgumentWrapper* val2,
|
||||
const ClosureArgumentWrapper* val3)
|
||||
: QObject(receiver),
|
||||
callback_(NULL),
|
||||
val0_(val0),
|
||||
val1_(val1),
|
||||
val2_(val2),
|
||||
val3_(val3) {
|
||||
const QMetaObject* meta_receiver = receiver->metaObject();
|
||||
|
||||
QByteArray normalised_slot = QMetaObject::normalizedSignature(slot + 1);
|
||||
const int index = meta_receiver->indexOfSlot(normalised_slot.constData());
|
||||
Q_ASSERT(index != -1);
|
||||
slot_ = meta_receiver->method(index);
|
||||
|
||||
Connect(sender, signal);
|
||||
ClosureBase::ClosureBase(ObjectHelper* helper)
|
||||
: helper_(helper) {
|
||||
}
|
||||
|
||||
Closure::Closure(QObject* sender,
|
||||
const char* signal,
|
||||
std::tr1::function<void()> callback)
|
||||
: callback_(callback) {
|
||||
Connect(sender, signal);
|
||||
ClosureBase::~ClosureBase() {
|
||||
}
|
||||
|
||||
Closure::~Closure() {
|
||||
ObjectHelper* ClosureBase::helper() const {
|
||||
return helper_;
|
||||
}
|
||||
|
||||
void Closure::Connect(QObject* sender, const char* signal) {
|
||||
bool success = connect(sender, signal, SLOT(Invoked()));
|
||||
Q_ASSERT(success);
|
||||
success = connect(sender, SIGNAL(destroyed()), SLOT(Cleanup()));
|
||||
Q_ASSERT(success);
|
||||
Q_UNUSED(success);
|
||||
ObjectHelper::ObjectHelper(
|
||||
QObject* sender,
|
||||
const char* signal,
|
||||
ClosureBase* closure)
|
||||
: closure_(closure) {
|
||||
connect(sender, signal, SLOT(Invoked()));
|
||||
connect(sender, SIGNAL(destroyed()), SLOT(deleteLater()));
|
||||
}
|
||||
|
||||
void Closure::Invoked() {
|
||||
if (callback_) {
|
||||
callback_();
|
||||
} else {
|
||||
slot_.invoke(
|
||||
parent(),
|
||||
val0_ ? val0_->arg() : QGenericArgument(),
|
||||
val1_ ? val1_->arg() : QGenericArgument(),
|
||||
val2_ ? val2_->arg() : QGenericArgument(),
|
||||
val3_ ? val3_->arg() : QGenericArgument());
|
||||
}
|
||||
void ObjectHelper::Invoked() {
|
||||
closure_->Invoke();
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
void Closure::Cleanup() {
|
||||
disconnect();
|
||||
deleteLater();
|
||||
}
|
||||
template<>
|
||||
void Arg<boost::tuples::tuple<>>(
|
||||
const boost::tuples::tuple<>&,
|
||||
QList<QGenericArgument>* list) {}
|
||||
|
||||
template<>
|
||||
void Arg<boost::tuples::null_type>(
|
||||
const boost::tuples::null_type&,
|
||||
QList<QGenericArgument>* list) {}
|
||||
|
||||
} // namespace _detail
|
||||
|
||||
_detail::Closure* NewClosure(
|
||||
QObject* sender, const char* signal,
|
||||
QObject* receiver, const char* slot) {
|
||||
return new _detail::Closure(sender, signal, receiver, slot);
|
||||
}
|
||||
|
||||
void DoAfter(QObject* receiver, const char* slot, int msec) {
|
||||
QTimer::singleShot(msec, receiver, slot);
|
||||
}
|
||||
|
@ -18,211 +18,169 @@
|
||||
#ifndef CLOSURE_H
|
||||
#define CLOSURE_H
|
||||
|
||||
#include <tr1/functional>
|
||||
|
||||
#include <QMetaMethod>
|
||||
#include <QObject>
|
||||
#include <QSharedPointer>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
#include "core/logging.h"
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
|
||||
namespace _detail {
|
||||
|
||||
class ClosureArgumentWrapper {
|
||||
public:
|
||||
virtual ~ClosureArgumentWrapper() {}
|
||||
class ObjectHelper;
|
||||
|
||||
virtual QGenericArgument arg() const = 0;
|
||||
// Interface for ObjectHelper to call on signal emission.
|
||||
class ClosureBase : boost::noncopyable {
|
||||
public:
|
||||
virtual ~ClosureBase();
|
||||
virtual void Invoke() = 0;
|
||||
|
||||
// Tests only.
|
||||
ObjectHelper* helper() const;
|
||||
|
||||
protected:
|
||||
explicit ClosureBase(ObjectHelper*);
|
||||
ObjectHelper* helper_;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class ClosureArgument : public ClosureArgumentWrapper {
|
||||
public:
|
||||
explicit ClosureArgument(const T& data) : data_(data) {}
|
||||
|
||||
virtual QGenericArgument arg() const {
|
||||
return Q_ARG(T, data_);
|
||||
}
|
||||
|
||||
private:
|
||||
T data_;
|
||||
};
|
||||
|
||||
class Closure : public QObject, boost::noncopyable {
|
||||
// QObject helper as templated QObjects do not work.
|
||||
// Connects to the given signal and invokes the closure when called.
|
||||
// Deletes itself and the Closure after being invoked.
|
||||
class ObjectHelper : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Closure(QObject* sender, const char* signal,
|
||||
QObject* receiver, const char* slot,
|
||||
const ClosureArgumentWrapper* val0 = 0,
|
||||
const ClosureArgumentWrapper* val1 = 0,
|
||||
const ClosureArgumentWrapper* val2 = 0,
|
||||
const ClosureArgumentWrapper* val3 = 0);
|
||||
|
||||
Closure(QObject* sender, const char* signal,
|
||||
std::tr1::function<void()> callback);
|
||||
|
||||
virtual ~Closure();
|
||||
ObjectHelper(
|
||||
QObject* parent,
|
||||
const char* signal,
|
||||
ClosureBase* closure);
|
||||
|
||||
private slots:
|
||||
void Invoked();
|
||||
void Cleanup();
|
||||
|
||||
private:
|
||||
void Connect(QObject* sender, const char* signal);
|
||||
|
||||
QMetaMethod slot_;
|
||||
std::tr1::function<void()> callback_;
|
||||
|
||||
boost::scoped_ptr<const ClosureArgumentWrapper> val0_;
|
||||
boost::scoped_ptr<const ClosureArgumentWrapper> val1_;
|
||||
boost::scoped_ptr<const ClosureArgumentWrapper> val2_;
|
||||
boost::scoped_ptr<const ClosureArgumentWrapper> val3_;
|
||||
};
|
||||
|
||||
class SharedPointerWrapper {
|
||||
public:
|
||||
virtual ~SharedPointerWrapper() {}
|
||||
virtual QObject* data() const = 0;
|
||||
boost::scoped_ptr<ClosureBase> closure_;
|
||||
Q_DISABLE_COPY(ObjectHelper);
|
||||
};
|
||||
|
||||
// Helper to unpack a tuple into a QList.
|
||||
template<typename T>
|
||||
class SharedPointer : public SharedPointerWrapper {
|
||||
void Arg(const T& tail, QList<QGenericArgument>* list) {
|
||||
typedef decltype(tail.get_head()) HeadType;
|
||||
list->append(Q_ARG(HeadType, tail.get_head()));
|
||||
Arg(tail.get_tail(), list);
|
||||
}
|
||||
|
||||
// Specialisation for starting with an empty tuple, ie. no arguments.
|
||||
template<>
|
||||
void Arg<boost::tuples::tuple<>>(
|
||||
const boost::tuples::tuple<>&,
|
||||
QList<QGenericArgument>* list);
|
||||
|
||||
// Specialisation for the end of a tuple, where get_tail() returns null_type.
|
||||
template<>
|
||||
void Arg<boost::tuples::null_type>(
|
||||
const boost::tuples::null_type&,
|
||||
QList<QGenericArgument>* list);
|
||||
|
||||
template <typename... Args>
|
||||
class Closure : public ClosureBase {
|
||||
public:
|
||||
explicit SharedPointer(QSharedPointer<T> ptr)
|
||||
: ptr_(ptr) {
|
||||
Closure(
|
||||
QObject* sender,
|
||||
const char* signal,
|
||||
QObject* receiver,
|
||||
const char* slot,
|
||||
const Args&... args)
|
||||
: ClosureBase(new ObjectHelper(sender, signal, this)),
|
||||
// boost::bind is the easiest way to store an argument list.
|
||||
function_(boost::bind(&Closure<Args...>::Call, this, args...)),
|
||||
receiver_(receiver) {
|
||||
const QMetaObject* meta_receiver = receiver->metaObject();
|
||||
QByteArray normalised_slot = QMetaObject::normalizedSignature(slot + 1);
|
||||
const int index = meta_receiver->indexOfSlot(normalised_slot.constData());
|
||||
Q_ASSERT(index != -1);
|
||||
slot_ = meta_receiver->method(index);
|
||||
}
|
||||
|
||||
QObject* data() const {
|
||||
return ptr_.data();
|
||||
virtual void Invoke() {
|
||||
function_();
|
||||
}
|
||||
|
||||
private:
|
||||
QSharedPointer<T> ptr_;
|
||||
void Call(const Args&... args) {
|
||||
auto t = boost::make_tuple(args...);
|
||||
QList<QGenericArgument> arg_list;
|
||||
Arg(t, &arg_list);
|
||||
|
||||
slot_.invoke(
|
||||
receiver_,
|
||||
arg_list.size() > 0 ? arg_list[0] : QGenericArgument(),
|
||||
arg_list.size() > 1 ? arg_list[1] : QGenericArgument(),
|
||||
arg_list.size() > 2 ? arg_list[2] : QGenericArgument(),
|
||||
arg_list.size() > 3 ? arg_list[3] : QGenericArgument(),
|
||||
arg_list.size() > 4 ? arg_list[4] : QGenericArgument(),
|
||||
arg_list.size() > 5 ? arg_list[5] : QGenericArgument(),
|
||||
arg_list.size() > 6 ? arg_list[6] : QGenericArgument(),
|
||||
arg_list.size() > 7 ? arg_list[7] : QGenericArgument(),
|
||||
arg_list.size() > 8 ? arg_list[8] : QGenericArgument(),
|
||||
arg_list.size() > 9 ? arg_list[9] : QGenericArgument());
|
||||
}
|
||||
|
||||
boost::function<void()> function_;
|
||||
QObject* receiver_;
|
||||
QMetaMethod slot_;
|
||||
};
|
||||
|
||||
// For use with a QSharedPointer as a sender.
|
||||
class SharedClosure : public Closure {
|
||||
Q_OBJECT
|
||||
|
||||
template <typename T, typename... Args>
|
||||
class SharedClosure : public Closure<Args...> {
|
||||
public:
|
||||
SharedClosure(SharedPointerWrapper* sender, const char* signal,
|
||||
QObject* receiver, const char* slot,
|
||||
const ClosureArgumentWrapper* val0 = 0,
|
||||
const ClosureArgumentWrapper* val1 = 0,
|
||||
const ClosureArgumentWrapper* val2 = 0,
|
||||
const ClosureArgumentWrapper* val3 = 0)
|
||||
: Closure(sender->data(), signal,
|
||||
receiver, slot,
|
||||
val0, val1, val2, val3),
|
||||
shared_sender_(sender) {
|
||||
SharedClosure(
|
||||
QSharedPointer<T> sender,
|
||||
const char* signal,
|
||||
QObject* receiver,
|
||||
const char* slot,
|
||||
const Args&... args)
|
||||
: Closure<Args...>(
|
||||
sender.data(),
|
||||
signal,
|
||||
receiver,
|
||||
slot,
|
||||
args...),
|
||||
data_(sender) {
|
||||
}
|
||||
|
||||
private:
|
||||
boost::scoped_ptr<SharedPointerWrapper> shared_sender_;
|
||||
QSharedPointer<T> data_;
|
||||
};
|
||||
|
||||
} // namespace _detail
|
||||
|
||||
#define C_ARG(type, data) new _detail::ClosureArgument<type>(data)
|
||||
|
||||
_detail::Closure* NewClosure(
|
||||
QObject* sender,
|
||||
const char* signal,
|
||||
QObject* receiver,
|
||||
const char* slot);
|
||||
|
||||
template <typename T>
|
||||
_detail::Closure* NewClosure(
|
||||
template <typename... Args>
|
||||
_detail::ClosureBase* NewClosure(
|
||||
QObject* sender,
|
||||
const char* signal,
|
||||
QObject* receiver,
|
||||
const char* slot,
|
||||
const T& val0) {
|
||||
return new _detail::Closure(
|
||||
sender, signal, receiver, slot,
|
||||
C_ARG(T, val0));
|
||||
const Args&... args) {
|
||||
return new _detail::Closure<Args...>(
|
||||
sender, signal, receiver, slot, args...);
|
||||
}
|
||||
|
||||
template <typename T0, typename T1>
|
||||
_detail::Closure* NewClosure(
|
||||
QObject* sender,
|
||||
// QSharedPointer variant
|
||||
template <typename T, typename... Args>
|
||||
_detail::ClosureBase* NewClosure(
|
||||
QSharedPointer<T> sender,
|
||||
const char* signal,
|
||||
QObject* receiver,
|
||||
const char* slot,
|
||||
const T0& val0,
|
||||
const T1& val1) {
|
||||
return new _detail::Closure(
|
||||
sender, signal, receiver, slot,
|
||||
C_ARG(T0, val0), C_ARG(T1, val1));
|
||||
const Args&... args) {
|
||||
return new _detail::SharedClosure<T, Args...>(
|
||||
sender, signal, receiver, slot, args...);
|
||||
}
|
||||
|
||||
template <typename T0, typename T1, typename T2>
|
||||
_detail::Closure* NewClosure(
|
||||
QObject* sender,
|
||||
const char* signal,
|
||||
QObject* receiver,
|
||||
const char* slot,
|
||||
const T0& val0,
|
||||
const T1& val1,
|
||||
const T2& val2) {
|
||||
return new _detail::Closure(
|
||||
sender, signal, receiver, slot,
|
||||
C_ARG(T0, val0), C_ARG(T1, val1), C_ARG(T2, val2));
|
||||
}
|
||||
|
||||
template <typename T0, typename T1, typename T2, typename T3>
|
||||
_detail::Closure* NewClosure(
|
||||
QObject* sender,
|
||||
const char* signal,
|
||||
QObject* receiver,
|
||||
const char* slot,
|
||||
const T0& val0,
|
||||
const T1& val1,
|
||||
const T2& val2,
|
||||
const T3& val3) {
|
||||
return new _detail::Closure(
|
||||
sender, signal, receiver, slot,
|
||||
C_ARG(T0, val0), C_ARG(T1, val1), C_ARG(T2, val2), C_ARG(T3, val3));
|
||||
}
|
||||
|
||||
template <typename TP>
|
||||
_detail::Closure* NewClosure(
|
||||
QSharedPointer<TP> sender,
|
||||
const char* signal,
|
||||
QObject* receiver,
|
||||
const char* slot) {
|
||||
return new _detail::SharedClosure(
|
||||
new _detail::SharedPointer<TP>(sender), signal, receiver, slot);
|
||||
}
|
||||
|
||||
template <typename TP, typename T0>
|
||||
_detail::Closure* NewClosure(
|
||||
QSharedPointer<TP> sender,
|
||||
const char* signal,
|
||||
QObject* receiver,
|
||||
const char* slot,
|
||||
const T0& val0) {
|
||||
return new _detail::SharedClosure(
|
||||
new _detail::SharedPointer<TP>(sender), signal, receiver, slot,
|
||||
C_ARG(T0, val0));
|
||||
}
|
||||
|
||||
template <typename TP, typename T0, typename T1>
|
||||
_detail::Closure* NewClosure(
|
||||
QSharedPointer<TP> sender,
|
||||
const char* signal,
|
||||
QObject* receiver,
|
||||
const char* slot,
|
||||
const T0& val0,
|
||||
const T1& val1) {
|
||||
return new _detail::SharedClosure(
|
||||
new _detail::SharedPointer<TP>(sender), signal, receiver, slot,
|
||||
C_ARG(T0, val0), C_ARG(T1, val1));
|
||||
}
|
||||
|
||||
void DoAfter(QObject* receiver, const char* slot, int msec);
|
||||
void DoInAMinuteOrSo(QObject* receiver, const char* slot);
|
||||
|
@ -1,27 +1,29 @@
|
||||
/* This file is part of Clementine.
|
||||
Copyright 2012, David Sansome <me@davidsansome.com>
|
||||
|
||||
|
||||
Clementine is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
Clementine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "googledriveclient.h"
|
||||
#include "oauthenticator.h"
|
||||
#include "core/closure.h"
|
||||
#include "core/network.h"
|
||||
|
||||
#include <qjson/parser.h>
|
||||
|
||||
#include "oauthenticator.h"
|
||||
#include "core/closure.h"
|
||||
#include "core/logging.h"
|
||||
#include "core/network.h"
|
||||
|
||||
using namespace google_drive;
|
||||
|
||||
const char* File::kFolderMimeType = "application/vnd.google-apps.folder";
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <qjson/parser.h>
|
||||
|
||||
#include "core/closure.h"
|
||||
#include "core/logging.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -16,11 +16,8 @@
|
||||
*/
|
||||
|
||||
#include "moodbarloader.h"
|
||||
#include "moodbarpipeline.h"
|
||||
#include "core/application.h"
|
||||
#include "core/closure.h"
|
||||
#include "core/qhash_qurl.h"
|
||||
#include "core/utilities.h"
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
@ -30,7 +27,12 @@
|
||||
#include <QThread>
|
||||
#include <QUrl>
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include "moodbarpipeline.h"
|
||||
#include "core/application.h"
|
||||
#include "core/closure.h"
|
||||
#include "core/logging.h"
|
||||
#include "core/qhash_qurl.h"
|
||||
#include "core/utilities.h"
|
||||
|
||||
MoodbarLoader::MoodbarLoader(Application* app, QObject* parent)
|
||||
: QObject(parent),
|
||||
|
@ -189,7 +189,7 @@ void GPodderSync::DeviceUpdatesFinished(mygpo::DeviceUpdatesPtr reply) {
|
||||
// have a list of the episodes.
|
||||
PodcastUrlLoaderReply* loader_reply = loader_->Load(url);
|
||||
NewClosure(loader_reply, SIGNAL(Finished(bool)),
|
||||
this, SLOT(NewPodcastLoaded(PodcastUrlLoaderReply*,QUrl,QList<QSharedPointer<mygpo::Episode> >)),
|
||||
this, SLOT(NewPodcastLoaded(PodcastUrlLoaderReply*,QUrl,QList<mygpo::EpisodePtr>)),
|
||||
loader_reply, url, episodes_by_podcast[url]);
|
||||
}
|
||||
|
||||
|
@ -1,28 +1,30 @@
|
||||
/* This file is part of Clementine.
|
||||
Copyright 2012, David Sansome <me@davidsansome.com>
|
||||
|
||||
|
||||
Clementine is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
Clementine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "podcastparser.h"
|
||||
#include "podcasturlloader.h"
|
||||
#include "core/closure.h"
|
||||
#include "core/network.h"
|
||||
#include "core/utilities.h"
|
||||
|
||||
#include <QNetworkReply>
|
||||
|
||||
#include "podcastparser.h"
|
||||
#include "core/closure.h"
|
||||
#include "core/logging.h"
|
||||
#include "core/network.h"
|
||||
#include "core/utilities.h"
|
||||
|
||||
const int PodcastUrlLoader::kMaxRedirects = 5;
|
||||
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <qjson/parser.h>
|
||||
|
||||
#include "core/closure.h"
|
||||
#include "core/logging.h"
|
||||
#include "songkickconcertwidget.h"
|
||||
|
||||
const char* SongkickConcerts::kSongkickArtistBucket = "id:songkick";
|
||||
|
@ -15,18 +15,20 @@
|
||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "songinfotextview.h"
|
||||
#include "songkickconcertwidget.h"
|
||||
#include "ui_songkickconcertwidget.h"
|
||||
#include "core/closure.h"
|
||||
#include "core/network.h"
|
||||
#include "core/utilities.h"
|
||||
|
||||
#include <QDate>
|
||||
#include <QDesktopServices>
|
||||
#include <QMouseEvent>
|
||||
#include <QTextDocument>
|
||||
|
||||
#include "songinfotextview.h"
|
||||
#include "ui_songkickconcertwidget.h"
|
||||
#include "core/closure.h"
|
||||
#include "core/logging.h"
|
||||
#include "core/network.h"
|
||||
#include "core/utilities.h"
|
||||
|
||||
const int SongKickConcertWidget::kStaticMapWidth = 100;
|
||||
const int SongKickConcertWidget::kStaticMapHeight = 100;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -U__STRICT_ANSI__ -fpermissive")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -fpermissive -U__STRICT_ANSI__")
|
||||
|
||||
if(USE_SYSTEM_GMOCK)
|
||||
include_directories(${GMOCK_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS})
|
||||
|
@ -11,7 +11,7 @@
|
||||
TEST(ClosureTest, ClosureInvokesReceiver) {
|
||||
TestQObject sender;
|
||||
TestQObject receiver;
|
||||
_detail::Closure* closure = NewClosure(
|
||||
_detail::ClosureBase* closure = NewClosure(
|
||||
&sender, SIGNAL(Emitted()),
|
||||
&receiver, SLOT(Invoke()));
|
||||
EXPECT_EQ(0, receiver.invoked());
|
||||
@ -22,17 +22,18 @@ TEST(ClosureTest, ClosureInvokesReceiver) {
|
||||
TEST(ClosureTest, ClosureDeletesSelf) {
|
||||
TestQObject sender;
|
||||
TestQObject receiver;
|
||||
_detail::Closure* closure = NewClosure(
|
||||
_detail::ClosureBase* closure = NewClosure(
|
||||
&sender, SIGNAL(Emitted()),
|
||||
&receiver, SLOT(Invoke()));
|
||||
QSignalSpy spy(closure, SIGNAL(destroyed()));
|
||||
_detail::ObjectHelper* helper = closure->helper();
|
||||
QSignalSpy spy(helper, SIGNAL(destroyed()));
|
||||
EXPECT_EQ(0, receiver.invoked());
|
||||
sender.Emit();
|
||||
EXPECT_EQ(1, receiver.invoked());
|
||||
|
||||
EXPECT_EQ(0, spy.count());
|
||||
QEventLoop loop;
|
||||
QObject::connect(closure, SIGNAL(destroyed()), &loop, SLOT(quit()));
|
||||
QObject::connect(helper, SIGNAL(destroyed()), &loop, SLOT(quit()));
|
||||
loop.exec();
|
||||
EXPECT_EQ(1, spy.count());
|
||||
}
|
||||
@ -41,23 +42,23 @@ TEST(ClosureTest, ClosureDoesNotCrashWithSharedPointerSender) {
|
||||
TestQObject receiver;
|
||||
TestQObject* sender;
|
||||
boost::scoped_ptr<QSignalSpy> spy;
|
||||
QPointer<_detail::Closure> closure;
|
||||
QPointer<_detail::ObjectHelper> closure;
|
||||
{
|
||||
QSharedPointer<TestQObject> sender_shared(new TestQObject);
|
||||
sender = sender_shared.data();
|
||||
closure = QPointer<_detail::Closure>(NewClosure(
|
||||
closure = QPointer<_detail::ObjectHelper>(NewClosure(
|
||||
sender_shared, SIGNAL(Emitted()),
|
||||
&receiver, SLOT(Invoke())));
|
||||
&receiver, SLOT(Invoke()))->helper());
|
||||
spy.reset(new QSignalSpy(sender, SIGNAL(destroyed())));
|
||||
}
|
||||
EXPECT_EQ(0, receiver.invoked());
|
||||
ASSERT_EQ(0, receiver.invoked());
|
||||
sender->Emit();
|
||||
EXPECT_EQ(1, receiver.invoked());
|
||||
ASSERT_EQ(1, receiver.invoked());
|
||||
|
||||
EXPECT_EQ(0, spy->count());
|
||||
ASSERT_EQ(0, spy->count());
|
||||
QEventLoop loop;
|
||||
QObject::connect(sender, SIGNAL(destroyed()), &loop, SLOT(quit()));
|
||||
loop.exec();
|
||||
EXPECT_EQ(1, spy->count());
|
||||
ASSERT_EQ(1, spy->count());
|
||||
EXPECT_TRUE(closure.isNull());
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user