kde-workspace/kuiserver/progresslistmodel.cpp
Ivailo Monev 1e5f051548 kuiserver: compiler warning fix
Signed-off-by: Ivailo Monev <xakepa10@laimg.moc>
2019-05-15 16:49:38 +00:00

340 lines
11 KiB
C++

/*
* This file is part of the KDE project
* Copyright (C) 2009 Shaun Reich <shaun.reich@kdemail.net>
* Copyright (C) 2006-2008 Rafael Fernández López <ereslibre@kde.org>
*
* This library 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 library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "progresslistmodel.h"
#include <QDBusServiceWatcher>
#include <KDebug>
#include "jobviewserveradaptor.h"
#include "kuiserveradaptor.h"
#include "jobviewserver_interface.h"
#include "requestviewcallwatcher.h"
#include "uiserver.h"
#include <QtDBus/qdbusabstractinterface.h>
ProgressListModel::ProgressListModel(QObject *parent)
: QAbstractItemModel(parent), QDBusContext(), m_jobId(1),
m_uiServer(0)
{
m_serviceWatcher = new QDBusServiceWatcher(this);
m_serviceWatcher->setConnection(QDBusConnection::sessionBus());
m_serviceWatcher->setWatchMode(QDBusServiceWatcher::WatchForUnregistration);
connect(m_serviceWatcher, SIGNAL(serviceUnregistered(const QString &)), this, SLOT(serviceUnregistered(const QString &)));
// Register necessary services and D-Bus adaptors.
new JobViewServerAdaptor(this);
new KuiserverAdaptor(this);
QDBusConnection sessionBus = QDBusConnection::sessionBus();
if (!sessionBus.registerService(QLatin1String("org.kde.kuiserver"))) {
kDebug(7024) << "failed to register service org.kde.kuiserver. Perhaps something has already taken it?";
}
if (!sessionBus.registerService(QLatin1String("org.kde.JobViewServer"))) {
kDebug(7024) << "failed to register service JobViewServer. Perhaps something already has taken it?";
}
if (!sessionBus.registerObject(QLatin1String("/JobViewServer"), this)) {
kDebug(7024) << "failed to register object JobViewServer.";
}
/* unused
if (m_registeredServices.isEmpty() && !m_uiServer) {
m_uiServer = new UiServer(this);
}
*/
}
ProgressListModel::~ProgressListModel()
{
QDBusConnection sessionBus = QDBusConnection::sessionBus();
sessionBus.unregisterService("org.kde.JobViewServer");
sessionBus.unregisterService("org.kde.kuiserver");
qDeleteAll(m_jobViews);
qDeleteAll(m_registeredServices);
delete m_uiServer;
}
QModelIndex ProgressListModel::parent(const QModelIndex&) const
{
return QModelIndex();
}
QDBusObjectPath ProgressListModel::requestView(const QString &appName, const QString &appIconName, int capabilities)
{
return newJob(appName, appIconName, capabilities);
}
Qt::ItemFlags ProgressListModel::flags(const QModelIndex &index) const
{
Q_UNUSED(index);
return Qt::ItemIsEnabled;
}
int ProgressListModel::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return 1;
}
QVariant ProgressListModel::data(const QModelIndex &index, int role) const
{
QVariant result;
if (!index.isValid()) {
return result;
}
JobView *jobView = m_jobViews.at(index.row());
Q_ASSERT(jobView);
switch (role) {
case JobView::Capabilities:
result = jobView->capabilities();
break;
case JobView::ApplicationName:
result = jobView->appName();
break;
case JobView::Icon:
result = jobView->appIconName();
break;
case JobView::SizeTotal:
result = jobView->sizeTotal();
break;
case JobView::SizeProcessed:
result = jobView->sizeProcessed();
break;
case JobView::TimeTotal:
break;
case JobView::TimeElapsed:
break;
case JobView::Speed:
result = jobView->speed();
break;
case JobView::Percent:
result = jobView->percent();
break;
case JobView::InfoMessage:
result = jobView->infoMessage();
break;
case JobView::DescFields:
break;
case JobView::State:
result = jobView->state();
break;
case JobView::JobViewRole:
result = QVariant::fromValue<JobView*>(jobView);
break;
default:
break;
}
return result;
}
QModelIndex ProgressListModel::index(int row, int column, const QModelIndex &parent) const
{
Q_UNUSED(parent);
if (row >= m_jobViews.count() || column > 0) {
return QModelIndex();
}
return createIndex(row, column);
}
QModelIndex ProgressListModel::indexForJob(JobView *jobView) const
{
int index = m_jobViews.indexOf(jobView);
if (index == -1) {
return QModelIndex();
}
return createIndex(index, 0, jobView);
}
int ProgressListModel::rowCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : m_jobViews.count();
}
QDBusObjectPath ProgressListModel::newJob(const QString &appName, const QString &appIcon, int capabilities)
{
// Since s_jobId is an unsigned int, if we received an overflow and go back to 0,
// be sure we do not assign 0 to a valid job, 0 is reserved only for
// reporting problems.
if (!m_jobId) ++m_jobId;
JobView *newJob = new JobView(m_jobId);
++m_jobId;
QString callerService = message().service();
m_jobViewsOwners.insertMulti(callerService, newJob);
m_serviceWatcher->addWatchedService(callerService);
newJob->setAppName(appName);
newJob->setAppIconName(appIcon);
newJob->setCapabilities(capabilities);
beginInsertRows(QModelIndex(), 0, 0);
m_jobViews.prepend(newJob);
endInsertRows();
//The model will now get notified when a job changes -- so it can emit dataChanged(..)
connect(newJob, SIGNAL(changed(uint)), this, SLOT(jobChanged(uint)));
connect(newJob, SIGNAL(finished(JobView*)), this, SLOT(jobFinished(JobView*)));
connect(newJob, SIGNAL(destUrlSet()), this, SLOT(emitJobUrlsChanged()));
connect(this, SIGNAL(serviceDropped(const QString&)), newJob, SLOT(serviceDropped(const QString&)));
//Forward this new job over to existing DBus clients.
foreach(QDBusAbstractInterface* interface, m_registeredServices) {
newJob->pendingCallStarted();
QDBusPendingCall pendingCall = interface->asyncCall(QLatin1String("requestView"), appName, appIcon, capabilities);
RequestViewCallWatcher *watcher = new RequestViewCallWatcher(newJob, interface->service(), pendingCall, this);
connect(watcher, SIGNAL(callFinished(RequestViewCallWatcher*)),
newJob, SLOT(pendingCallFinished(RequestViewCallWatcher*)));
}
return newJob->objectPath();
}
QStringList ProgressListModel::gatherJobUrls()
{
QStringList jobUrls;
foreach(JobView* jobView, m_jobViews) {
jobUrls.append(jobView->destUrl().toString());
}
return jobUrls;
}
void ProgressListModel::jobFinished(JobView *jobView)
{
// Job finished, delete it if we are not in self-ui mode, *and* the config option to keep finished jobs is set
//TODO: does not check for case for the config
if (!m_uiServer) {
kDebug(7024) << "removing jobview from list, it finished";
m_jobViews.removeOne(jobView);
//job dies, dest. URL's change..
emit jobUrlsChanged(gatherJobUrls());
}
}
void ProgressListModel::jobChanged(uint jobId)
{
emit dataChanged(createIndex(jobId - 1, 0), createIndex(jobId + 1, 0));
layoutChanged();
}
void ProgressListModel::emitJobUrlsChanged()
{
emit jobUrlsChanged(gatherJobUrls());
}
void ProgressListModel::registerService(const QString &serviceName, const QString &objectPath)
{
QDBusConnection sessionBus = QDBusConnection::sessionBus();
if (!serviceName.isEmpty() && !objectPath.isEmpty()) {
if (sessionBus.interface()->isServiceRegistered(serviceName).value() &&
!m_registeredServices.contains(serviceName)) {
org::kde::JobViewServer *client =
new org::kde::JobViewServer(serviceName, objectPath, sessionBus);
if (client->isValid()) {
delete m_uiServer;
m_uiServer = 0;
m_serviceWatcher->addWatchedService(serviceName);
m_registeredServices.insert(serviceName, client);
//tell this new client to create all of the same jobs that we currently have.
//also connect them so that when the method comes back, it will return a
//QDBusObjectPath value, which is where we can contact that job, within "org.kde.JobViewV2"
//TODO: KDE5 remember to replace current org.kde.JobView interface with the V2 one.. (it's named V2 for compat. reasons).
//TODO: this falls victim to what newJob used to be vulnerable to...async calls returning too slowly and a terminate ensuing before that.
// it may not be a problem (yet), though.
foreach(JobView* jobView, m_jobViews) {
QDBusPendingCall pendingCall = client->asyncCall(QLatin1String("requestView"), jobView->appName(), jobView->appIconName(), jobView->capabilities());
RequestViewCallWatcher *watcher = new RequestViewCallWatcher(jobView, serviceName, pendingCall, this);
connect(watcher, SIGNAL(callFinished(RequestViewCallWatcher*)),
jobView, SLOT(pendingCallFinished(RequestViewCallWatcher*)));
}
} else {
delete client;
}
}
}
}
bool ProgressListModel::requiresJobTracker()
{
return m_registeredServices.isEmpty();
}
void ProgressListModel::serviceUnregistered(const QString &name)
{
m_serviceWatcher->removeWatchedService(name);
if (m_registeredServices.contains(name)) {
emit serviceDropped(name);
m_registeredServices.remove(name);
/* unused (FIXME)
if (m_registeredServices.isEmpty()) {
//the last service dropped, we *need* to show our GUI
m_uiServer = new UiServer(this);
}
*/
}
QList<JobView*> jobs = m_jobViewsOwners.values(name);
if (!jobs.isEmpty()) {
m_jobViewsOwners.remove(name);
Q_FOREACH(JobView *job, jobs) {
job->terminate(QString());
}
}
}
QStringList ProgressListModel::registeredJobContacts()
{
QStringList output;
foreach (JobView* jobView, m_jobViews) {
output.append(jobView->jobContacts());
}
return output;
}
#include "moc_progresslistmodel.cpp"