Add NewClosure overload for QFuture

This commit is contained in:
John Maguire 2015-11-26 18:34:41 +00:00
parent bcaa9e4a37
commit 2cd15ff430
3 changed files with 26 additions and 21 deletions

View File

@ -22,6 +22,8 @@
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <QFuture>
#include <QFutureWatcher>
#include <QMetaMethod> #include <QMetaMethod>
#include <QObject> #include <QObject>
#include <QSharedPointer> #include <QSharedPointer>
@ -189,13 +191,22 @@ _detail::ClosureBase* NewClosure(QObject* sender, const char* signal,
return NewClosure(sender, signal, std::bind(callback, receiver, args...)); return NewClosure(sender, signal, std::bind(callback, receiver, args...));
} }
template <typename T, typename... Args>
_detail::ClosureBase* NewClosure(QFuture<T> future, QObject* receiver,
const char* slot, const Args&... args) {
QFutureWatcher<T>* watcher = new QFutureWatcher<T>;
watcher->setFuture(future);
QObject::connect(watcher, SIGNAL(finished()), watcher, SLOT(deleteLater()));
return NewClosure(watcher, SIGNAL(finished()), receiver, slot, args...);
}
void DoAfter(QObject* receiver, const char* slot, int msec); void DoAfter(QObject* receiver, const char* slot, int msec);
void DoAfter(std::function<void()> callback, std::chrono::milliseconds msec); void DoAfter(std::function<void()> callback, std::chrono::milliseconds msec);
void DoInAMinuteOrSo(QObject* receiver, const char* slot); void DoInAMinuteOrSo(QObject* receiver, const char* slot);
template <typename R, typename P> template <typename R, typename P>
void DoAfter( void DoAfter(std::function<void()> callback,
std::function<void()> callback, std::chrono::duration<R, P> duration) { std::chrono::duration<R, P> duration) {
QTimer* timer = new QTimer; QTimer* timer = new QTimer;
timer->setSingleShot(true); timer->setSingleShot(true);
NewClosure(timer, SIGNAL(timeout()), callback); NewClosure(timer, SIGNAL(timeout()), callback);

View File

@ -16,7 +16,6 @@
*/ */
#include "prettyimage.h" #include "prettyimage.h"
#include "ui/iconloader.h"
#include <QApplication> #include <QApplication>
#include <QContextMenuEvent> #include <QContextMenuEvent>
@ -24,7 +23,6 @@
#include <QDir> #include <QDir>
#include <QFileDialog> #include <QFileDialog>
#include <QFuture> #include <QFuture>
#include <QFutureWatcher>
#include <QLabel> #include <QLabel>
#include <QMenu> #include <QMenu>
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
@ -34,6 +32,9 @@
#include <QSettings> #include <QSettings>
#include <QtConcurrentRun> #include <QtConcurrentRun>
#include "core/closure.h"
#include "ui/iconloader.h"
const int PrettyImage::kTotalHeight = 200; const int PrettyImage::kTotalHeight = 200;
const int PrettyImage::kReflectionHeight = 40; const int PrettyImage::kReflectionHeight = 40;
const int PrettyImage::kImageHeight = const int PrettyImage::kImageHeight =
@ -60,8 +61,9 @@ void PrettyImage::LazyLoad() {
// Start fetching the image // Start fetching the image
QNetworkReply* reply = network_->get(QNetworkRequest(url_)); QNetworkReply* reply = network_->get(QNetworkRequest(url_));
connect(reply, SIGNAL(finished()), SLOT(ImageFetched()));
state_ = State_Fetching; state_ = State_Fetching;
NewClosure(reply, SIGNAL(finished()), this,
SLOT(ImageFetched(QNetworkReply*)), reply);
} }
QSize PrettyImage::image_size() const { QSize PrettyImage::image_size() const {
@ -76,8 +78,7 @@ QSize PrettyImage::sizeHint() const {
return QSize(image_size().width(), kTotalHeight); return QSize(image_size().width(), kTotalHeight);
} }
void PrettyImage::ImageFetched() { void PrettyImage::ImageFetched(QNetworkReply* reply) {
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
reply->deleteLater(); reply->deleteLater();
QImage image = QImage::fromData(reply->readAll()); QImage image = QImage::fromData(reply->readAll());
@ -90,20 +91,12 @@ void PrettyImage::ImageFetched() {
QFuture<QImage> future = QFuture<QImage> future =
QtConcurrent::run(image_, &QImage::scaled, image_size(), QtConcurrent::run(image_, &QImage::scaled, image_size(),
Qt::KeepAspectRatio, Qt::SmoothTransformation); Qt::KeepAspectRatio, Qt::SmoothTransformation);
NewClosure(future, this, SLOT(ImageScaled(QFuture<QImage>)), future);
QFutureWatcher<QImage>* watcher = new QFutureWatcher<QImage>(this);
watcher->setFuture(future);
connect(watcher, SIGNAL(finished()), SLOT(ImageScaled()));
} }
} }
void PrettyImage::ImageScaled() { void PrettyImage::ImageScaled(QFuture<QImage> future) {
QFutureWatcher<QImage>* watcher = thumbnail_ = QPixmap::fromImage(future.result());
reinterpret_cast<QFutureWatcher<QImage>*>(sender());
if (!watcher) return;
watcher->deleteLater();
thumbnail_ = QPixmap::fromImage(watcher->result());
state_ = State_Finished; state_ = State_Finished;
updateGeometry(); updateGeometry();
@ -179,7 +172,7 @@ void PrettyImage::contextMenuEvent(QContextMenuEvent* e) {
if (!menu_) { if (!menu_) {
menu_ = new QMenu(this); menu_ = new QMenu(this);
menu_->addAction(IconLoader::Load("zoom-in", IconLoader::Base), menu_->addAction(IconLoader::Load("zoom-in", IconLoader::Base),
tr("Show fullsize..."), this, SLOT(ShowFullsize())); tr("Show fullsize..."), this, SLOT(ShowFullsize()));
menu_->addAction(IconLoader::Load("document-save", IconLoader::Base), menu_->addAction(IconLoader::Load("document-save", IconLoader::Base),
tr("Save image") + "...", this, SLOT(SaveAs())); tr("Save image") + "...", this, SLOT(SaveAs()));

View File

@ -18,6 +18,7 @@
#ifndef PRETTYIMAGE_H #ifndef PRETTYIMAGE_H
#define PRETTYIMAGE_H #define PRETTYIMAGE_H
#include <QFuture>
#include <QUrl> #include <QUrl>
#include <QWidget> #include <QWidget>
@ -56,8 +57,8 @@ signals:
void paintEvent(QPaintEvent*); void paintEvent(QPaintEvent*);
private slots: private slots:
void ImageFetched(); void ImageFetched(QNetworkReply* reply);
void ImageScaled(); void ImageScaled(QFuture<QImage> future);
private: private:
enum State { enum State {