UI: Add SchedulePage.

This commit is contained in:
Nodir Temirkhodjaev 2019-12-31 12:06:28 +05:00
parent fba0f88a6b
commit 48208ff8c6
22 changed files with 780 additions and 89 deletions

View File

@ -27,6 +27,7 @@ SOURCES += \
form/controls/listview.cpp \ form/controls/listview.cpp \
form/controls/spincombo.cpp \ form/controls/spincombo.cpp \
form/controls/tabbar.cpp \ form/controls/tabbar.cpp \
form/controls/tableview.cpp \
form/controls/textarea2splitter.cpp \ form/controls/textarea2splitter.cpp \
form/controls/textarea2splitterhandle.cpp \ form/controls/textarea2splitterhandle.cpp \
form/graph/axistickerspeed.cpp \ form/graph/axistickerspeed.cpp \
@ -56,7 +57,6 @@ SOURCES += \
log/model/appblockedmodel.cpp \ log/model/appblockedmodel.cpp \
log/model/appstatmodel.cpp \ log/model/appstatmodel.cpp \
log/model/iplistmodel.cpp \ log/model/iplistmodel.cpp \
log/model/stringlistmodel.cpp \
log/model/traflistmodel.cpp \ log/model/traflistmodel.cpp \
main.cpp \ main.cpp \
mainwindow.cpp \ mainwindow.cpp \
@ -67,6 +67,7 @@ SOURCES += \
task/taskinfo.cpp \ task/taskinfo.cpp \
task/taskinfotasix.cpp \ task/taskinfotasix.cpp \
task/taskinfoupdatechecker.cpp \ task/taskinfoupdatechecker.cpp \
task/tasklistmodel.cpp \
task/taskmanager.cpp \ task/taskmanager.cpp \
task/tasktasix.cpp \ task/tasktasix.cpp \
task/taskupdatechecker.cpp \ task/taskupdatechecker.cpp \
@ -87,6 +88,8 @@ SOURCES += \
util/guiutil.cpp \ util/guiutil.cpp \
util/hotkeymanager.cpp \ util/hotkeymanager.cpp \
util/logger.cpp \ util/logger.cpp \
util/model/stringlistmodel.cpp \
util/model/tableitemmodel.cpp \
util/nativeeventfilter.cpp \ util/nativeeventfilter.cpp \
util/net/hostinfo.cpp \ util/net/hostinfo.cpp \
util/net/hostinfocache.cpp \ util/net/hostinfocache.cpp \
@ -124,6 +127,7 @@ HEADERS += \
form/controls/listview.h \ form/controls/listview.h \
form/controls/spincombo.h \ form/controls/spincombo.h \
form/controls/tabbar.h \ form/controls/tabbar.h \
form/controls/tableview.h \
form/controls/textarea2splitter.h \ form/controls/textarea2splitter.h \
form/controls/textarea2splitterhandle.h \ form/controls/textarea2splitterhandle.h \
form/graph/axistickerspeed.h \ form/graph/axistickerspeed.h \
@ -153,7 +157,6 @@ HEADERS += \
log/model/appblockedmodel.h \ log/model/appblockedmodel.h \
log/model/appstatmodel.h \ log/model/appstatmodel.h \
log/model/iplistmodel.h \ log/model/iplistmodel.h \
log/model/stringlistmodel.h \
log/model/traflistmodel.h \ log/model/traflistmodel.h \
mainwindow.h \ mainwindow.h \
stat/quotamanager.h \ stat/quotamanager.h \
@ -163,6 +166,7 @@ HEADERS += \
task/taskinfo.h \ task/taskinfo.h \
task/taskinfotasix.h \ task/taskinfotasix.h \
task/taskinfoupdatechecker.h \ task/taskinfoupdatechecker.h \
task/tasklistmodel.h \
task/taskmanager.h \ task/taskmanager.h \
task/tasktasix.h \ task/tasktasix.h \
task/taskupdatechecker.h \ task/taskupdatechecker.h \
@ -183,6 +187,8 @@ HEADERS += \
util/guiutil.h \ util/guiutil.h \
util/hotkeymanager.h \ util/hotkeymanager.h \
util/logger.h \ util/logger.h \
util/model/stringlistmodel.h \
util/model/tableitemmodel.h \
util/nativeeventfilter.h \ util/nativeeventfilter.h \
util/net/hostinfo.h \ util/net/hostinfo.h \
util/net/hostinfocache.h \ util/net/hostinfocache.h \

View File

@ -0,0 +1,14 @@
#include "tableview.h"
TableView::TableView(QWidget *parent) :
QTableView(parent)
{
}
void TableView::currentChanged(const QModelIndex &current,
const QModelIndex &previous)
{
QTableView::currentChanged(current, previous);
emit currentIndexChanged(current);
}

View File

@ -0,0 +1,21 @@
#ifndef TABLEVIEW_H
#define TABLEVIEW_H
#include <QTableView>
class TableView : public QTableView
{
Q_OBJECT
public:
explicit TableView(QWidget *parent = nullptr);
signals:
void currentIndexChanged(const QModelIndex &index);
protected:
void currentChanged(const QModelIndex &current,
const QModelIndex &previous) override;
};
#endif // TABLEVIEW_H

View File

@ -1,7 +1,219 @@
#include "schedulepage.h" #include "schedulepage.h"
#include <QCheckBox>
#include <QDate>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QPushButton>
#include <QSpinBox>
#include <QTableView>
#include <QVBoxLayout>
#include "../../../task/taskinfo.h"
#include "../../../task/tasklistmodel.h"
#include "../../../task/taskmanager.h"
#include "../../controls/checkspincombo.h"
#include "../../controls/controlutil.h"
#include "../../controls/tableview.h"
#include "../optionscontroller.h"
namespace {
const ValuesList taskIntervalHourValues = {
3, 1, 6, 12, 24, 24 * 7, 24 * 30
};
}
SchedulePage::SchedulePage(OptionsController *ctrl, SchedulePage::SchedulePage(OptionsController *ctrl,
QWidget *parent) : QWidget *parent) :
BasePage(ctrl, parent) BasePage(ctrl, parent),
m_taskListModel(new TaskListModel(taskManager(), this))
{ {
setupTaskListModel();
setupUi();
}
void SchedulePage::setScheduleEdited(bool v)
{
if (m_scheduleEdited != v) {
m_scheduleEdited = v;
if (scheduleEdited()) {
ctrl()->setOthersEdited(true);
}
}
}
void SchedulePage::onEditResetted()
{
setScheduleEdited(false);
m_taskListModel->resetEdited();
}
void SchedulePage::onSaved()
{
if (!scheduleEdited()) return;
m_taskListModel->saveChanges();
}
void SchedulePage::onRetranslateUi()
{
m_taskListModel->refresh();
m_btTaskRun->setText(tr("Run"));
m_btTaskAbort->setText(tr("Abort"));
retranslateTaskDetails();
}
void SchedulePage::setupTaskListModel()
{
connect(m_taskListModel, &TaskListModel::dataChanged, [&] {
setScheduleEdited(true);
});
}
void SchedulePage::retranslateTaskDetails()
{
const QStringList list = {
tr("Custom"), tr("Hourly"), tr("Each 6 hours"),
tr("Each 12 hours"), tr("Daily"), tr("Weekly"), tr("Monthly")
};
m_lscTaskInterval->setNames(list);
m_lscTaskInterval->spinBox()->setSuffix(tr(" hours"));
}
void SchedulePage::setupUi()
{
auto layout = new QVBoxLayout();
// Tasks Table
setupTableTasks();
setupTableTasksHeader();
layout->addWidget(m_tableTasks, 1);
// Task Details
setupTaskDetails();
layout->addWidget(m_taskDetailsRow);
// Actions on tasks table's current changed
setupTableTasksChanged();
this->setLayout(layout);
}
void SchedulePage::setupTableTasks()
{
m_tableTasks = new TableView();
m_tableTasks->setSelectionMode(QAbstractItemView::SingleSelection);
m_tableTasks->setSelectionBehavior(QAbstractItemView::SelectRows);
m_tableTasks->setModel(taskListModel());
}
void SchedulePage::setupTableTasksHeader()
{
auto header = m_tableTasks->horizontalHeader();
header->setSectionResizeMode(0, QHeaderView::Fixed);
header->setSectionResizeMode(1, QHeaderView::Stretch);
header->setSectionResizeMode(2, QHeaderView::Stretch);
header->setSectionResizeMode(3, QHeaderView::Stretch);
const auto refreshTableTasksHeader = [&] {
auto hh = m_tableTasks->horizontalHeader();
hh->resizeSection(0, qRound(hh->width() * 0.45));
};
refreshTableTasksHeader();
connect(header, &QHeaderView::geometriesChanged, this, refreshTableTasksHeader);
}
void SchedulePage::setupTaskDetails()
{
m_taskDetailsRow = new QWidget();
auto layout = new QHBoxLayout();
layout->setMargin(0);
m_taskDetailsRow->setLayout(layout);
setupTaskInterval();
m_btTaskRun = ControlUtil::createButton(":/images/run.png", [&] {
currentTaskInfo()->run();
});
m_btTaskAbort = ControlUtil::createButton(":/images/cancel.png", [&] {
currentTaskInfo()->abort();
});
layout->addWidget(m_lscTaskInterval, 1);
layout->addWidget(m_btTaskRun);
layout->addWidget(m_btTaskAbort);
}
void SchedulePage::setupTaskInterval()
{
m_lscTaskInterval = new CheckSpinCombo();
m_lscTaskInterval->checkBox()->setFont(ControlUtil::createFont(QFont::DemiBold));
m_lscTaskInterval->spinBox()->setRange(1, 24 * 30 * 12); // ~Year
m_lscTaskInterval->setValues(taskIntervalHourValues);
connect(m_lscTaskInterval->checkBox(), &QCheckBox::toggled, [&](bool checked) {
const int taskIndex = currentTaskIndex();
const auto index = taskListModel()->index(taskIndex, 0);
taskListModel()->setData(index, checked, TaskListModel::RoleEnabled);
});
connect(m_lscTaskInterval->spinBox(), QOverload<int>::of(&QSpinBox::valueChanged), [&](int value) {
const int taskIndex = currentTaskIndex();
const auto index = taskListModel()->index(taskIndex, 1);
taskListModel()->setData(index, value, TaskListModel::RoleIntervalHours);
});
}
void SchedulePage::setupTableTasksChanged()
{
const auto refreshTableTasksChanged = [&] {
const int taskIndex = currentTaskIndex();
const bool taskSelected = taskIndex >= 0;
setCurrentTaskInfo(taskSelected
? taskListModel()->taskInfoAt(taskIndex)
: nullptr);
m_taskDetailsRow->setVisible(taskSelected);
if (taskSelected) {
const auto index = taskListModel()->index(taskIndex, 0);
m_lscTaskInterval->checkBox()->setChecked(
taskListModel()->data(index, TaskListModel::RoleEnabled).toBool());
m_lscTaskInterval->checkBox()->setText(
taskListModel()->data(index).toString());
m_lscTaskInterval->spinBox()->setValue(
taskListModel()->data(index, TaskListModel::RoleIntervalHours).toInt());
const bool running = currentTaskInfo()->running();
m_btTaskRun->setEnabled(!running);
m_btTaskAbort->setEnabled(running);
}
};
refreshTableTasksChanged();
connect(m_tableTasks, &TableView::currentIndexChanged, this, refreshTableTasksChanged);
connect(taskListModel(), &TaskListModel::dataChanged, this, refreshTableTasksChanged);
connect(taskManager(), &TaskManager::taskStarted, this, refreshTableTasksChanged);
connect(taskManager(), &TaskManager::taskFinished, this, refreshTableTasksChanged);
}
int SchedulePage::currentTaskIndex() const
{
return m_tableTasks->currentIndex().row();
} }

View File

@ -3,6 +3,13 @@
#include "basepage.h" #include "basepage.h"
QT_FORWARD_DECLARE_CLASS(QTableView)
QT_FORWARD_DECLARE_CLASS(CheckSpinCombo)
QT_FORWARD_DECLARE_CLASS(TableView)
QT_FORWARD_DECLARE_CLASS(TaskInfo)
QT_FORWARD_DECLARE_CLASS(TaskListModel)
class SchedulePage : public BasePage class SchedulePage : public BasePage
{ {
Q_OBJECT Q_OBJECT
@ -11,8 +18,45 @@ public:
explicit SchedulePage(OptionsController *ctrl = nullptr, explicit SchedulePage(OptionsController *ctrl = nullptr,
QWidget *parent = nullptr); QWidget *parent = nullptr);
signals: TaskListModel *taskListModel() const { return m_taskListModel; }
protected slots:
void onEditResetted() override;
void onSaved() override;
void onRetranslateUi() override;
private:
bool scheduleEdited() const { return m_scheduleEdited; }
void setScheduleEdited(bool v);
void retranslateTaskDetails();
void setupTaskListModel();
void setupUi();
void setupTableTasks();
void setupTableTasksHeader();
void setupTaskDetails();
void setupTaskInterval();
void setupTableTasksChanged();
int currentTaskIndex() const;
TaskInfo *currentTaskInfo() const { return m_taskInfo; }
void setCurrentTaskInfo(TaskInfo *v) { m_taskInfo = v; }
private:
bool m_scheduleEdited = false;
TaskListModel *m_taskListModel = nullptr;
TaskInfo *m_taskInfo = nullptr;
TableView *m_tableTasks = nullptr;
QWidget *m_taskDetailsRow = nullptr;
CheckSpinCombo *m_lscTaskInterval = nullptr;
QPushButton *m_btTaskRun = nullptr;
QPushButton *m_btTaskAbort = nullptr;
}; };
#endif // SCHEDULEPAGE_H #endif // SCHEDULEPAGE_H

View File

@ -734,7 +734,7 @@ void StatisticsPage::setupAppListViewChanged()
refreshAppListViewChanged(); refreshAppListViewChanged();
connect(m_appListView, &ListView::currentIndexChanged, this , refreshAppListViewChanged); connect(m_appListView, &ListView::currentIndexChanged, this, refreshAppListViewChanged);
} }
void StatisticsPage::updatePage() void StatisticsPage::updatePage()

View File

@ -193,7 +193,7 @@ void FortManager::setupLogger()
void FortManager::setupTaskManager() void FortManager::setupTaskManager()
{ {
m_taskManager->loadSettings(settings(), m_confManager); m_taskManager->loadSettings();
} }
void FortManager::setupTranslationManager() void FortManager::setupTranslationManager()

View File

@ -4,7 +4,7 @@
#include <QHash> #include <QHash>
#include <QSet> #include <QSet>
#include "stringlistmodel.h" #include "../../util/model/stringlistmodel.h"
QT_FORWARD_DECLARE_CLASS(IpListModel) QT_FORWARD_DECLARE_CLASS(IpListModel)
QT_FORWARD_DECLARE_CLASS(LogEntryBlocked) QT_FORWARD_DECLARE_CLASS(LogEntryBlocked)

View File

@ -1,7 +1,7 @@
#ifndef APPSTATMODEL_H #ifndef APPSTATMODEL_H
#define APPSTATMODEL_H #define APPSTATMODEL_H
#include "stringlistmodel.h" #include "../../util/model/stringlistmodel.h"
QT_FORWARD_DECLARE_CLASS(AppInfoCache) QT_FORWARD_DECLARE_CLASS(AppInfoCache)
QT_FORWARD_DECLARE_CLASS(LogEntryProcNew) QT_FORWARD_DECLARE_CLASS(LogEntryProcNew)

View File

@ -1,7 +1,7 @@
#ifndef IPLISTMODEL_H #ifndef IPLISTMODEL_H
#define IPLISTMODEL_H #define IPLISTMODEL_H
#include "stringlistmodel.h" #include "../../util/model/stringlistmodel.h"
class IpListModel : public StringListModel class IpListModel : public StringListModel
{ {

View File

@ -9,14 +9,7 @@
TrafListModel::TrafListModel(StatManager *statManager, TrafListModel::TrafListModel(StatManager *statManager,
QObject *parent) : QObject *parent) :
QAbstractItemModel(parent), TableItemModel(parent),
m_isEmpty(false),
m_unit(UnitAdaptive),
m_type(TrafHourly),
m_appId(0),
m_minTrafTime(0),
m_maxTrafTime(0),
m_trafCount(0),
m_statManager(statManager) m_statManager(statManager)
{ {
} }
@ -36,28 +29,6 @@ void TrafListModel::setAppId(qint64 appId)
m_appId = appId; m_appId = appId;
} }
QModelIndex TrafListModel::index(int row, int column,
const QModelIndex &parent) const
{
return hasIndex(row, column, parent)
? createIndex(row, column) : QModelIndex();
}
QModelIndex TrafListModel::parent(const QModelIndex &child) const
{
Q_UNUSED(child)
return {};
}
QModelIndex TrafListModel::sibling(int row, int column,
const QModelIndex &index) const
{
Q_UNUSED(index)
return this->index(row, column);
}
int TrafListModel::rowCount(const QModelIndex &parent) const int TrafListModel::rowCount(const QModelIndex &parent) const
{ {
Q_UNUSED(parent) Q_UNUSED(parent)
@ -70,11 +41,6 @@ int TrafListModel::columnCount(const QModelIndex &parent) const
return parent.isValid() ? 0 : 4; return parent.isValid() ? 0 : 4;
} }
bool TrafListModel::hasChildren(const QModelIndex &parent) const
{
return !parent.isValid() && rowCount() > 0;
}
QVariant TrafListModel::headerData(int section, Qt::Orientation orientation, int role) const QVariant TrafListModel::headerData(int section, Qt::Orientation orientation, int role) const
{ {
if (orientation == Qt::Horizontal if (orientation == Qt::Horizontal
@ -113,12 +79,6 @@ QVariant TrafListModel::data(const QModelIndex &index, int role) const
return QVariant(); return QVariant();
} }
Qt::ItemFlags TrafListModel::flags(const QModelIndex &index) const
{
return QAbstractItemModel::flags(index)
| (index.isValid() ? Qt::ItemNeverHasChildren : Qt::NoItemFlags);
}
void TrafListModel::clear() void TrafListModel::clear()
{ {
m_statManager->clear(); m_statManager->clear();

View File

@ -1,7 +1,7 @@
#ifndef TRAFLISTMODEL_H #ifndef TRAFLISTMODEL_H
#define TRAFLISTMODEL_H #define TRAFLISTMODEL_H
#include <QAbstractItemModel> #include "../util/model/tableitemmodel.h"
QT_FORWARD_DECLARE_CLASS(StatManager) QT_FORWARD_DECLARE_CLASS(StatManager)
@ -15,7 +15,7 @@ struct TrafficRow {
qint64 outBytes = 0; qint64 outBytes = 0;
}; };
class TrafListModel : public QAbstractItemModel class TrafListModel : public TableItemModel
{ {
Q_OBJECT Q_OBJECT
@ -50,22 +50,13 @@ public:
qint64 appId() const { return m_appId; } qint64 appId() const { return m_appId; }
void setAppId(qint64 appId); void setAppId(qint64 appId);
QModelIndex index(int row, int column,
const QModelIndex &parent = QModelIndex()) const override;
QModelIndex parent(const QModelIndex &child) const override;
QModelIndex sibling(int row, int column,
const QModelIndex &index) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override;
bool hasChildren(const QModelIndex &parent = QModelIndex()) const override;
QVariant headerData(int section, Qt::Orientation orientation, QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const override; int role = Qt::DisplayRole) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
public slots: public slots:
void clear(); void clear();
@ -91,20 +82,20 @@ private:
static const char *getSqlSelectTraffic(TrafType type, qint64 appId); static const char *getSqlSelectTraffic(TrafType type, qint64 appId);
private: private:
bool m_isEmpty; bool m_isEmpty = false;
TrafUnit m_unit; TrafUnit m_unit = UnitAdaptive;
TrafType m_type; TrafType m_type = TrafHourly;
qint64 m_appId; qint64 m_appId = 0;
qint32 m_minTrafTime; qint32 m_minTrafTime = 0;
qint32 m_maxTrafTime; qint32 m_maxTrafTime = 0;
qint32 m_trafCount; qint32 m_trafCount = 0;
StatManager *m_statManager = nullptr;
mutable TrafficRow m_rowCache; mutable TrafficRow m_rowCache;
StatManager *m_statManager;
}; };
#endif // TRAFLISTMODEL_H #endif // TRAFLISTMODEL_H

View File

@ -12,6 +12,7 @@
TaskInfo::TaskInfo(TaskType type, QObject *parent) : TaskInfo::TaskInfo(TaskType type, QObject *parent) :
QObject(parent), QObject(parent),
m_enabled(false), m_enabled(false),
m_running(false),
m_aborted(false), m_aborted(false),
m_intervalHours(24), m_intervalHours(24),
m_type(type), m_type(type),
@ -33,6 +34,14 @@ void TaskInfo::setEnabled(bool enabled)
} }
} }
void TaskInfo::setRunning(bool running)
{
if (m_running != running) {
m_running = running;
emit enabledChanged();
}
}
void TaskInfo::setIntervalHours(int intervalHours) void TaskInfo::setIntervalHours(int intervalHours)
{ {
if (m_intervalHours != intervalHours) { if (m_intervalHours != intervalHours) {
@ -159,6 +168,9 @@ void TaskInfo::run()
setTaskWorker(taskWorker); setTaskWorker(taskWorker);
setRunning(true);
emit workStarted();
taskWorker->run(); taskWorker->run();
} }
@ -185,6 +197,7 @@ void TaskInfo::handleFinished(bool success)
setLastSuccess(lastRun()); setLastSuccess(lastRun());
} }
setRunning(false);
emit workFinished(success); emit workFinished(success);
abort(); abort();

View File

@ -37,6 +37,9 @@ public:
bool enabled() const { return m_enabled; } bool enabled() const { return m_enabled; }
void setEnabled(bool enabled); void setEnabled(bool enabled);
bool running() const { return m_running; }
void setRunning(bool running);
int intervalHours() const { return m_intervalHours; } int intervalHours() const { return m_intervalHours; }
void setIntervalHours(int intervalHours); void setIntervalHours(int intervalHours);
@ -62,8 +65,6 @@ public:
TaskWorker *taskWorker() const { return m_taskWorker; } TaskWorker *taskWorker() const { return m_taskWorker; }
void setTaskWorker(TaskWorker *taskWorker); void setTaskWorker(TaskWorker *taskWorker);
bool running() const { return m_taskWorker != nullptr; }
void rawData(QByteArray &data) const; void rawData(QByteArray &data) const;
void setRawData(const QByteArray &data); void setRawData(const QByteArray &data);
@ -72,12 +73,14 @@ public:
signals: signals:
void enabledChanged(); void enabledChanged();
void runningChanged();
void intervalHoursChanged(); void intervalHoursChanged();
void typeChanged(); void typeChanged();
void lastRunChanged(); void lastRunChanged();
void lastSuccessChanged(); void lastSuccessChanged();
void taskWorkerChanged(); void taskWorkerChanged();
void workStarted();
void workFinished(bool success); void workFinished(bool success);
public slots: public slots:
@ -94,6 +97,7 @@ private:
private: private:
quint8 m_enabled : 1; quint8 m_enabled : 1;
quint8 m_running : 1;
quint8 m_aborted : 1; // transient quint8 m_aborted : 1; // transient
quint16 m_intervalHours; quint16 m_intervalHours;

View File

@ -0,0 +1,245 @@
#include "tasklistmodel.h"
#include "taskinfo.h"
#include "taskmanager.h"
TaskListModel::TaskListModel(TaskManager *taskManager,
QObject *parent) :
TableItemModel(parent),
m_taskManager(taskManager)
{
setupTaskRows();
connect(m_taskManager, &TaskManager::taskFinished, this, &TaskListModel::refresh);
}
TaskListModel::~TaskListModel()
{
clearTaskRows();
}
const QList<TaskInfo *> &TaskListModel::taskInfosList() const
{
return taskManager()->taskInfosList();
}
int TaskListModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return taskInfosList().size();
}
int TaskListModel::columnCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : 4;
}
QVariant TaskListModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal
&& role == Qt::DisplayRole) {
switch (section) {
case 0: return tr("Name");
case 1: return tr("Interval, hours");
case 2: return tr("Last Run");
case 3: return tr("Last Success");
}
}
return QVariant();
}
QVariant TaskListModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
switch (role) {
case Qt::DisplayRole:
{
const int row = index.row();
const int column = index.column();
const auto taskInfo = taskInfoAt(row);
switch (column) {
case 0: return taskInfo->title();
case 1: return taskIntervalHours(row);
case 2: return formatDateTime(taskInfo->lastRun());
case 3: return formatDateTime(taskInfo->lastSuccess());
}
}
break;
case Qt::CheckStateRole:
case RoleEnabled:
if (index.column() == 0) {
return taskEnabled(index.row());
}
break;
case RoleIntervalHours:
return taskIntervalHours(index.row());
case RoleRunning: {
const auto taskInfo = taskInfoAt(index.row());
return taskInfo->running();
}
}
return QVariant();
}
bool TaskListModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
Q_UNUSED(value)
if (!index.isValid())
return false;
switch (role) {
case Qt::CheckStateRole:
setTaskEnabled(index, !taskEnabled(index.row()));
return true;
case RoleEnabled:
setTaskEnabled(index, value.toBool());
return true;
case RoleIntervalHours:
setTaskIntervalHours(index, value.toInt());
return true;
}
return false;
}
Qt::ItemFlags TaskListModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return Qt::NoItemFlags;
const int column = index.column();
return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemNeverHasChildren
| (column == 0 ? Qt::ItemIsUserCheckable : Qt::NoItemFlags);
}
void TaskListModel::resetEdited()
{
beginResetModel();
setupTaskRows();
endResetModel();
}
void TaskListModel::saveChanges()
{
const int taskCount = taskInfosList().size();
for (int i = 0; i < taskCount; ++i) {
const auto taskRow = taskRowAt(i);
if (!taskRow) continue;
auto taskInfo = taskInfoAt(i);
taskInfo->setEnabled(taskRow->enabled);
taskInfo->setIntervalHours(taskRow->intervalHours);
}
taskManager()->saveSettings();
}
void TaskListModel::setupTaskRows()
{
clearTaskRows();
const int taskCount = taskInfosList().size();
for (int i = 0; i < taskCount; ++i) {
m_taskRows.append(nullptr);
}
}
void TaskListModel::clearTaskRows()
{
qDeleteAll(m_taskRows);
m_taskRows.clear();
}
bool TaskListModel::taskEnabled(int index) const
{
const auto taskRow = taskRowAt(index);
if (taskRow)
return taskRow->enabled;
const auto taskInfo = taskInfoAt(index);
return taskInfo->enabled();
}
void TaskListModel::setTaskEnabled(const QModelIndex &index, bool v)
{
const int row = index.row();
auto taskRow = taskRowAt(row);
if (!taskRow) {
taskRow = addTaskRow(row);
}
if (taskRow->enabled == v)
return;
taskRow->enabled = v;
emit dataChanged(index, index, {Qt::CheckStateRole});
}
int TaskListModel::taskIntervalHours(int index) const
{
const auto taskRow = taskRowAt(index);
if (taskRow)
return taskRow->intervalHours;
const auto taskInfo = taskInfoAt(index);
return taskInfo->intervalHours();
}
void TaskListModel::setTaskIntervalHours(const QModelIndex &index, int v)
{
const int row = index.row();
auto taskRow = taskRowAt(row);
if (!taskRow) {
taskRow = addTaskRow(row);
}
if (taskRow->intervalHours == v)
return;
taskRow->intervalHours = v;
emit dataChanged(index, index, {Qt::DisplayRole});
}
TaskRow *TaskListModel::addTaskRow(int index)
{
auto taskRow = new TaskRow();
m_taskRows.replace(index, taskRow);
auto taskInfo = taskInfoAt(index);
taskRow->enabled = taskInfo->enabled();
taskRow->intervalHours = taskInfo->intervalHours();
return taskRow;
}
TaskInfo *TaskListModel::taskInfoAt(int index) const
{
return taskInfosList().at(index);
}
TaskRow *TaskListModel::taskRowAt(int index) const
{
return m_taskRows.at(index);
}
QString TaskListModel::formatDateTime(const QDateTime &dateTime)
{
return dateTime.toString("yyyy-MM-dd HH:mm:ss");
}

View File

@ -0,0 +1,74 @@
#ifndef TASKLISTMODEL_H
#define TASKLISTMODEL_H
#include <QList>
#include "../util/model/tableitemmodel.h"
QT_FORWARD_DECLARE_CLASS(TaskInfo)
QT_FORWARD_DECLARE_CLASS(TaskManager)
struct TaskRow {
bool enabled = false;
int intervalHours = 0;
};
class TaskListModel : public TableItemModel
{
Q_OBJECT
public:
enum Roles {
RoleEnabled = Qt::UserRole,
RoleIntervalHours,
RoleRunning
};
Q_ENUM(Roles)
explicit TaskListModel(TaskManager *taskManager,
QObject *parent = nullptr);
~TaskListModel() override;
TaskManager *taskManager() const { return m_taskManager; }
const QList<TaskInfo *> &taskInfosList() const;
TaskInfo *taskInfoAt(int index) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
public slots:
void resetEdited();
void saveChanges();
private:
void setupTaskRows();
void clearTaskRows();
bool taskEnabled(int index) const;
void setTaskEnabled(const QModelIndex &index, bool v);
int taskIntervalHours(int index) const;
void setTaskIntervalHours(const QModelIndex &index, int v);
TaskRow *addTaskRow(int index);
TaskRow *taskRowAt(int index) const;
static QString formatDateTime(const QDateTime &dateTime);
private:
TaskManager *m_taskManager = nullptr;
mutable QList<TaskRow *> m_taskRows;
};
#endif // TASKLISTMODEL_H

View File

@ -6,7 +6,6 @@
#include "../util/dateutil.h" #include "../util/dateutil.h"
#include "taskinfotasix.h" #include "taskinfotasix.h"
#include "taskinfoupdatechecker.h" #include "taskinfoupdatechecker.h"
#include "taskworker.h"
TaskManager::TaskManager(FortManager *fortManager, TaskManager::TaskManager(FortManager *fortManager,
QObject *parent) : QObject *parent) :
@ -18,8 +17,17 @@ TaskManager::TaskManager(FortManager *fortManager,
m_timer.setSingleShot(true); m_timer.setSingleShot(true);
connect(&m_timer, &QTimer::timeout, connect(&m_timer, &QTimer::timeout, this, &TaskManager::runExpiredTasks);
this, &TaskManager::runExpiredTasks); }
FortSettings *TaskManager::settings() const
{
return fortManager()->settings();
}
ConfManager *TaskManager::confManager() const
{
return fortManager()->confManager();
} }
void TaskManager::setupTasks() void TaskManager::setupTasks()
@ -32,17 +40,16 @@ void TaskManager::setupTasks()
void TaskManager::appendTaskInfo(TaskInfo *taskInfo) void TaskManager::appendTaskInfo(TaskInfo *taskInfo)
{ {
connect(taskInfo, &TaskInfo::workFinished, connect(taskInfo, &TaskInfo::workStarted, this, &TaskManager::handleTaskStarted);
this, &TaskManager::handleTaskFinished); connect(taskInfo, &TaskInfo::workFinished, this, &TaskManager::handleTaskFinished);
m_taskInfos.append(taskInfo); m_taskInfos.append(taskInfo);
} }
void TaskManager::loadSettings(const FortSettings *fortSettings, void TaskManager::loadSettings()
ConfManager *confManager)
{ {
if (!confManager->loadTasks(m_taskInfos)) { if (!confManager()->loadTasks(m_taskInfos)) {
const TasksMap tasksMap = fortSettings->tasks(); const TasksMap tasksMap = settings()->tasks();
if (!tasksMap.isEmpty()) { if (!tasksMap.isEmpty()) {
for (TaskInfo *taskInfo : m_taskInfos) { for (TaskInfo *taskInfo : m_taskInfos) {
const QByteArray taskData = tasksMap.value(taskInfo->name()); const QByteArray taskData = tasksMap.value(taskInfo->name());
@ -56,26 +63,33 @@ void TaskManager::loadSettings(const FortSettings *fortSettings,
runExpiredTasks(); runExpiredTasks();
} }
bool TaskManager::saveSettings(FortSettings *fortSettings, bool TaskManager::saveSettings()
ConfManager *confManager)
{ {
runExpiredTasks(); runExpiredTasks();
if (!confManager->saveTasks(m_taskInfos)) if (!confManager()->saveTasks(m_taskInfos))
return false; return false;
fortSettings->removeTasks(); settings()->removeTasks();
return true; return true;
} }
void TaskManager::handleTaskStarted()
{
auto taskInfo = qobject_cast<TaskInfo *>(sender());
emit taskStarted(taskInfo);
}
void TaskManager::handleTaskFinished(bool success) void TaskManager::handleTaskFinished(bool success)
{ {
auto taskInfo = qobject_cast<TaskInfo *>(sender()); auto taskInfo = qobject_cast<TaskInfo *>(sender());
taskInfo->processResult(m_fortManager, success); taskInfo->processResult(m_fortManager, success);
saveSettings(m_fortManager->settings(), saveSettings();
m_fortManager->confManager());
emit taskFinished(taskInfo);
} }
void TaskManager::runExpiredTasks() void TaskManager::runExpiredTasks()

View File

@ -21,6 +21,8 @@ public:
QObject *parent = nullptr); QObject *parent = nullptr);
FortManager *fortManager() const { return m_fortManager; } FortManager *fortManager() const { return m_fortManager; }
FortSettings *settings() const;
ConfManager *confManager() const;
TaskInfoUpdateChecker *taskInfoUpdateChecker() const { return m_taskInfoUpdateChecker; } TaskInfoUpdateChecker *taskInfoUpdateChecker() const { return m_taskInfoUpdateChecker; }
@ -29,11 +31,15 @@ public:
signals: signals:
void taskInfosChanged(); void taskInfosChanged();
void taskStarted(TaskInfo *taskInfo);
void taskFinished(TaskInfo *taskInfo);
public slots: public slots:
void loadSettings(const FortSettings *fortSettings, ConfManager *confManager); void loadSettings();
bool saveSettings(FortSettings *fortSettings, ConfManager *confManager); bool saveSettings();
private slots: private slots:
void handleTaskStarted();
void handleTaskFinished(bool success); void handleTaskFinished(bool success);
void runExpiredTasks(); void runExpiredTasks();

View File

@ -62,6 +62,14 @@ void StringListModel::replace(const QString &text, int row)
emit dataChanged(modelIndex, modelIndex); emit dataChanged(modelIndex, modelIndex);
} }
void StringListModel::refresh()
{
const auto firstCell = index(0, 0);
const auto lastCell = index(rowCount() - 1, 0);
emit dataChanged(firstCell, lastCell);
}
void StringListModel::removeRow(int row) void StringListModel::removeRow(int row)
{ {
m_list.removeAt(row); m_list.removeAt(row);

View File

@ -30,6 +30,7 @@ public slots:
beginResetModel(); beginResetModel();
endResetModel(); endResetModel();
} }
void refresh();
protected: protected:
void removeRow(int row); void removeRow(int row);

View File

@ -0,0 +1,47 @@
#include "tableitemmodel.h"
TableItemModel::TableItemModel(QObject *parent) :
QAbstractItemModel(parent)
{
}
QModelIndex TableItemModel::index(int row, int column, const QModelIndex &parent) const
{
return hasIndex(row, column, parent)
? createIndex(row, column) : QModelIndex();
}
QModelIndex TableItemModel::parent(const QModelIndex &child) const
{
Q_UNUSED(child)
return {};
}
QModelIndex TableItemModel::sibling(int row, int column, const QModelIndex &index) const
{
Q_UNUSED(index)
return this->index(row, column);
}
bool TableItemModel::hasChildren(const QModelIndex &parent) const
{
return !parent.isValid() && rowCount() > 0;
}
Qt::ItemFlags TableItemModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return Qt::NoItemFlags;
return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemNeverHasChildren;
}
void TableItemModel::refresh()
{
const auto firstCell = index(0, 0);
const auto lastCell = index(rowCount() - 1, columnCount(firstCell) - 1);
emit dataChanged(firstCell, lastCell);
}

View File

@ -0,0 +1,31 @@
#ifndef TABLEITEMMODEL_H
#define TABLEITEMMODEL_H
#include <QAbstractItemModel>
class TableItemModel : public QAbstractItemModel
{
Q_OBJECT
public:
explicit TableItemModel(QObject *parent = nullptr);
QModelIndex index(int row, int column,
const QModelIndex &parent = QModelIndex()) const override;
QModelIndex parent(const QModelIndex &child) const override;
QModelIndex sibling(int row, int column,
const QModelIndex &index) const override;
bool hasChildren(const QModelIndex &parent = QModelIndex()) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
public slots:
void reset() {
beginResetModel();
endResetModel();
}
void refresh();
};
#endif // TABLEITEMMODEL_H