Plasma-workspace

jobsmodel.cpp
1/*
2 SPDX-FileCopyrightText: 2019 Kai Uwe Broulik <kde@privat.broulik.de>
3
4 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5*/
6
7#include "jobsmodel.h"
8#include "jobsmodel_p.h"
9
10#include "utils_p.h"
11
12#include <QDebug>
13
14#include <KJob>
15#include <KLocalizedString>
16
17#include "job.h"
18#include "job_p.h"
19
20using namespace NotificationManager;
21
22JobsModel::JobsModel()
23 : QAbstractListModel(nullptr)
24 , d(new JobsModelPrivate(this))
25{
26 connect(d, &JobsModelPrivate::jobViewAboutToBeAdded, this, [this](int row, Job *job) {
27 Q_UNUSED(job);
28 beginInsertRows(QModelIndex(), row, row);
29 });
30 connect(d, &JobsModelPrivate::jobViewAdded, this, [this](int row) {
31 Q_UNUSED(row);
32 endInsertRows();
33 });
34
35 connect(d, &JobsModelPrivate::jobViewAboutToBeRemoved, this, [this](int row) {
36 beginRemoveRows(QModelIndex(), row, row);
37 });
38 connect(d, &JobsModelPrivate::jobViewRemoved, this, [this](int row) {
39 Q_UNUSED(row);
40 endRemoveRows();
41 });
42
43 connect(d, &JobsModelPrivate::jobViewChanged, this, [this](int row, Job *job, const QList<int> &roles) {
44 Q_UNUSED(job);
45 const QModelIndex idx = index(row, 0);
46 Q_EMIT dataChanged(idx, idx, roles);
47 });
48
49 connect(d, &JobsModelPrivate::serviceOwnershipLost, this, &JobsModel::serviceOwnershipLost);
50}
51
52JobsModel::~JobsModel() = default;
53
54JobsModel::Ptr JobsModel::createJobsModel()
55{
56 static std::weak_ptr<JobsModel> s_instance;
57 if (s_instance.expired()) {
58 std::shared_ptr<JobsModel> ptr(new JobsModel());
59 s_instance = ptr;
60 return ptr;
61 }
62 return s_instance.lock();
63}
64
66{
67 return d->init();
68}
69
71{
72 return d->m_valid;
73}
74
75QVariant JobsModel::data(const QModelIndex &index, int role) const
76{
77 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid)) {
78 return QVariant();
79 }
80
81 Job *job = d->m_jobViews.at(index.row());
82
83 switch (role) {
85 return job->id();
88 // basically when it started
90 if (job->created().isValid()) {
91 return job->created();
92 }
93 break;
94 // basically when it finished
96 if (job->updated().isValid()) {
97 return job->updated();
98 }
99 break;
101 return job->summary();
103 return job->text();
105 return i18nc("@info %1 notification body %2 job name", "%1 from %2", job->text(), job->applicationName());
107 return job->desktopEntry();
109 return job->applicationName();
111 return job->applicationIconName();
112
114 return job->state();
116 return job->percentage();
118 return job->error();
120 return job->suspendable();
122 return job->killable();
124 return QVariant::fromValue(job);
125
126 // successfully finished jobs timeout like a regular notifiation
127 // whereas running or error'd jobs are persistent
129 return job->state() == Notifications::JobStateStopped && !job->error() ? -1 : 0;
131 return job->state() == Notifications::JobStateStopped;
132
134 return false;
136 return job->expired();
138 return job->dismissed();
139
140 // A job is usually either a long lasting operation you're aware about
141 // or a quick job you don't care about.
142 // When it's running, it's there, when it failed, it's persistent.
143 // There's hardly a reason why it should show up as "unread".
145 return true;
146 }
147
148 return QVariant();
149}
150
151bool JobsModel::setData(const QModelIndex &index, const QVariant &value, int role)
152{
153 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid)) {
154 return false;
155 }
156
157 Job *job = d->m_jobViews.at(index.row());
158
159 switch (role) {
161 if (value.toBool() != job->dismissed()) {
162 job->setDismissed(value.toBool());
163 return true;
164 }
165 break;
166 }
167
168 return false;
169}
170
171int JobsModel::rowCount(const QModelIndex &parent) const
172{
173 if (parent.isValid()) {
174 return 0;
175 }
176
177 return d->m_jobViews.count();
178}
179
180QHash<int, QByteArray> JobsModel::roleNames() const
181{
182 return Utils::roleNames();
183}
184
186{
187 if (checkIndex(idx, QAbstractItemModel::CheckIndexOption::IndexIsValid)) {
188 d->removeAt(idx.row());
189 }
190}
191
192void JobsModel::expire(const QModelIndex &idx)
193{
194 if (checkIndex(idx, QAbstractItemModel::CheckIndexOption::IndexIsValid)) {
195 d->m_jobViews.at(idx.row())->setExpired(true);
196 }
197}
198
200{
201 if (checkIndex(idx, QAbstractItemModel::CheckIndexOption::IndexIsValid)) {
202 d->m_jobViews.at(idx.row())->suspend();
203 }
204}
205
207{
208 if (checkIndex(idx, QAbstractItemModel::CheckIndexOption::IndexIsValid)) {
209 d->m_jobViews.at(idx.row())->resume();
210 }
211}
212
214{
215 if (checkIndex(idx, QAbstractItemModel::CheckIndexOption::IndexIsValid)) {
216 d->m_jobViews.at(idx.row())->kill();
217 }
218}
219
220void JobsModel::clear(Notifications::ClearFlags flags)
221{
222 if (d->m_jobViews.isEmpty()) {
223 return;
224 }
225
226 for (int i = d->m_jobViews.count() - 1; i >= 0; --i) {
227 Job *job = d->m_jobViews.at(i);
228
229 bool clear = (flags.testFlag(Notifications::ClearExpired) && job->expired());
230
231 // Compared to notifications, the number of jobs is typically small
232 // so for simplicity we can just delete one item at a time
233 if (clear) {
234 d->removeAt(i);
235 }
236 }
237}
Represents a single job.
Definition job.h:32
QString text
User-friendly compact description text of the job, for example "42 of 1337 files to "~/some/folder",...
Definition job.h:46
bool suspendable
Whether the job can be suspended.
Definition job.h:78
int error
The error code of the job failure.
Definition job.h:71
QString desktopEntry
The desktop entry of the application owning the job, e.g.
Definition job.h:51
QString applicationIconName
The icon name of the application owning the job, e.g.
Definition job.h:59
QML_ELEMENTQString summary
The job infoMessage, e.g.
Definition job.h:40
bool killable
Whether the job can be aborted.
Definition job.h:84
Notifications::JobState state
The state the job is currently in.
Definition job.h:63
QString applicationName
The user-visible name of the application owning the job, e.g.
Definition job.h:55
int percentage
The total percentage (0-100) of job completion.
Definition job.h:67
A model used for listing Job.
Definition jobsmodel.h:23
void kill(const QModelIndex &idx)
Kill a job.
void resume(const QModelIndex &idx)
Resume a job.
bool init()
Registers the JobView service on DBus.
Definition jobsmodel.cpp:65
bool isValid() const
Whether the notification service could be registered.
Definition jobsmodel.cpp:70
void suspend(const QModelIndex &idx)
Suspend a job.
void close(const QModelIndex &idx)
Close a job.
@ JobType
This item represents an application job.
@ JobStateStopped
The job is stopped. It has either finished (error is 0) or failed (error is not 0)
@ ApplicationNameRole
The user-visible name of the application (e.g. Spectacle)
@ ConfigurableRole
Whether the notification can be configured because a desktopEntry or notifyRcName is known,...
@ SummaryRole
The notification summary.
@ UpdatedRole
When the notification was last updated, invalid when it hasn't been updated.
@ ReadRole
Whether the notification got read by the user.
@ BodyRole
The notification body text.
@ JobDetailsRole
A pointer to a Job item itself containing more detailed information about the job.
@ SuspendableRole
Whether the job can be suspended.
@ DismissedRole
The notification got temporarily hidden by the user but could still be interacted with.
@ JobStateRole
The state of the job, either JobStateJopped, JobStateSuspended, or JobStateRunning.
@ IdRole
A notification identifier. This can be uint notification ID or string application job source.
@ DesktopEntryRole
The desktop entry (without .desktop suffix, e.g. org.kde.spectacle) of the application that sent the ...
@ ApplicationIconNameRole
The icon name of the application.
@ KillableRole
Whether the job can be killed/canceled.
@ ExpiredRole
The notification timed out and closed. Actions on it cannot be invoked anymore.
@ JobErrorRole
The error id of the job, zero in case of no error.
@ CreatedRole
When the notification was first created.
@ TimeoutRole
The timeout for the notification in milliseconds.
@ ClosableRole
Whether the item can be closed. Notifications are always closable, jobs are only when in JobStateStop...
@ TypeRole
The type of model entry, either NotificationType or JobType.
@ PercentageRole
The percentage of the job. Use jobsPercentage to get a global percentage for all jobs.
QString i18nc(const char *context, const char *text, const TYPE &arg...)
bool checkIndex(const QModelIndex &index, CheckIndexOptions options) const const
virtual Qt::ItemFlags flags(const QModelIndex &index) const const override
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const override
bool isValid() const const
int row() const const
QObject * parent() const const
AccessibleDescriptionRole
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QVariant fromValue(T &&value)
bool toBool() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:17:42 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.