kde-workspace/plasma/dataengines/applicationjobs/kuiserverengine.cpp
Ivailo Monev 42bd88d0d2 kuiserver: announce destination URL changes to job clients
to fix the plasma job notification actions (see the previous commit), also
changing the destination URL type to QString because it is such (see
kdelibs/kio/kio/copyjob.cpp and kdelibs/kio/kio/job.cpp) and the
QVariant/QDBusVariant conversion is redundant

requires changes to the job tracker interface in kdelibs aswell.. see
kdelibs/kdeui/jobs/kuiserverjobtracker.cpp

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
2023-06-27 03:26:20 +03:00

383 lines
9.9 KiB
C++

/*
* Copyright © 2008 Rob Scheepmaker <r.scheepmaker@student.utwente.nl>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License version 2 as
* published by the Free Software Foundation
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "jobviewadaptor.h"
#include "jobviewserveradaptor.h"
#include "kuiserverengine.h"
#include "jobcontrol.h"
#include <QDBusConnection>
#include <QTimerEvent>
#include <QDebug>
#include <KJob>
#include <Plasma/DataEngine>
uint JobView::s_jobId = 0;
static const int UPDATE_INTERVAL = 100;
JobView::JobView(QObject* parent)
: Plasma::DataContainer(parent),
m_capabilities(-1),
m_percent(0),
m_speed(0),
m_totalBytes(0),
m_processedBytes(0),
m_state(UnknownState),
m_bytesUnitId(-1),
m_unitId(0)
{
m_jobId = ++s_jobId;
setObjectName(QString("Job %1").arg(s_jobId));
new JobViewAdaptor(this);
m_objectPath.setPath(QString("/DataEngine/applicationjobs/JobView_%1").arg(m_jobId));
QDBusConnection::sessionBus().registerObject(m_objectPath.path(), this);
setSuspended(false);
}
JobView::~JobView()
{
QDBusConnection::sessionBus().unregisterObject(m_objectPath.path(), QDBusConnection::UnregisterTree);
}
uint JobView::jobId() const
{
return m_jobId;
}
void JobView::scheduleUpdate()
{
if (!m_updateTimer.isActive()) {
m_updateTimer.start(UPDATE_INTERVAL, this);
}
}
void JobView::timerEvent(QTimerEvent *event)
{
if (event->timerId() == m_updateTimer.timerId()) {
m_updateTimer.stop();
checkForUpdate();
if (m_state == Stopped) {
emit becameUnused(objectName());
}
} else {
Plasma::DataContainer::timerEvent(event);
}
}
void JobView::terminate(const QString &errorMessage)
{
setData("error", errorMessage);
QTimer::singleShot(0, this, SLOT(finished()));
}
void JobView::finished()
{
if (m_state != Stopped) {
m_state = Stopped;
setData("state", "stopped");
setData("speed", QVariant());
setData("numericSpeed", QVariant());
scheduleUpdate();
}
}
JobView::State JobView::state()
{
return m_state;
}
void JobView::setSuspended(bool suspended)
{
if (suspended) {
if (m_state != Suspended) {
m_state = Suspended;
setData("state", "suspended");
setData("speed", QVariant());
setData("numericSpeed", QVariant());
scheduleUpdate();
}
} else if (m_state != Running) {
m_state = Running;
setData("state", "running");
setData("speed", speedString());
setData("numericSpeed", m_speed);
scheduleUpdate();
}
}
int JobView::unitId(const QString &unit)
{
int id = 0;
if (m_unitMap.contains(unit)) {
id = m_unitMap.value(unit);
} else {
id = m_unitId;
setData(QString("totalUnit%1").arg(id), unit);
setData(QString("totalAmount%1").arg(id), 0);
setData(QString("processedUnit%1").arg(id), unit);
setData(QString("processedAmount%1").arg(id), 0);
m_unitMap.insert(unit, m_unitId);
if (unit == "bytes") {
m_bytesUnitId = id;
}
++m_unitId;
scheduleUpdate();
}
return id;
}
void JobView::updateEta()
{
if (m_speed < 1) {
setData("eta", 0);
return;
}
if (m_totalBytes < 1) {
setData("eta", 0);
return;
}
const qlonglong remaining = 1000 * (m_totalBytes - m_processedBytes);
setData("eta", remaining / m_speed);
}
void JobView::setTotalAmount(qlonglong amount, const QString &unit)
{
const int id = unitId(unit);
const QString amountString = QString("totalAmount%1").arg(id);
const qlonglong prevTotal = data().value(amountString).toLongLong();
if (prevTotal != amount) {
if (id == m_bytesUnitId) {
m_totalBytes = amount;
updateEta();
}
setData(amountString, amount);
scheduleUpdate();
}
}
void JobView::setProcessedAmount(qlonglong amount, const QString &unit)
{
const int id = unitId(unit);
const QString processedString = QString("processedAmount%1").arg(id);
const qlonglong prevTotal = data().value(processedString).toLongLong();
if (prevTotal != amount) {
if (id == m_bytesUnitId) {
m_processedBytes = amount;
updateEta();
}
setData(processedString, amount);
scheduleUpdate();
}
}
void JobView::setDestUrl(const QString &destUrl)
{
if (m_destUrl != destUrl) {
setData("destUrl", destUrl);
scheduleUpdate();
}
}
void JobView::setPercent(uint percent)
{
if (m_percent != percent) {
m_percent = percent;
setData("percentage", m_percent);
scheduleUpdate();
}
}
void JobView::setSpeed(qlonglong bytesPerSecond)
{
if (m_speed != bytesPerSecond) {
m_speed = bytesPerSecond;
setData("speed", speedString());
setData("numericSpeed", m_speed);
if (m_bytesUnitId > -1) {
updateEta();
}
scheduleUpdate();
}
}
QString JobView::speedString() const
{
return i18nc("Bytes per second", "%1/s", KGlobal::locale()->formatByteSize(m_speed));
}
void JobView::setInfoMessage(const QString &infoMessage)
{
if (data().value("infoMessage") != infoMessage) {
setData("infoMessage", infoMessage);
scheduleUpdate();
}
}
bool JobView::setDescriptionField(uint number, const QString &name, const QString &value)
{
const QString labelString = QString("label%1").arg(number);
const QString labelNameString = QString("labelName%1").arg(number);
if (!data().contains(labelNameString) || data().value(labelString) != value) {
setData(labelNameString, name);
setData(labelString, value);
scheduleUpdate();
}
return true;
}
void JobView::clearDescriptionField(uint number)
{
const QString labelString = QString("label%1").arg(number);
const QString labelNameString = QString("labelName%1").arg(number);
setData(labelNameString, QVariant());
setData(labelString, QVariant());
scheduleUpdate();
}
void JobView::setAppName(const QString &appName)
{
// don't need to update, this is only set once at creation
setData("appName", appName);
}
void JobView::setAppIconName(const QString &appIconName)
{
// don't need to update, this is only set once at creation
setData("appIconName", appIconName);
}
void JobView::setCapabilities(int capabilities)
{
if (m_capabilities != uint(capabilities)) {
m_capabilities = capabilities;
setData("suspendable", m_capabilities & KJob::Suspendable);
setData("killable", m_capabilities & KJob::Killable);
scheduleUpdate();
}
}
QDBusObjectPath JobView::objectPath() const
{
return m_objectPath;
}
void JobView::requestStateChange(State state)
{
switch (state) {
case Running:
emit resumeRequested();
break;
case Suspended:
emit suspendRequested();
break;
case Stopped:
emit cancelRequested();
break;
default:
break;
}
}
KuiserverEngine::KuiserverEngine(QObject* parent, const QVariantList& args)
: Plasma::DataEngine(parent, args)
{
new JobViewServerAdaptor(this);
QDBusConnection bus = QDBusConnection::sessionBus();
bus.registerObject(QLatin1String("/DataEngine/applicationjobs/JobWatcher"), this);
setMinimumPollingInterval(500);
m_pendingJobsTimer.setSingleShot(true);
m_pendingJobsTimer.setInterval(500);
connect(&m_pendingJobsTimer, SIGNAL(timeout()), this, SLOT(processPendingJobs()));
}
KuiserverEngine::~KuiserverEngine()
{
QDBusConnection::sessionBus()
.unregisterObject(QLatin1String("/DataEngine/applicationjobs/JobWatcher"), QDBusConnection::UnregisterTree);
qDeleteAll(m_pendingJobs);
}
QDBusObjectPath KuiserverEngine::requestView(const QString &appName,
const QString &appIconName, int capabilities)
{
JobView *jobView = new JobView(this);
jobView->setAppName(appName);
jobView->setAppIconName(appIconName);
jobView->setCapabilities(capabilities);
connect(jobView, SIGNAL(becameUnused(QString)), this, SLOT(removeSource(QString)));
m_pendingJobs << jobView;
m_pendingJobsTimer.start();
return jobView->objectPath();
}
void KuiserverEngine::processPendingJobs()
{
foreach (JobView *jobView, m_pendingJobs) {
if (jobView->state() == JobView::Stopped) {
delete jobView;
} else {
addSource(jobView);
}
}
m_pendingJobs.clear();
}
Plasma::Service* KuiserverEngine::serviceForSource(const QString& source)
{
JobView *jobView = qobject_cast<JobView *>(containerForSource(source));
if (jobView) {
return new JobControl(this, jobView);
}
return DataEngine::serviceForSource(source);
}
void KuiserverEngine::init()
{
// register with the Job UI Serer to receive notifications of jobs becoming available
QDBusInterface interface("org.kde.kuiserver", "/JobViewServer"/* object to connect to */,
""/* use the default interface */, QDBusConnection::sessionBus(), this);
interface.asyncCall(QLatin1String("registerService"), QDBusConnection::sessionBus().baseService(), "/DataEngine/applicationjobs/JobWatcher");
}
K_EXPORT_PLASMA_DATAENGINE(kuiserver, KuiserverEngine)
#include "moc_kuiserverengine.cpp"