diff --git a/kuiserver/jobview.cpp b/kuiserver/jobview.cpp index 01715959d..e29061bdf 100644 --- a/kuiserver/jobview.cpp +++ b/kuiserver/jobview.cpp @@ -1,460 +1,460 @@ /***************************************************************************** * Copyright (C) 2009 Shaun Reich * * Copyright (C) 2006-2008 Rafael Fernández López * * Copyright (C) 2001 George Staikos * * Copyright (C) 2000 Matej Koss * * Copyright (C) 2000 David Faure * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of * * the License, or (at your option) any later version. * * * * 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 General Public License * * along with this program. If not, see . * *****************************************************************************/ #include "uiserver.h" #include "jobviewadaptor.h" #include "jobview_interface.h" #include "requestviewcallwatcher.h" #include #include #include #include JobView::JobView(uint jobId, QObject *parent) : QObject(parent), m_capabilities(-1), m_percent(-1), m_error(KJob::NoError), m_totalAmount(0), m_processAmount(0), m_jobId(jobId), m_state(Running), m_isTerminated(false), m_currentPendingCalls(0) { new JobViewV2Adaptor(this); m_objectPath.setPath(QStringLiteral("/JobViewServer/JobView_%1").arg(m_jobId)); QDBusConnection::sessionBus().registerObject(m_objectPath.path(), this); } JobView::~JobView() { } void JobView::terminate(const QString &errorMessage) { QDBusConnection::sessionBus().unregisterObject(m_objectPath.path(), QDBusConnection::UnregisterTree); typedef QPair iFacePair; foreach(const iFacePair &pair, m_objectPaths) { qCDebug(KUISERVER) << "making async call of terminate for: " << pair.first; pair.second->asyncCall(QLatin1String("setError"), m_error); pair.second->asyncCall(QLatin1String("terminate"), errorMessage); } m_errorText = errorMessage; if (m_currentPendingCalls < 1) { // if hit it means a job exists for *something* but can't be terminated properly // because the async call to create the job didn't come back fast enough. // (thus addJobContact wasn't called before this was hit). // Q_ASSERT(!m_objectPaths.isEmpty()); // no more calls waiting. Lets mark ourselves for deletion. emit finished(this); } m_isTerminated = true; } void JobView::requestSuspend() { emit suspendRequested(); } void JobView::requestResume() { emit resumeRequested(); } void JobView::requestCancel() { emit cancelRequested(); } void JobView::setSuspended(bool suspended) { typedef QPair iFacePair; foreach(const iFacePair &pair, m_objectPaths) { pair.second->asyncCall(QLatin1String("setSuspended"), suspended); } m_state = suspended ? Suspended : Running; emit changed(m_jobId); } uint JobView::state() const { return m_state; } void JobView::setTotalAmount(qulonglong amount, const QString &unit) { typedef QPair iFacePair; foreach(const iFacePair &pair, m_objectPaths) { pair.second->asyncCall(QLatin1String("setTotalAmount"), amount, unit); } m_totalAmount = amount; m_totalUnit = unit; if (unit == QLatin1String("bytes")) { m_sizeTotal = amount ? KFormat().formatByteSize(amount) : QString(); } else if (unit == QLatin1String("files")) { m_sizeTotal = amount ? i18np("%1 file", "%1 files", amount) : QString(); } else if (unit == QLatin1String("dirs")) { m_sizeTotal = amount ? i18np("%1 folder", "%1 folders", amount) : QString(); } emit changed(m_jobId); } QString JobView::sizeTotal() const { return m_sizeTotal; } void JobView::setProcessedAmount(qulonglong amount, const QString &unit) { typedef QPair iFacePair; foreach(const iFacePair &pair, m_objectPaths) { pair.second->asyncCall(QLatin1String("setProcessedAmount"), amount, unit); } m_processAmount = amount; m_processUnit = unit; if (unit == QLatin1String("bytes")) { m_sizeProcessed = amount ? KFormat().formatByteSize(amount) : QString(); } else if (unit == QLatin1String("files")) { m_sizeProcessed = amount ? i18np("%1 file", "%1 files", amount) : QString(); } else if (unit == QLatin1String("dirs")) { m_sizeProcessed = amount ? i18np("%1 folder", "%1 folders", amount) : QString(); } emit changed(m_jobId); } QString JobView::sizeProcessed() const { return m_sizeProcessed; } void JobView::setPercent(uint value) { typedef QPair iFacePair; foreach(const iFacePair &pair, m_objectPaths) { pair.second->asyncCall(QLatin1String("setPercent"), value); } m_percent = value; emit changed(m_jobId); } uint JobView::percent() const { return m_percent; } void JobView::setSpeed(qulonglong bytesPerSecond) { typedef QPair iFacePair; foreach(const iFacePair &pair, m_objectPaths) { pair.second->asyncCall(QLatin1String("setSpeed"), bytesPerSecond); } m_speed = bytesPerSecond ? KFormat().formatByteSize(bytesPerSecond) : QString(); emit changed(m_jobId); } QString JobView::speed() const { return m_speed; } void JobView::setInfoMessage(const QString &infoMessage) { typedef QPair iFacePair; foreach(const iFacePair &pair, m_objectPaths) { pair.second->asyncCall(QLatin1String("setInfoMessage"), infoMessage); } m_infoMessage = infoMessage; emit changed(m_jobId); } QString JobView::infoMessage() const { return m_infoMessage; } bool JobView::setDescriptionField(uint number, const QString &name, const QString &value) { typedef QPair iFacePair; foreach(const iFacePair &pair, m_objectPaths) { pair.second->asyncCall(QLatin1String("setDescriptionField"), number, name, value); } if (m_descFields.contains(number)) { m_descFields[number].first = name; m_descFields[number].second = value; } else { QPair tempDescField(name, value); m_descFields.insert(number, tempDescField); } emit changed(m_jobId); return true; } void JobView::clearDescriptionField(uint number) { typedef QPair iFacePair; foreach(const iFacePair &pair, m_objectPaths) { pair.second->asyncCall(QLatin1String("clearDescriptionField"), number); } if (m_descFields.contains(number)) { m_descFields.remove(number); } emit changed(m_jobId); } void JobView::setAppName(const QString &appName) { typedef QPair iFacePair; foreach(const iFacePair &pair, m_objectPaths) { pair.second->asyncCall(QLatin1String("setAppName"), appName); } m_applicationName = appName; } QString JobView::appName() const { return m_applicationName; } void JobView::setAppIconName(const QString &appIconName) { typedef QPair iFacePair; foreach(const iFacePair &pair, m_objectPaths) { pair.second->asyncCall(QLatin1String("setAppIconName"), appIconName); } m_appIconName = appIconName; } QString JobView::appIconName() const { return m_appIconName; } void JobView::setCapabilities(int capabilities) { typedef QPair iFacePair; foreach(const iFacePair &pair, m_objectPaths) { pair.second->asyncCall(QLatin1String("setCapabilities"), capabilities); } m_capabilities = capabilities; } int JobView::capabilities() const { return m_capabilities; } void JobView::setError(uint errorCode) { m_error = errorCode; } uint JobView::error() const { return m_error; } QString JobView::errorText() const { return m_errorText; } uint JobView::jobId() const { return m_jobId; } QDBusObjectPath JobView::objectPath() const { return m_objectPath; } void JobView::setDestUrl(const QDBusVariant &destUrl) { - for (const auto &pair : qAsConst(m_objectPaths)) { + Q_FOREACH (const auto &pair, m_objectPaths) { // if we just pass destUrl.variant() Qt will unwrap it into a string and // the method signature "s" won't match the expected "v" on the receiver's side pair.second->asyncCall(QLatin1String("setDestUrl"), QVariant::fromValue(destUrl)); } m_destUrl = destUrl.variant(); emit destUrlSet(); } QVariant JobView::destUrl() const { return m_destUrl; } void JobView::addJobContact(const QString& objectPath, const QString& address) { org::kde::JobViewV2 *client = new org::kde::JobViewV2(address, objectPath, QDBusConnection::sessionBus()); QPair pair(objectPath, client); //propagate any request signals from the client's job, up to us, then to the parent KJob //otherwise e.g. the pause button on plasma's tray would be broken. connect(client, &org::kde::JobViewV2::suspendRequested, this, &JobView::suspendRequested); connect(client, &org::kde::JobViewV2::resumeRequested, this, &JobView::resumeRequested); connect(client, &org::kde::JobViewV2::cancelRequested, this, &JobView::cancelRequested); Q_ASSERT(!m_objectPaths.contains(address)); m_objectPaths.insert(address, pair); //If the job already has any information, send it to the contact if (m_capabilities > -1) { client->asyncCall(QLatin1String("setCapabilities"), m_capabilities); } if (!m_applicationName.isEmpty()) { client->asyncCall(QLatin1String("setAppName"), m_applicationName); } if (!m_appIconName.isEmpty()) { client->asyncCall(QLatin1String("setAppIconName"), m_appIconName); } if (m_percent > -1) { client->asyncCall(QLatin1String("setPercent"), m_percent); } if (!m_infoMessage.isEmpty()) { client->asyncCall(QLatin1String("setInfoMessage"), m_infoMessage); } if (!m_descFields.isEmpty()) { QHashIterator > i(m_descFields); while (i.hasNext()) { i.next(); client->asyncCall(QLatin1String("setDescriptionField"), i.key(), i.value().first, i.value().second); } } if (m_state == Suspended) { client->asyncCall(QLatin1String("setSuspended"), true); } if (m_processAmount > 0) { client->asyncCall(QLatin1String("setProcessedAmount"), m_processAmount, m_processUnit); } if (m_totalAmount > 0) { client->asyncCall(QLatin1String("setTotalAmount"), m_totalAmount, m_totalUnit); } if (m_destUrl.isValid()) { client->asyncCall(QLatin1String("setDestUrl"), m_destUrl); } } QStringList JobView::jobContacts() { QStringList output; QHash >::const_iterator it = m_objectPaths.constBegin(); for (; it != m_objectPaths.constEnd(); ++it) { //for debug purposes only output.append("service name of the interface: " + it.key() + "; objectPath for the interface: " + it.value().first); } return output; } void JobView::pendingCallStarted() { ++m_currentPendingCalls; } void JobView::pendingCallFinished(RequestViewCallWatcher* watcher) { QDBusPendingReply reply = *watcher; QString address = watcher->service(); if (reply.isError()) { // this happens if plasma crashed meanwhile qWarning() << "got error from" << address << ":" << reply.error(); qWarning() << "app name was" << watcher->jobView()->appName(); return; } // note: this is the *remote* jobview objectpath, not the kuiserver one. QDBusObjectPath objectPath = reply.argumentAt<0>(); Q_ASSERT(reply.isValid()); --m_currentPendingCalls; if (m_isTerminated) { // do basically the same as terminate() except only for service // since this one missed out. org::kde::JobViewV2 *client = new org::kde::JobViewV2(address, objectPath.path(), QDBusConnection::sessionBus()); qCDebug(KUISERVER) << "making async terminate call to objectPath: " << objectPath.path(); qCDebug(KUISERVER) << "this was because a pending call was finished, but the job was already terminated before it returned."; qCDebug(KUISERVER) << "current pending calls left: " << m_currentPendingCalls; // forcibly set the percent (should be 100). Since the job missed out on that too. client->asyncCall(QLatin1String("setPercent"), m_percent); client->asyncCall(QLatin1String("setError"), m_error); client->asyncCall(QLatin1String("terminate"), m_errorText); if (m_currentPendingCalls < 1) { qCDebug(KUISERVER) << "no more async calls left pending..emitting finished so we can have ourselves deleted."; emit finished(this); } } else { // add this job contact because we are _not_ just terminating here. // we'll need it for regular things like speed changes, etc. qCDebug(KUISERVER) << "adding job contact for address: " << address << " objectPath: " << objectPath.path(); addJobContact(objectPath.path(), address); } } void JobView::serviceDropped(const QString &address) { m_objectPaths.remove(address); --m_currentPendingCalls; }