IBackgroundChecker: new helper class for checkers

BackgroundResultWidget: result widget implementation
This commit is contained in:
Filippo Gentile 2022-11-01 21:44:00 +01:00
parent 9383f4a922
commit 77dcb5d0de
5 changed files with 339 additions and 0 deletions

View file

@ -1,6 +1,14 @@
set(MR_TIMETABLE_PLANNER_SOURCES
${MR_TIMETABLE_PLANNER_SOURCES}
backgroundmanager/backgroundmanager.h
backgroundmanager/backgroundmanager.cpp
backgroundmanager/backgroundresultwidget.cpp
backgroundmanager/backgroundresultwidget.h
backgroundmanager/ibackgroundchecker.cpp
backgroundmanager/ibackgroundchecker.h
PARENT_SCOPE
)

View file

@ -0,0 +1,113 @@
#ifdef ENABLE_BACKGROUND_MANAGER
#include "ibackgroundchecker.h"
#include "backgroundresultwidget.h"
#include <QTreeView>
#include <QHeaderView>
#include <QProgressBar>
#include <QPushButton>
#include <QGridLayout>
#include <QMenu>
#include <QAction>
#include <QTimerEvent>
BackgroundResultWidget::BackgroundResultWidget(IBackgroundChecker *mgr_, QWidget *parent) :
QWidget(parent),
mgr(mgr_),
timerId(0)
{
view = new QTreeView;
view->setUniformRowHeights(true);
view->setSelectionBehavior(QTreeView::SelectRows);
progressBar = new QProgressBar;
startBut = new QPushButton(tr("Start"));
stopBut = new QPushButton(tr("Stop"));
startBut->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
stopBut->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
view->setModel(mgr_->getModel());
view->header()->setStretchLastSection(true);
view->setSelectionBehavior(QTreeView::SelectRows);
QGridLayout *grid = new QGridLayout(this);
grid->addWidget(view, 0, 0, 1, 3);
grid->addWidget(startBut, 1, 0, 1, 1);
grid->addWidget(stopBut, 1, 1, 1, 1);
grid->addWidget(progressBar, 1, 2, 1, 1);
connect(mgr, &IBackgroundChecker::progress, this, &BackgroundResultWidget::onTaskProgress);
connect(mgr, &IBackgroundChecker::taskFinished, this, &BackgroundResultWidget::taskFinished);
connect(startBut, &QPushButton::clicked, this, &BackgroundResultWidget::startTask);
connect(stopBut, &QPushButton::clicked, this, &BackgroundResultWidget::stopTask);
view->setContextMenuPolicy(Qt::CustomContextMenu);
connect(view, &QTreeView::customContextMenuRequested, this, &BackgroundResultWidget::showContextMenu);
setWindowTitle(tr("Rollingstock Errors"));
progressBar->hide();
}
void BackgroundResultWidget::startTask()
{
progressBar->setValue(0);
if(mgr->startWorker())
{
if(timerId)
{
killTimer(timerId); //Stop progressBar from hiding in 1 second
timerId = 0;
}
}
}
void BackgroundResultWidget::stopTask()
{
mgr->abortTasks();
}
void BackgroundResultWidget::onTaskProgress(int val, int max)
{
progressBar->setMaximum(max);
progressBar->setValue(val);
progressBar->show();
}
void BackgroundResultWidget::taskFinished()
{
progressBar->setValue(progressBar->maximum());
if(timerId)
killTimer(timerId);
timerId = startTimer(1000); //Hide progressBar after 1 second
}
void BackgroundResultWidget::timerEvent(QTimerEvent *e)
{
if(e->timerId() == timerId)
{
killTimer(timerId);
timerId = 0;
progressBar->hide();
}
}
void BackgroundResultWidget::showContextMenu(const QPoint& pos)
{
QModelIndex idx = view->indexAt(pos);
if(!idx.isValid())
return;
mgr->showContextMenu(this, view->viewport()->mapToGlobal(pos), idx);
}
#endif // ENABLE_BACKGROUND_MANAGER

View file

@ -0,0 +1,43 @@
#ifndef BACKGROUNDRESULTWIDGET_H
#define BACKGROUNDRESULTWIDGET_H
#ifdef ENABLE_BACKGROUND_MANAGER
#include <QWidget>
class QTreeView;
class QProgressBar;
class QPushButton;
class IBackgroundChecker;
class BackgroundResultWidget : public QWidget
{
Q_OBJECT
public:
explicit BackgroundResultWidget(IBackgroundChecker *mgr_, QWidget *parent = nullptr);
protected:
void timerEvent(QTimerEvent *e) override;
private slots:
void startTask();
void stopTask();
void onTaskProgress(int val, int max);
void taskFinished();
void showContextMenu(const QPoint &pos);
private:
friend class BackgroundResultPanel;
IBackgroundChecker *mgr;
QTreeView *view;
QProgressBar *progressBar;
QPushButton *startBut;
QPushButton *stopBut;
int timerId;
};
#endif // ENABLE_BACKGROUND_MANAGER
#endif // BACKGROUNDRESULTWIDGET_H

View file

@ -0,0 +1,114 @@
#ifdef ENABLE_BACKGROUND_MANAGER
#include "ibackgroundchecker.h"
#include <QThreadPool>
#include "utils/thread/iquittabletask.h"
#include "utils/thread/taskprogressevent.h"
#include "sqlite3pp/sqlite3pp.h"
IBackgroundChecker::IBackgroundChecker(sqlite3pp::database &db, QObject *parent) :
QObject(parent),
mDb(db)
{
}
bool IBackgroundChecker::event(QEvent *e)
{
if(e->type() == TaskProgressEvent::_Type)
{
e->setAccepted(true);
TaskProgressEvent *ev = static_cast<TaskProgressEvent *>(e);
emit progress(ev->progress, ev->progressMax);
return true;
}
else if(e->type() == eventType)
{
e->setAccepted(true);
GenericTaskEvent *ev = static_cast<GenericTaskEvent *>(e);
if(m_mainWorker && ev->task == m_mainWorker)
{
if(!m_mainWorker->wasStopped())
{
setErrors(ev, false);
}
delete m_mainWorker;
m_mainWorker = nullptr;
emit taskFinished();
}
else
{
int idx = m_workers.indexOf(ev->task);
if(idx != -1)
{
m_workers.removeAt(idx);
if(!ev->task->wasStopped())
setErrors(ev, true);
delete ev->task;
}
}
return true;
}
return QObject::event(e);
}
bool IBackgroundChecker::startWorker()
{
if(m_mainWorker)
return false;
if(!mDb.db())
return false;
m_mainWorker = createMainWorker();
QThreadPool::globalInstance()->start(m_mainWorker);
for(auto task = m_workers.begin(); task != m_workers.end(); task++)
{
if(QThreadPool::globalInstance()->tryTake(*task))
{
IQuittableTask *ptr = *task;
m_workers.erase(task);
delete ptr;
}
else
{
(*task)->stop();
}
}
return true;
}
void IBackgroundChecker::abortTasks()
{
if(m_mainWorker)
{
m_mainWorker->stop();
}
for(IQuittableTask *task : qAsConst(m_workers))
{
task->stop();
}
}
void IBackgroundChecker::addSubTask(IQuittableTask *task)
{
m_workers.append(task);
QThreadPool::globalInstance()->start(task);
}
#endif // ENABLE_BACKGROUND_MANAGER

View file

@ -0,0 +1,61 @@
#ifndef IBACKGROUNDCHECKER_H
#define IBACKGROUNDCHECKER_H
#ifdef ENABLE_BACKGROUND_MANAGER
#include <QObject>
#include <QVector>
class QAbstractItemModel;
class QModelIndex;
class QWidget;
class QPoint;
class IQuittableTask;
namespace sqlite3pp {
class database;
}
class IBackgroundChecker : public QObject
{
Q_OBJECT
public:
IBackgroundChecker(sqlite3pp::database &db, QObject *parent = nullptr);
bool event(QEvent *e) override;
bool startWorker();
void abortTasks();
inline bool isRunning() const { return m_mainWorker || m_workers.size() > 0; }
inline QAbstractItemModel *getModel() const { return errorsModel; };
virtual QString getName() const = 0;
virtual void clearModel() = 0;
virtual void showContextMenu(QWidget *panel, const QPoint& globalPos, const QModelIndex& idx) const = 0;
signals:
void progress(int val, int max);
void taskFinished();
protected:
void addSubTask(IQuittableTask *task);
virtual IQuittableTask *createMainWorker() = 0;
virtual void setErrors(QEvent *e, bool merge) = 0;
protected:
sqlite3pp::database &mDb;
QAbstractItemModel *errorsModel = nullptr;
int eventType = 0;
private:
IQuittableTask *m_mainWorker = nullptr;
QVector<IQuittableTask *> m_workers;
};
#endif // ENABLE_BACKGROUND_MANAGER
#endif // IBACKGROUNDCHECKER_H