mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
238 lines
6.3 KiB
238 lines
6.3 KiB
/* |
|
SPDX-FileCopyrightText: 2019 Kai Uwe Broulik <[email protected]> |
|
|
|
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL |
|
*/ |
|
|
|
#include "jobsmodel.h" |
|
#include "jobsmodel_p.h" |
|
|
|
#include "utils_p.h" |
|
|
|
#include <QDebug> |
|
|
|
#include <KJob> |
|
|
|
#include <Plasma/DataEngine> |
|
#include <Plasma/DataEngineConsumer> |
|
#include <Plasma/ServiceJob> |
|
|
|
#include "job.h" |
|
#include "job_p.h" |
|
|
|
using namespace NotificationManager; |
|
|
|
JobsModel::JobsModel() |
|
: QAbstractListModel(nullptr) |
|
, d(new JobsModelPrivate(this)) |
|
{ |
|
connect(d, &JobsModelPrivate::jobViewAboutToBeAdded, this, [this](int row, Job *job) { |
|
Q_UNUSED(job); |
|
beginInsertRows(QModelIndex(), row, row); |
|
}); |
|
connect(d, &JobsModelPrivate::jobViewAdded, this, [this](int row) { |
|
Q_UNUSED(row); |
|
endInsertRows(); |
|
}); |
|
|
|
connect(d, &JobsModelPrivate::jobViewAboutToBeRemoved, this, [this](int row) { |
|
beginRemoveRows(QModelIndex(), row, row); |
|
}); |
|
connect(d, &JobsModelPrivate::jobViewRemoved, this, [this](int row) { |
|
Q_UNUSED(row); |
|
endRemoveRows(); |
|
}); |
|
|
|
connect(d, &JobsModelPrivate::jobViewChanged, this, [this](int row, Job *job, const QVector<int> &roles) { |
|
Q_UNUSED(job); |
|
const QModelIndex idx = index(row, 0); |
|
Q_EMIT dataChanged(idx, idx, roles); |
|
}); |
|
|
|
connect(d, &JobsModelPrivate::serviceOwnershipLost, this, &JobsModel::serviceOwnershipLost); |
|
} |
|
|
|
JobsModel::~JobsModel() = default; |
|
|
|
JobsModel::Ptr JobsModel::createJobsModel() |
|
{ |
|
static QWeakPointer<JobsModel> s_instance; |
|
if (!s_instance) { |
|
QSharedPointer<JobsModel> ptr(new JobsModel()); |
|
s_instance = ptr.toWeakRef(); |
|
return ptr; |
|
} |
|
return s_instance.toStrongRef(); |
|
} |
|
|
|
bool JobsModel::init() |
|
{ |
|
return d->init(); |
|
} |
|
|
|
bool JobsModel::isValid() const |
|
{ |
|
return d->m_valid; |
|
} |
|
|
|
QVariant JobsModel::data(const QModelIndex &index, int role) const |
|
{ |
|
if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid)) { |
|
return QVariant(); |
|
} |
|
|
|
Job *job = d->m_jobViews.at(index.row()); |
|
|
|
switch (role) { |
|
case Notifications::IdRole: |
|
return job->id(); |
|
case Notifications::TypeRole: |
|
return Notifications::JobType; |
|
// basically when it started |
|
case Notifications::CreatedRole: |
|
if (job->created().isValid()) { |
|
return job->created(); |
|
} |
|
break; |
|
// basically when it finished |
|
case Notifications::UpdatedRole: |
|
if (job->updated().isValid()) { |
|
return job->updated(); |
|
} |
|
break; |
|
case Notifications::SummaryRole: |
|
return job->summary(); |
|
case Notifications::BodyRole: |
|
return job->text(); |
|
case Notifications::DesktopEntryRole: |
|
return job->desktopEntry(); |
|
case Notifications::ApplicationNameRole: |
|
return job->applicationName(); |
|
case Notifications::ApplicationIconNameRole: |
|
return job->applicationIconName(); |
|
|
|
case Notifications::JobStateRole: |
|
return job->state(); |
|
case Notifications::PercentageRole: |
|
return job->percentage(); |
|
case Notifications::JobErrorRole: |
|
return job->error(); |
|
case Notifications::SuspendableRole: |
|
return job->suspendable(); |
|
case Notifications::KillableRole: |
|
return job->killable(); |
|
case Notifications::JobDetailsRole: |
|
return QVariant::fromValue(job); |
|
|
|
// successfully finished jobs timeout like a regular notifiation |
|
// whereas running or error'd jobs are persistent |
|
case Notifications::TimeoutRole: |
|
return job->state() == Notifications::JobStateStopped && !job->error() ? -1 : 0; |
|
case Notifications::ClosableRole: |
|
return job->state() == Notifications::JobStateStopped; |
|
|
|
case Notifications::ConfigurableRole: |
|
return false; |
|
case Notifications::ExpiredRole: |
|
return job->expired(); |
|
case Notifications::DismissedRole: |
|
return job->dismissed(); |
|
|
|
// A job is usually either a long lasting operation you're aware about |
|
// or a quick job you don't care about. |
|
// When it's running, it's there, when it failed, it's persistent. |
|
// There's hardly a reason why it should show up as "unread". |
|
case Notifications::ReadRole: |
|
return true; |
|
} |
|
|
|
return QVariant(); |
|
} |
|
|
|
bool JobsModel::setData(const QModelIndex &index, const QVariant &value, int role) |
|
{ |
|
if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid)) { |
|
return false; |
|
} |
|
|
|
Job *job = d->m_jobViews.at(index.row()); |
|
|
|
switch (role) { |
|
case Notifications::DismissedRole: |
|
if (value.toBool() != job->dismissed()) { |
|
job->setDismissed(value.toBool()); |
|
return true; |
|
} |
|
break; |
|
} |
|
|
|
return false; |
|
} |
|
|
|
int JobsModel::rowCount(const QModelIndex &parent) const |
|
{ |
|
if (parent.isValid()) { |
|
return 0; |
|
} |
|
|
|
return d->m_jobViews.count(); |
|
} |
|
|
|
QHash<int, QByteArray> JobsModel::roleNames() const |
|
{ |
|
return Utils::roleNames(); |
|
} |
|
|
|
void JobsModel::close(const QModelIndex &idx) |
|
{ |
|
if (checkIndex(idx, QAbstractItemModel::CheckIndexOption::IndexIsValid)) { |
|
d->removeAt(idx.row()); |
|
} |
|
} |
|
|
|
void JobsModel::expire(const QModelIndex &idx) |
|
{ |
|
if (checkIndex(idx, QAbstractItemModel::CheckIndexOption::IndexIsValid)) { |
|
d->m_jobViews.at(idx.row())->setExpired(true); |
|
} |
|
} |
|
|
|
void JobsModel::suspend(const QModelIndex &idx) |
|
{ |
|
if (checkIndex(idx, QAbstractItemModel::CheckIndexOption::IndexIsValid)) { |
|
d->m_jobViews.at(idx.row())->suspend(); |
|
} |
|
} |
|
|
|
void JobsModel::resume(const QModelIndex &idx) |
|
{ |
|
if (checkIndex(idx, QAbstractItemModel::CheckIndexOption::IndexIsValid)) { |
|
d->m_jobViews.at(idx.row())->resume(); |
|
} |
|
} |
|
|
|
void JobsModel::kill(const QModelIndex &idx) |
|
{ |
|
if (checkIndex(idx, QAbstractItemModel::CheckIndexOption::IndexIsValid)) { |
|
d->m_jobViews.at(idx.row())->kill(); |
|
} |
|
} |
|
|
|
void JobsModel::clear(Notifications::ClearFlags flags) |
|
{ |
|
if (d->m_jobViews.isEmpty()) { |
|
return; |
|
} |
|
|
|
for (int i = d->m_jobViews.count() - 1; i >= 0; --i) { |
|
Job *job = d->m_jobViews.at(i); |
|
|
|
bool clear = (flags.testFlag(Notifications::ClearExpired) && job->expired()); |
|
|
|
// Compared to notifications, the number of jobs is typically small |
|
// so for simplicity we can just delete one item at a time |
|
if (clear) { |
|
d->removeAt(i); |
|
} |
|
} |
|
}
|
|
|