Skip to content
Snippets Groups Projects
Commit 085d519b authored by Yuya Nishihara's avatar Yuya Nishihara
Browse files

Add PoC interface

parent 760a6ecb
No related branches found
No related tags found
No related merge requests found
......@@ -14,8 +14,16 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt5 COMPONENTS Core Quick REQUIRED)
add_executable(async-operation
backend.cpp
backend.h
handler.cpp
handler.h
main.cpp
qml.qrc
watcher.cpp
watcher.h
worker.cpp
worker.h
)
target_compile_definitions(async-operation
......
#include <QtDebug>
#include "backend.h"
#include "handler.h"
#include "worker.h"
Backend::Backend(QObject *parent)
: QObject(parent),
workerThread_(std::make_unique<QThread>()),
worker_(std::make_unique<Worker>()),
handler_()
{
worker_->moveToThread(workerThread_.get());
workerThread_->start(); // or start() when needed
}
Backend::~Backend()
{
// or add explicit quit()
workerThread_->quit();
workerThread_->wait();
}
std::unique_ptr<Watcher> Backend::run(const std::vector<int> &ids)
{
handler_ = std::make_shared<Handler>(ids);
connect(handler_.get(), &Handler::operate, worker_.get(), &Worker::process);
connect(worker_.get(), &Worker::done, handler_.get(), &Handler::tryNext);
QMetaObject::invokeMethod(handler_.get(), &Handler::tryNext, Qt::QueuedConnection);
return std::make_unique<Watcher>(handler_);
}
#ifndef BACKEND_H
#define BACKEND_H
#include <QObject>
#include <QString>
#include <QThread>
#include <memory>
#include <vector>
#include "handler.h"
#include "watcher.h"
#include "worker.h"
class Backend : public QObject
{
Q_OBJECT
public:
explicit Backend(QObject *parent = nullptr);
~Backend();
std::unique_ptr<Watcher> run(const std::vector<int> &ids);
private:
std::unique_ptr<QThread> workerThread_;
std::unique_ptr<Worker> worker_;
std::shared_ptr<Handler> handler_;
};
#endif // BACKEND_H
#include <QtDebug>
#include "handler.h"
Handler::Handler(const std::vector<int> &ids)
: QObject(nullptr),
ids_(ids),
currentIndex_(-1)
{
}
int Handler::progressMaximum() const
{
return static_cast<int>(ids_.size());
}
int Handler::progressValue() const
{
return currentIndex_;
}
bool Handler::isRunning() const
{
return currentIndex_ < static_cast<int>(ids_.size());
}
void Handler::cancel()
{
qDebug() << "cancel requested";
currentIndex_ = static_cast<int>(ids_.size()) - 1;
}
void Handler::tryNext()
{
++currentIndex_;
emit progressValueChanged(currentIndex_);
if (currentIndex_ < static_cast<int>(ids_.size())) {
emit operate(ids_.at(static_cast<size_t>(currentIndex_)));
} else {
emit finished();
}
}
#ifndef HANDLER_H
#define HANDLER_H
#include <QObject>
#include <vector>
class Handler : public QObject
{
Q_OBJECT
public:
explicit Handler(const std::vector<int> &ids);
int progressMaximum() const;
int progressValue() const;
bool isRunning() const;
void cancel();
public slots:
void tryNext();
signals:
void operate(int id);
void progressValueChanged(int value);
void finished();
private:
std::vector<int> ids_;
int currentIndex_;
};
#endif // HANDLER_H
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QTimer>
#include "backend.h"
int main(int argc, char *argv[])
{
......@@ -7,6 +9,8 @@ int main(int argc, char *argv[])
QGuiApplication app(argc, argv);
Backend backend;
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
......@@ -16,5 +20,8 @@ int main(int argc, char *argv[])
}, Qt::QueuedConnection);
engine.load(url);
auto watcher = backend.run({1, 2, 3});
QTimer::singleShot(2000, [&watcher]() { watcher->cancel(); });
return app.exec();
}
#include "watcher.h"
Watcher::Watcher(const std::shared_ptr<Handler> handler)
: QObject(nullptr),
handler_(handler)
{
connect(handler_.get(), &Handler::progressValueChanged, this, &Watcher::progressValueChanged);
connect(handler_.get(), &Handler::finished, this, &Watcher::finished);
}
int Watcher::progressMaximum() const
{
return handler_->progressMaximum();
}
int Watcher::progressValue() const
{
return handler_->progressValue();
}
bool Watcher::isRunning() const
{
return handler_->isRunning();
}
void Watcher::cancel()
{
handler_->cancel();
}
#ifndef WATCHER_H
#define WATCHER_H
#include <QObject>
#include <memory>
#include "handler.h"
class Watcher : public QObject
{
Q_OBJECT
Q_PROPERTY(int progressMaximum READ progressMaximum CONSTANT)
Q_PROPERTY(int progressValue READ progressValue NOTIFY progressValueChanged)
Q_PROPERTY(bool running READ isRunning NOTIFY finished)
public:
explicit Watcher(const std::shared_ptr<Handler> handler);
int progressMaximum() const;
int progressValue() const;
bool isRunning() const;
// TODO: isCanceled()?
// TODO: QString errorString()?
public slots:
void cancel();
signals:
void progressValueChanged(int value);
void finished();
private:
std::shared_ptr<Handler> handler_;
};
#endif // WATCHER_H
#include <QThread>
#include <QtDebug>
#include "worker.h"
Worker::Worker(QObject *parent) : QObject(parent)
{
}
void Worker::process(int id)
{
qDebug() << "do some expensive work for id:" << id;
QThread::sleep(1);
emit done();
}
worker.h 0 → 100644
#ifndef WORKER_H
#define WORKER_H
#include <QObject>
#include <vector>
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(QObject *parent = nullptr);
public slots:
void process(int id);
signals:
void done();
};
#endif // WORKER_H
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment