mirror of
https://bitbucket.org/smil3y/kdelibs.git
synced 2025-02-23 10:22:48 +00:00
kdeui: rework job tracking
just watch me do it without a dedicated D-Bus service and dataengine Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
parent
35e6fb9b0c
commit
8293d08153
15 changed files with 269 additions and 858 deletions
|
@ -309,7 +309,7 @@ install(
|
||||||
KWidgetItemDelegate
|
KWidgetItemDelegate
|
||||||
KWidgetJobTracker
|
KWidgetJobTracker
|
||||||
KDynamicJobTracker
|
KDynamicJobTracker
|
||||||
KUiServerJobTracker
|
KPlasmaJobTracker
|
||||||
KPixmapSequence
|
KPixmapSequence
|
||||||
KPixmapSequenceWidget
|
KPixmapSequenceWidget
|
||||||
KPixmapSequenceOverlayPainter
|
KPixmapSequenceOverlayPainter
|
||||||
|
|
1
includes/KPlasmaJobTracker
Normal file
1
includes/KPlasmaJobTracker
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#include "../kplasmajobtracker.h"
|
|
@ -1 +0,0 @@
|
||||||
#include "../kuiserverjobtracker.h"
|
|
|
@ -132,7 +132,7 @@ set(kdeui_LIB_SRCS
|
||||||
jobs/kdialogjobuidelegate.cpp
|
jobs/kdialogjobuidelegate.cpp
|
||||||
jobs/kabstractwidgetjobtracker.cpp
|
jobs/kabstractwidgetjobtracker.cpp
|
||||||
jobs/kwidgetjobtracker.cpp
|
jobs/kwidgetjobtracker.cpp
|
||||||
jobs/kuiserverjobtracker.cpp
|
jobs/kplasmajobtracker.cpp
|
||||||
jobs/kdynamicjobtracker.cpp
|
jobs/kdynamicjobtracker.cpp
|
||||||
kernel/kapplication.cpp
|
kernel/kapplication.cpp
|
||||||
kernel/kuniqueapplication.cpp
|
kernel/kuniqueapplication.cpp
|
||||||
|
@ -250,13 +250,6 @@ if (X11_Xkb_FOUND AND X11_Xkbfile_FOUND)
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
qt4_add_dbus_interfaces(kdeui_LIB_SRCS jobs/org.kde.JobViewServer.xml )
|
|
||||||
|
|
||||||
qt4_add_dbus_interface(kdeui_LIB_SRCS
|
|
||||||
jobs/org.kde.JobView.xml
|
|
||||||
jobviewiface
|
|
||||||
)
|
|
||||||
|
|
||||||
set(kglobalaccel_xml shortcuts/org.kde.KGlobalAccel.xml)
|
set(kglobalaccel_xml shortcuts/org.kde.KGlobalAccel.xml)
|
||||||
set_source_files_properties(${kglobalaccel_xml} PROPERTIES INCLUDE "kglobalshortcutinfo_p.h")
|
set_source_files_properties(${kglobalaccel_xml} PROPERTIES INCLUDE "kglobalshortcutinfo_p.h")
|
||||||
qt4_add_dbus_interface(kdeui_LIB_SRCS ${kglobalaccel_xml} kglobalaccel_interface )
|
qt4_add_dbus_interface(kdeui_LIB_SRCS ${kglobalaccel_xml} kglobalaccel_interface )
|
||||||
|
@ -407,7 +400,7 @@ install(
|
||||||
jobs/kdialogjobuidelegate.h
|
jobs/kdialogjobuidelegate.h
|
||||||
jobs/kabstractwidgetjobtracker.h
|
jobs/kabstractwidgetjobtracker.h
|
||||||
jobs/kwidgetjobtracker.h
|
jobs/kwidgetjobtracker.h
|
||||||
jobs/kuiserverjobtracker.h
|
jobs/kplasmajobtracker.h
|
||||||
jobs/kdynamicjobtracker.h
|
jobs/kdynamicjobtracker.h
|
||||||
kernel/kapplication.h
|
kernel/kapplication.h
|
||||||
kernel/kuniqueapplication.h
|
kernel/kuniqueapplication.h
|
||||||
|
@ -518,10 +511,3 @@ install(
|
||||||
PROGRAMS preparetips
|
PROGRAMS preparetips
|
||||||
DESTINATION ${KDE4_BIN_INSTALL_DIR}
|
DESTINATION ${KDE4_BIN_INSTALL_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
install(
|
|
||||||
FILES
|
|
||||||
jobs/org.kde.JobViewServer.xml
|
|
||||||
jobs/org.kde.JobView.xml
|
|
||||||
DESTINATION ${KDE4_DBUS_INTERFACES_INSTALL_DIR}
|
|
||||||
)
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
#include "kdynamicjobtracker.h"
|
#include "kdynamicjobtracker.h"
|
||||||
|
|
||||||
#include <kuiserverjobtracker.h>
|
#include <kplasmajobtracker.h>
|
||||||
#include <kwidgetjobtracker.h>
|
#include <kwidgetjobtracker.h>
|
||||||
#include <kjobtrackerinterface.h>
|
#include <kjobtrackerinterface.h>
|
||||||
#include <kdebug.h>
|
#include <kdebug.h>
|
||||||
|
@ -32,7 +32,7 @@
|
||||||
|
|
||||||
struct AllTrackers
|
struct AllTrackers
|
||||||
{
|
{
|
||||||
KUiServerJobTracker *kuiserverTracker;
|
KPlasmaJobTracker *plasmaTracker;
|
||||||
KWidgetJobTracker *widgetTracker;
|
KWidgetJobTracker *widgetTracker;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -40,18 +40,18 @@ class KDynamicJobTracker::Private
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Private()
|
Private()
|
||||||
: kuiserverTracker(nullptr),
|
: plasmaTracker(nullptr),
|
||||||
widgetTracker(nullptr)
|
widgetTracker(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
~Private()
|
~Private()
|
||||||
{
|
{
|
||||||
delete kuiserverTracker;
|
delete plasmaTracker;
|
||||||
delete widgetTracker;
|
delete widgetTracker;
|
||||||
}
|
}
|
||||||
|
|
||||||
KUiServerJobTracker *kuiserverTracker;
|
KPlasmaJobTracker *plasmaTracker;
|
||||||
KWidgetJobTracker *widgetTracker;
|
KWidgetJobTracker *widgetTracker;
|
||||||
QMap<KJob*, AllTrackers> trackers;
|
QMap<KJob*, AllTrackers> trackers;
|
||||||
};
|
};
|
||||||
|
@ -69,19 +69,16 @@ KDynamicJobTracker::~KDynamicJobTracker()
|
||||||
|
|
||||||
void KDynamicJobTracker::registerJob(KJob *job)
|
void KDynamicJobTracker::registerJob(KJob *job)
|
||||||
{
|
{
|
||||||
if (!d->kuiserverTracker) {
|
if (!d->plasmaTracker) {
|
||||||
d->kuiserverTracker = new KUiServerJobTracker();
|
d->plasmaTracker = new KPlasmaJobTracker();
|
||||||
}
|
}
|
||||||
|
|
||||||
d->trackers[job].kuiserverTracker = d->kuiserverTracker;
|
d->trackers[job].plasmaTracker = d->plasmaTracker;
|
||||||
d->trackers[job].kuiserverTracker->registerJob(job);
|
d->trackers[job].plasmaTracker->registerJob(job);
|
||||||
|
|
||||||
QDBusInterface interface("org.kde.kuiserver", "/JobViewServer", "",
|
QDBusInterface interface("org.kde.plasma-desktop", "/JobTracker", "org.kde.JobTracker", QDBusConnection::sessionBus(), this);
|
||||||
QDBusConnection::sessionBus(), this);
|
if (!interface.isValid()) {
|
||||||
QDBusReply<bool> reply = interface.call("requiresJobTracker");
|
// create a widget tracker in addition to KPlasmaJobTracker.
|
||||||
|
|
||||||
if (reply.isValid() && reply.value()) {
|
|
||||||
//create a widget tracker in addition to kuiservertracker.
|
|
||||||
if (!d->widgetTracker) {
|
if (!d->widgetTracker) {
|
||||||
d->widgetTracker = new KWidgetJobTracker();
|
d->widgetTracker = new KWidgetJobTracker();
|
||||||
}
|
}
|
||||||
|
@ -89,21 +86,21 @@ void KDynamicJobTracker::registerJob(KJob *job)
|
||||||
d->trackers[job].widgetTracker->registerJob(job);
|
d->trackers[job].widgetTracker->registerJob(job);
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_ASSERT(d->trackers[job].kuiserverTracker || d->trackers[job].widgetTracker);
|
Q_ASSERT(d->trackers[job].plasmaTracker || d->trackers[job].widgetTracker);
|
||||||
}
|
}
|
||||||
|
|
||||||
void KDynamicJobTracker::unregisterJob(KJob *job)
|
void KDynamicJobTracker::unregisterJob(KJob *job)
|
||||||
{
|
{
|
||||||
KUiServerJobTracker *kuiserverTracker = d->trackers[job].kuiserverTracker;
|
KPlasmaJobTracker *plasmaTracker = d->trackers[job].plasmaTracker;
|
||||||
KWidgetJobTracker *widgetTracker = d->trackers[job].widgetTracker;
|
KWidgetJobTracker *widgetTracker = d->trackers[job].widgetTracker;
|
||||||
|
|
||||||
if (!(widgetTracker || kuiserverTracker)) {
|
if (!(widgetTracker || plasmaTracker)) {
|
||||||
kWarning() << "Tried to unregister a kio job that hasn't been registered.";
|
kWarning() << "Tried to unregister a kio job that hasn't been registered.";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kuiserverTracker) {
|
if (plasmaTracker) {
|
||||||
kuiserverTracker->unregisterJob(job);
|
plasmaTracker->unregisterJob(job);
|
||||||
}
|
}
|
||||||
if (widgetTracker) {
|
if (widgetTracker) {
|
||||||
widgetTracker->unregisterJob(job);
|
widgetTracker->unregisterJob(job);
|
||||||
|
|
|
@ -25,14 +25,12 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class implements a simple job tracker which registers any job to the KWidgetJobTracker if a
|
* This class implements a simple job tracker which registers any job to the KWidgetJobTracker if a
|
||||||
* kuiserver isn't available on the DBus, or to the KUiServerJobTracker, if a kuiserver is
|
* plasma isn't available on the DBus, or to the KPlasmaJobTracker, if a plasma is available. This
|
||||||
* available. This way, we have the old dialogs as fallback when the user doesn't use a kuiserver
|
* way, we have the old dialogs as fallback when the user doesn't use a plasma applet.
|
||||||
* applet or application.
|
|
||||||
*/
|
*/
|
||||||
class KDEUI_EXPORT KDynamicJobTracker : public KJobTrackerInterface
|
class KDEUI_EXPORT KDynamicJobTracker : public KJobTrackerInterface
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Creates a new KDynamicJobTracker
|
* Creates a new KDynamicJobTracker
|
||||||
|
@ -48,8 +46,7 @@ public:
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
/**
|
/**
|
||||||
* Register a new job in this tracker. This call will get forwarded to either KWidgetJobTracker
|
* Register a new job in this tracker.
|
||||||
* or KUiServerJobTracker, depending on the availability of the Kuiserver.
|
|
||||||
*
|
*
|
||||||
* @param job the job to register
|
* @param job the job to register
|
||||||
*/
|
*/
|
||||||
|
@ -67,4 +64,4 @@ private:
|
||||||
Private *const d;
|
Private *const d;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif // KDYNAMICJOBTRACKER_H
|
||||||
|
|
230
kdeui/jobs/kplasmajobtracker.cpp
Normal file
230
kdeui/jobs/kplasmajobtracker.cpp
Normal file
|
@ -0,0 +1,230 @@
|
||||||
|
/*
|
||||||
|
This file is part of the KDE libraries
|
||||||
|
Copyright (C) 2024 Ivailo Monev <xakepa10@gmail.com>
|
||||||
|
|
||||||
|
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 "kplasmajobtracker.h"
|
||||||
|
|
||||||
|
#include <QDBusInterface>
|
||||||
|
#include <QDBusConnectionInterface>
|
||||||
|
#include <kglobal.h>
|
||||||
|
#include <kcomponentdata.h>
|
||||||
|
#include <kaboutdata.h>
|
||||||
|
#include <kjob.h>
|
||||||
|
#include <kdebug.h>
|
||||||
|
|
||||||
|
static QString kJobID(const KJob *job)
|
||||||
|
{
|
||||||
|
return QString::number(quintptr(job), 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
class KPlasmaJobTrackerPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
KPlasmaJobTrackerPrivate();
|
||||||
|
|
||||||
|
void _k_slotStopRequested(const QString &name);
|
||||||
|
|
||||||
|
QMap<KJob*, QVariantMap> jobs;
|
||||||
|
QDBusInterface interface;
|
||||||
|
};
|
||||||
|
|
||||||
|
KPlasmaJobTrackerPrivate::KPlasmaJobTrackerPrivate()
|
||||||
|
: interface("org.kde.plasma-desktop", "/JobTracker", "org.kde.JobTracker", QDBusConnection::sessionBus())
|
||||||
|
{
|
||||||
|
QDBusConnectionInterface* sessionIface = QDBusConnection::sessionBus().interface();
|
||||||
|
if (!sessionIface->isServiceRegistered("org.kde.plasma-desktop")) {
|
||||||
|
kError() << "The service org.kde.plasma-desktop is still not registered";
|
||||||
|
} else {
|
||||||
|
kDebug() << "Plasma job tracker registered";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KPlasmaJobTrackerPrivate::_k_slotStopRequested(const QString &name)
|
||||||
|
{
|
||||||
|
kDebug() << "job stop requested" << name;
|
||||||
|
foreach (KJob* job, jobs.keys()) {
|
||||||
|
const QString jobid = kJobID(job);
|
||||||
|
if (jobid == name) {
|
||||||
|
job->kill(KJob::EmitResult);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
KPlasmaJobTracker::KPlasmaJobTracker(QObject *parent)
|
||||||
|
: KJobTrackerInterface(parent),
|
||||||
|
d(new KPlasmaJobTrackerPrivate())
|
||||||
|
{
|
||||||
|
if (d->interface.isValid()) {
|
||||||
|
connect(
|
||||||
|
&d->interface, SIGNAL(stopRequested(QString)),
|
||||||
|
this, SLOT(_k_slotStopRequested(QString))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KPlasmaJobTracker::~KPlasmaJobTracker()
|
||||||
|
{
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KPlasmaJobTracker::registerJob(KJob *job)
|
||||||
|
{
|
||||||
|
if (d->jobs.contains(job)) {
|
||||||
|
kWarning() << "atempting to register the same job twice" << job;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const KComponentData componentData = KGlobal::mainComponent();
|
||||||
|
QString appName = job->property("appName").toString();
|
||||||
|
if (appName.isEmpty()) {
|
||||||
|
appName = componentData.aboutData()->programName();
|
||||||
|
}
|
||||||
|
QString appIconName = job->property("appIconName").toString();
|
||||||
|
if (appIconName.isEmpty()) {
|
||||||
|
appIconName = componentData.aboutData()->programIconName();
|
||||||
|
}
|
||||||
|
if (appIconName.isEmpty()) {
|
||||||
|
appIconName = componentData.aboutData()->appName();
|
||||||
|
}
|
||||||
|
const QString destUrl = job->property("destUrl").toString();
|
||||||
|
|
||||||
|
const QString jobid = kJobID(job);
|
||||||
|
QVariantMap jobdata;
|
||||||
|
jobdata.insert("infoMessage", QString());
|
||||||
|
jobdata.insert("appName", appName); // currently not used
|
||||||
|
jobdata.insert("appIconName", appIconName);
|
||||||
|
jobdata.insert("labelName0", QString());
|
||||||
|
jobdata.insert("labelName1", QString());
|
||||||
|
jobdata.insert("label0", QString());
|
||||||
|
jobdata.insert("label1", QString());
|
||||||
|
jobdata.insert("destUrl", destUrl);
|
||||||
|
jobdata.insert("error", QString());
|
||||||
|
jobdata.insert("percentage", 0);
|
||||||
|
jobdata.insert("state", "running");
|
||||||
|
jobdata.insert("killable", bool(job->capabilities() & KJob::Killable));
|
||||||
|
d->jobs.insert(job, jobdata);
|
||||||
|
d->interface.call("addJob", jobid);
|
||||||
|
d->interface.call("updateJob", jobid, jobdata);
|
||||||
|
|
||||||
|
kDebug() << "registerd job" << jobid << jobdata;
|
||||||
|
KJobTrackerInterface::registerJob(job);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KPlasmaJobTracker::unregisterJob(KJob *job)
|
||||||
|
{
|
||||||
|
KJobTrackerInterface::unregisterJob(job);
|
||||||
|
|
||||||
|
if (!d->jobs.contains(job)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// both finished() and unregistrJob will be called, either does it
|
||||||
|
kDebug() << "unregisterd job" << kJobID(job);
|
||||||
|
finished(job);
|
||||||
|
d->jobs.remove(job);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KPlasmaJobTracker::finished(KJob *job)
|
||||||
|
{
|
||||||
|
if (!d->jobs.contains(job)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString jobid = kJobID(job);
|
||||||
|
QVariantMap jobdata = d->jobs.value(job);
|
||||||
|
jobdata.insert("state", "stopped");
|
||||||
|
d->interface.call("updateJob", jobid, jobdata);
|
||||||
|
kDebug() << "job finished" << jobid;
|
||||||
|
d->jobs.remove(job);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KPlasmaJobTracker::suspended(KJob *job)
|
||||||
|
{
|
||||||
|
if (!d->jobs.contains(job)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString jobid = kJobID(job);
|
||||||
|
QVariantMap jobdata = d->jobs.value(job);
|
||||||
|
jobdata.insert("state", "suspended");
|
||||||
|
d->interface.call("updateJob", jobid, jobdata);
|
||||||
|
kDebug() << "job suspended" << jobid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KPlasmaJobTracker::resumed(KJob *job)
|
||||||
|
{
|
||||||
|
if (!d->jobs.contains(job)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString jobid = kJobID(job);
|
||||||
|
QVariantMap jobdata = d->jobs.value(job);
|
||||||
|
jobdata.insert("state", "running");
|
||||||
|
d->interface.call("updateJob", jobid, jobdata);
|
||||||
|
kDebug() << "job resumed" << jobid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KPlasmaJobTracker::description(KJob *job, const QString &title,
|
||||||
|
const QPair<QString, QString> &field1,
|
||||||
|
const QPair<QString, QString> &field2)
|
||||||
|
{
|
||||||
|
if (!d->jobs.contains(job)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString jobid = kJobID(job);
|
||||||
|
QVariantMap jobdata = d->jobs.value(job);
|
||||||
|
jobdata.insert("labelName0", field1.first);
|
||||||
|
jobdata.insert("label0", field1.second);
|
||||||
|
jobdata.insert("labelName1", field2.first);
|
||||||
|
jobdata.insert("label1", field2.second);
|
||||||
|
d->interface.call("updateJob", jobid, jobdata);
|
||||||
|
kDebug() << "job description" << jobid << field1 << field2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KPlasmaJobTracker::infoMessage(KJob *job, const QString &plain, const QString &rich)
|
||||||
|
{
|
||||||
|
Q_UNUSED(rich);
|
||||||
|
|
||||||
|
if (!d->jobs.contains(job)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString jobid = kJobID(job);
|
||||||
|
QVariantMap jobdata = d->jobs.value(job);
|
||||||
|
jobdata.insert("infoMessage", plain);
|
||||||
|
d->interface.call("updateJob", jobid, jobdata);
|
||||||
|
kDebug() << "job info message" << jobid << plain << rich;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KPlasmaJobTracker::percent(KJob *job, unsigned long percent)
|
||||||
|
{
|
||||||
|
if (!d->jobs.contains(job)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString jobid = kJobID(job);
|
||||||
|
QVariantMap jobdata = d->jobs.value(job);
|
||||||
|
jobdata.insert("percent", qulonglong(percent));
|
||||||
|
d->interface.call("updateJob", jobid, jobdata);
|
||||||
|
kDebug() << "job percent" << jobid << percent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "moc_kplasmajobtracker.cpp"
|
|
@ -1,9 +1,10 @@
|
||||||
/* This file is part of the KDE project
|
/*
|
||||||
Copyright (C) 2007 Kevin Ottens <ervin@kde.org>
|
This file is part of the KDE libraries
|
||||||
|
Copyright (C) 2024 Ivailo Monev <xakepa10@gmail.com>
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
This library is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU Library General Public
|
modify it under the terms of the GNU Library General Public
|
||||||
License version 2 as published by the Free Software Foundation.
|
License version 2, as published by the Free Software Foundation.
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
This library is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
@ -16,52 +17,30 @@
|
||||||
Boston, MA 02110-1301, USA.
|
Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef KUISERVERJOBTRACKER_H
|
#ifndef KPLASMAJOBTRACKER_H
|
||||||
#define KUISERVERJOBTRACKER_H
|
#define KPLASMAJOBTRACKER_H
|
||||||
|
|
||||||
#include <kdeui_export.h>
|
#include <kdeui_export.h>
|
||||||
#include <kjobtrackerinterface.h>
|
#include <kjobtrackerinterface.h>
|
||||||
|
|
||||||
class KJob;
|
class KJob;
|
||||||
|
class KPlasmaJobTrackerPrivate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The interface to implement to track the progresses of a job.
|
* The interface to implement to track the progresses of a job.
|
||||||
*/
|
*/
|
||||||
class KDEUI_EXPORT KUiServerJobTracker : public KJobTrackerInterface
|
class KDEUI_EXPORT KPlasmaJobTracker : public KJobTrackerInterface
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
KPlasmaJobTracker(QObject *parent = nullptr);
|
||||||
* Creates a new KJobTrackerInterface
|
virtual ~KPlasmaJobTracker();
|
||||||
*
|
|
||||||
* @param parent the parent object
|
|
||||||
*/
|
|
||||||
KUiServerJobTracker(QObject *parent=0);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroys a KJobTrackerInterface
|
|
||||||
*/
|
|
||||||
virtual ~KUiServerJobTracker();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register a new job in this tracker.
|
|
||||||
*
|
|
||||||
* @param job the job to register
|
|
||||||
*/
|
|
||||||
virtual void registerJob(KJob *job);
|
virtual void registerJob(KJob *job);
|
||||||
|
|
||||||
/**
|
|
||||||
* Unregister a job from this tracker.
|
|
||||||
*
|
|
||||||
* @param job the job to unregister
|
|
||||||
*/
|
|
||||||
virtual void unregisterJob(KJob *job);
|
virtual void unregisterJob(KJob *job);
|
||||||
|
|
||||||
protected Q_SLOTS:
|
protected Q_SLOTS:
|
||||||
/**
|
|
||||||
* The following slots are inherited from KJobTrackerInterface.
|
|
||||||
*/
|
|
||||||
virtual void finished(KJob *job);
|
virtual void finished(KJob *job);
|
||||||
virtual void suspended(KJob *job);
|
virtual void suspended(KJob *job);
|
||||||
virtual void resumed(KJob *job);
|
virtual void resumed(KJob *job);
|
||||||
|
@ -69,16 +48,12 @@ protected Q_SLOTS:
|
||||||
const QPair<QString, QString> &field1,
|
const QPair<QString, QString> &field1,
|
||||||
const QPair<QString, QString> &field2);
|
const QPair<QString, QString> &field2);
|
||||||
virtual void infoMessage(KJob *job, const QString &plain, const QString &rich);
|
virtual void infoMessage(KJob *job, const QString &plain, const QString &rich);
|
||||||
virtual void totalAmount(KJob *job, KJob::Unit unit, qulonglong amount);
|
|
||||||
virtual void processedAmount(KJob *job, KJob::Unit unit, qulonglong amount);
|
|
||||||
virtual void percent(KJob *job, unsigned long percent);
|
virtual void percent(KJob *job, unsigned long percent);
|
||||||
virtual void speed(KJob *job, unsigned long value);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Private;
|
KPlasmaJobTrackerPrivate *const d;
|
||||||
Private *const d;
|
|
||||||
|
|
||||||
Q_PRIVATE_SLOT(d, void _k_killJob())
|
Q_PRIVATE_SLOT(d, void _k_slotStopRequested(const QString &name))
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif // KPLASMAJOBTRACKER_H
|
|
@ -1,333 +0,0 @@
|
||||||
/* This file is part of the KDE project
|
|
||||||
Copyright (C) 2008 Rafael Fernández López <ereslibre@kde.org>
|
|
||||||
Copyright (C) 2007 Kevin Ottens <ervin@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 "kuiserverjobtracker.h"
|
|
||||||
#include "kuiserverjobtracker_p.h"
|
|
||||||
|
|
||||||
#include "jobviewiface.h"
|
|
||||||
|
|
||||||
#include <klocale.h>
|
|
||||||
#include <kdebug.h>
|
|
||||||
#include <ktoolinvocation.h>
|
|
||||||
#include <kcomponentdata.h>
|
|
||||||
#include <kaboutdata.h>
|
|
||||||
#include <kjob.h>
|
|
||||||
|
|
||||||
K_GLOBAL_STATIC(KSharedUiServerProxy, serverProxy)
|
|
||||||
|
|
||||||
class KUiServerJobTracker::Private
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Private(KUiServerJobTracker *parent)
|
|
||||||
: q(parent)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
KUiServerJobTracker *const q;
|
|
||||||
|
|
||||||
void _k_killJob();
|
|
||||||
|
|
||||||
QHash<KJob*, org::kde::JobView*> progressJobView;
|
|
||||||
};
|
|
||||||
|
|
||||||
void KUiServerJobTracker::Private::_k_killJob()
|
|
||||||
{
|
|
||||||
org::kde::JobView *jobView = qobject_cast<org::kde::JobView*>(q->sender());
|
|
||||||
|
|
||||||
if (jobView) {
|
|
||||||
KJob *job = progressJobView.key(jobView);
|
|
||||||
|
|
||||||
if (job)
|
|
||||||
job->kill(KJob::EmitResult);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
KUiServerJobTracker::KUiServerJobTracker(QObject *parent)
|
|
||||||
: KJobTrackerInterface(parent),
|
|
||||||
d(new Private(this))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
KUiServerJobTracker::~KUiServerJobTracker()
|
|
||||||
{
|
|
||||||
if (!d->progressJobView.isEmpty()) {
|
|
||||||
qWarning() << "A KUiServerJobTracker instance contains"
|
|
||||||
<< d->progressJobView.size() << "stalled jobs";
|
|
||||||
}
|
|
||||||
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KUiServerJobTracker::registerJob(KJob *job)
|
|
||||||
{
|
|
||||||
// Already registered job?
|
|
||||||
if (d->progressJobView.contains(job)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
KComponentData componentData = KGlobal::mainComponent();
|
|
||||||
QString appName = job->property("appName").toString();
|
|
||||||
if (appName.isEmpty()) {
|
|
||||||
appName = componentData.aboutData()->programName();
|
|
||||||
}
|
|
||||||
QString appIconName = job->property("appIconName").toString();
|
|
||||||
if (appIconName.isEmpty()) {
|
|
||||||
appIconName = componentData.aboutData()->programIconName();
|
|
||||||
}
|
|
||||||
if (appIconName.isEmpty()) {
|
|
||||||
appIconName = componentData.aboutData()->appName();
|
|
||||||
}
|
|
||||||
|
|
||||||
QWeakPointer<KJob> jobWatch = job;
|
|
||||||
QDBusReply<QDBusObjectPath> reply = serverProxy->uiserver().requestView(appName,
|
|
||||||
appIconName,
|
|
||||||
job->capabilities());
|
|
||||||
|
|
||||||
// If we got a valid reply, register the interface for later usage.
|
|
||||||
if (reply.isValid()) {
|
|
||||||
org::kde::JobView *jobView = new org::kde::JobView("org.kde.JobViewServer",
|
|
||||||
reply.value().path(),
|
|
||||||
QDBusConnection::sessionBus());
|
|
||||||
if (!jobWatch) {
|
|
||||||
//kDebug() << "deleted out from under us when asking the server proxy for the view";
|
|
||||||
jobView->terminate(QString());
|
|
||||||
delete jobView;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QObject::connect(jobView, SIGNAL(cancelRequested()), this,
|
|
||||||
SLOT(_k_killJob()));
|
|
||||||
QObject::connect(jobView, SIGNAL(suspendRequested()), job,
|
|
||||||
SLOT(suspend()));
|
|
||||||
QObject::connect(jobView, SIGNAL(resumeRequested()), job,
|
|
||||||
SLOT(resume()));
|
|
||||||
|
|
||||||
QVariant destUrl = job->property("destUrl");
|
|
||||||
if (destUrl.isValid()) {
|
|
||||||
jobView->setDestUrl(destUrl.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!jobWatch) {
|
|
||||||
//kDebug() << "deleted out from under us when creating the dbus interface";
|
|
||||||
jobView->terminate(QString());
|
|
||||||
delete jobView;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
d->progressJobView.insert(job, jobView);
|
|
||||||
} else if (!jobWatch) {
|
|
||||||
qWarning() << "Uh-oh...KUiServerJobTracker was trying to forward a job, but it was deleted from under us."
|
|
||||||
<< "kuiserver *may* have a stranded job. we can't do anything about it because the returned objectPath is invalid.";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
KJobTrackerInterface::registerJob(job);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KUiServerJobTracker::unregisterJob(KJob *job)
|
|
||||||
{
|
|
||||||
KJobTrackerInterface::unregisterJob(job);
|
|
||||||
|
|
||||||
if (!d->progressJobView.contains(job)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
org::kde::JobView *jobView = d->progressJobView.take(job);
|
|
||||||
|
|
||||||
if (job->error()) {
|
|
||||||
jobView->terminate(job->errorText());
|
|
||||||
} else {
|
|
||||||
jobView->terminate(QString());
|
|
||||||
}
|
|
||||||
|
|
||||||
delete jobView;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KUiServerJobTracker::finished(KJob *job)
|
|
||||||
{
|
|
||||||
if (!d->progressJobView.contains(job)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
org::kde::JobView *jobView = d->progressJobView.take(job);
|
|
||||||
|
|
||||||
if (job->error()) {
|
|
||||||
jobView->terminate(job->errorText());
|
|
||||||
} else {
|
|
||||||
jobView->terminate(QString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KUiServerJobTracker::suspended(KJob *job)
|
|
||||||
{
|
|
||||||
if (!d->progressJobView.contains(job)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
org::kde::JobView *jobView = d->progressJobView[job];
|
|
||||||
|
|
||||||
jobView->setSuspended(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KUiServerJobTracker::resumed(KJob *job)
|
|
||||||
{
|
|
||||||
if (!d->progressJobView.contains(job)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
org::kde::JobView *jobView = d->progressJobView[job];
|
|
||||||
|
|
||||||
jobView->setSuspended(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KUiServerJobTracker::description(KJob *job, const QString &title,
|
|
||||||
const QPair<QString, QString> &field1,
|
|
||||||
const QPair<QString, QString> &field2)
|
|
||||||
{
|
|
||||||
if (!d->progressJobView.contains(job)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
org::kde::JobView *jobView = d->progressJobView[job];
|
|
||||||
|
|
||||||
jobView->setInfoMessage(title);
|
|
||||||
|
|
||||||
if (field1.first.isNull() || field1.second.isNull()) {
|
|
||||||
jobView->clearDescriptionField(0);
|
|
||||||
} else {
|
|
||||||
jobView->setDescriptionField(0, field1.first, field1.second);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (field2.first.isNull() || field2.second.isNull()) {
|
|
||||||
jobView->clearDescriptionField(1);
|
|
||||||
} else {
|
|
||||||
jobView->setDescriptionField(1, field2.first, field2.second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KUiServerJobTracker::infoMessage(KJob *job, const QString &plain, const QString &rich)
|
|
||||||
{
|
|
||||||
Q_UNUSED(rich)
|
|
||||||
|
|
||||||
if (!d->progressJobView.contains(job)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
org::kde::JobView *jobView = d->progressJobView[job];
|
|
||||||
|
|
||||||
jobView->setInfoMessage(plain);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KUiServerJobTracker::totalAmount(KJob *job, KJob::Unit unit, qulonglong amount)
|
|
||||||
{
|
|
||||||
if (!d->progressJobView.contains(job)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
org::kde::JobView *jobView = d->progressJobView[job];
|
|
||||||
|
|
||||||
switch (unit) {
|
|
||||||
case KJob::Bytes:
|
|
||||||
jobView->setTotalAmount(amount, "bytes");
|
|
||||||
break;
|
|
||||||
case KJob::Files:
|
|
||||||
jobView->setTotalAmount(amount, "files");
|
|
||||||
break;
|
|
||||||
case KJob::Directories:
|
|
||||||
jobView->setTotalAmount(amount, "dirs");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KUiServerJobTracker::processedAmount(KJob *job, KJob::Unit unit, qulonglong amount)
|
|
||||||
{
|
|
||||||
if (!d->progressJobView.contains(job)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
org::kde::JobView *jobView = d->progressJobView[job];
|
|
||||||
|
|
||||||
switch (unit) {
|
|
||||||
case KJob::Bytes:
|
|
||||||
jobView->setProcessedAmount(amount, "bytes");
|
|
||||||
break;
|
|
||||||
case KJob::Files:
|
|
||||||
jobView->setProcessedAmount(amount, "files");
|
|
||||||
break;
|
|
||||||
case KJob::Directories:
|
|
||||||
jobView->setProcessedAmount(amount, "dirs");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KUiServerJobTracker::percent(KJob *job, unsigned long percent)
|
|
||||||
{
|
|
||||||
if (!d->progressJobView.contains(job)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
org::kde::JobView *jobView = d->progressJobView[job];
|
|
||||||
|
|
||||||
jobView->setPercent(percent);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KUiServerJobTracker::speed(KJob *job, unsigned long value)
|
|
||||||
{
|
|
||||||
if (!d->progressJobView.contains(job)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
org::kde::JobView *jobView = d->progressJobView[job];
|
|
||||||
|
|
||||||
jobView->setSpeed(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
KSharedUiServerProxy::KSharedUiServerProxy()
|
|
||||||
: m_uiserver("org.kde.JobViewServer", "/JobViewServer", QDBusConnection::sessionBus())
|
|
||||||
{
|
|
||||||
QDBusConnectionInterface* sessionIface = QDBusConnection::sessionBus().interface();
|
|
||||||
if (!sessionIface->isServiceRegistered("org.kde.JobViewServer")) {
|
|
||||||
QDBusReply<void> sessionReply = sessionIface->startService("org.kde.kuiserver");
|
|
||||||
if (!sessionReply.isValid()) {
|
|
||||||
kError() << "Couldn't start kuiserver service" << sessionReply.error();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sessionIface->isServiceRegistered("org.kde.JobViewServer"))
|
|
||||||
kError() << "The service org.kde.JobViewServer is still not registered";
|
|
||||||
else
|
|
||||||
kDebug() << "kuiserver registered";
|
|
||||||
}
|
|
||||||
|
|
||||||
KSharedUiServerProxy::~KSharedUiServerProxy()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
org::kde::JobViewServer &KSharedUiServerProxy::uiserver()
|
|
||||||
{
|
|
||||||
return m_uiserver;
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "moc_kuiserverjobtracker.cpp"
|
|
||||||
#include "moc_kuiserverjobtracker_p.cpp"
|
|
|
@ -1,48 +0,0 @@
|
||||||
/* This file is part of the KDE libraries
|
|
||||||
Copyright (C) 2006-2008 Rafael Fernández López <ereslibre@kde.org>
|
|
||||||
Kevin Ottens <ervin@kde.org>
|
|
||||||
Copyright (C) 2000 Matej Koss <koss@miesto.sk>
|
|
||||||
David Faure <faure@kde.org>
|
|
||||||
Stephan Kulow <coolo@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 as published by the Free Software Foundation; either
|
|
||||||
version 2 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef KUISERVERJOBTRACKER_P_H
|
|
||||||
#define KUISERVERJOBTRACKER_P_H
|
|
||||||
|
|
||||||
#include <QtCore/QMap>
|
|
||||||
|
|
||||||
#include <kglobal.h>
|
|
||||||
|
|
||||||
#include "jobviewserverinterface.h"
|
|
||||||
#include "jobviewiface.h"
|
|
||||||
|
|
||||||
class KSharedUiServerProxy : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
KSharedUiServerProxy();
|
|
||||||
~KSharedUiServerProxy();
|
|
||||||
|
|
||||||
org::kde::JobViewServer &uiserver();
|
|
||||||
|
|
||||||
private:
|
|
||||||
org::kde::JobViewServer m_uiserver;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -556,7 +556,7 @@ void KWidgetJobTracker::Private::ProgressWidget::init()
|
||||||
resize(sizeHint());
|
resize(sizeHint());
|
||||||
setMaximumHeight(sizeHint().height());
|
setMaximumHeight(sizeHint().height());
|
||||||
|
|
||||||
setWindowTitle(i18n("Progress Dialog")); // show something better than kuiserver
|
setWindowTitle(i18n("Progress Dialog"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void KWidgetJobTracker::Private::ProgressWidget::showTotals()
|
void KWidgetJobTracker::Private::ProgressWidget::showTotals()
|
||||||
|
|
|
@ -1,65 +0,0 @@
|
||||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
|
|
||||||
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
|
||||||
<node>
|
|
||||||
<interface name="org.kde.JobView">
|
|
||||||
<method name="terminate">
|
|
||||||
<arg name="errorMessage" type="s" direction="in"/>
|
|
||||||
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
|
|
||||||
</method>
|
|
||||||
<method name="setSuspended">
|
|
||||||
<arg name="suspended" type="b" direction="in"/>
|
|
||||||
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
|
|
||||||
</method>
|
|
||||||
<method name="setTotalAmount">
|
|
||||||
<arg name="amount" type="t" direction="in"/>
|
|
||||||
<arg name="unit" type="s" direction="in"/>
|
|
||||||
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
|
|
||||||
</method>
|
|
||||||
<method name="setProcessedAmount">
|
|
||||||
<arg name="amount" type="t" direction="in"/>
|
|
||||||
<arg name="unit" type="s" direction="in"/>
|
|
||||||
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
|
|
||||||
</method>
|
|
||||||
<method name="setPercent">
|
|
||||||
<arg name="percent" type="u" direction="in"/>
|
|
||||||
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
|
|
||||||
</method>
|
|
||||||
<method name="setSpeed">
|
|
||||||
<arg name="bytesPerSecond" type="t" direction="in"/>
|
|
||||||
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
|
|
||||||
</method>
|
|
||||||
<method name="setInfoMessage">
|
|
||||||
<arg name="message" type="s" direction="in"/>
|
|
||||||
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
|
|
||||||
</method>
|
|
||||||
<method name="setDescriptionField">
|
|
||||||
<arg name="number" type="u" direction="in"/>
|
|
||||||
<arg name="name" type="s" direction="in"/>
|
|
||||||
<arg name="value" type="s" direction="in"/>
|
|
||||||
<arg name="res" type="b" direction="out"/>
|
|
||||||
</method>
|
|
||||||
<method name="clearDescriptionField">
|
|
||||||
<arg name="number" type="u" direction="in"/>
|
|
||||||
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
|
|
||||||
</method>
|
|
||||||
<method name="setAppName">
|
|
||||||
<arg name="message" type="s" direction="in"/>
|
|
||||||
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
|
|
||||||
</method>
|
|
||||||
<method name="setAppIconName">
|
|
||||||
<arg name="message" type="s" direction="in"/>
|
|
||||||
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
|
|
||||||
</method>
|
|
||||||
<method name="setCapabilities">
|
|
||||||
<arg name="number" type="i" direction="in"/>
|
|
||||||
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
|
|
||||||
</method>
|
|
||||||
<method name="setDestUrl">
|
|
||||||
<arg name="destUrl" type="s" direction="in"/>
|
|
||||||
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
|
|
||||||
</method>
|
|
||||||
<signal name="suspendRequested"/>
|
|
||||||
<signal name="resumeRequested"/>
|
|
||||||
<signal name="cancelRequested"/>
|
|
||||||
</interface>
|
|
||||||
</node>
|
|
|
@ -1,17 +0,0 @@
|
||||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
|
|
||||||
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
|
||||||
<node>
|
|
||||||
<interface name="org.kde.JobViewServer">
|
|
||||||
<method name="requestView">
|
|
||||||
<arg name="appName" type="s" direction="in"/>
|
|
||||||
<arg name="appIconName" type="s" direction="in"/>
|
|
||||||
|
|
||||||
<!-- 'capabilities' is used as a bit field:
|
|
||||||
0x0001 means that the user should be able to cancel the job
|
|
||||||
0x0002 means that the user should be able to suspend/resume the job
|
|
||||||
-->
|
|
||||||
<arg name="capabilities" type="i" direction="in"/>
|
|
||||||
<arg name="trackerPath" type="o" direction="out"/>
|
|
||||||
</method>
|
|
||||||
</interface>
|
|
||||||
</node>
|
|
276
kio/DESIGN
276
kio/DESIGN
|
@ -1,276 +0,0 @@
|
||||||
DESIGN:
|
|
||||||
=======
|
|
||||||
|
|
||||||
libkio uses kioslaves (separate processes) that handle a given protocol.
|
|
||||||
|
|
||||||
Connection is the most low-level class, the one that encapsulates the pipe.
|
|
||||||
|
|
||||||
SlaveInterface is the class for transferring anything to the slave.
|
|
||||||
|
|
||||||
A slave inherits SlaveBase, which is the other half of SlaveInterface.
|
|
||||||
|
|
||||||
The scheduling is supposed to be on a two level basis. One is in the daemon
|
|
||||||
and one is in the application. The daemon one (as opposite to the holy one? :)
|
|
||||||
will determine how many slaves are ok for this app to be opened and it will
|
|
||||||
also assign tasks to actually existing slaves.
|
|
||||||
The application will still have some kind of a scheduler, but it should be
|
|
||||||
a lot simpler as it doesn't have to decide anything besides which
|
|
||||||
task goes to which pool of slaves (related to the protocol/host/user/port)
|
|
||||||
and move tasks around.
|
|
||||||
Currently a design study to name it cool is in scheduler.cpp but in the
|
|
||||||
application side. This is just to test other things like recursive jobs
|
|
||||||
and signals/slots within SlaveInterface. If someone feels brave, the scheduler
|
|
||||||
is yours!
|
|
||||||
On a second thought: at the daemon side there is no real scheduler, but a
|
|
||||||
pool of slaves. So what we need is some kind of load calculation of the
|
|
||||||
scheduler in the application and load balancing in the daemon.
|
|
||||||
|
|
||||||
A third thought: Maybe the daemon can just take care of a number of 'unused'
|
|
||||||
slaves. When an application needs a slave, it can request it from the daemon.
|
|
||||||
The application will get one, either from the pool of unused slaves,
|
|
||||||
or a new one will be created. This keeps things simple at the daemon level.
|
|
||||||
It is up to the application to give the slaves back to the daemon.
|
|
||||||
The scheduler in the application must take care not to request too many
|
|
||||||
slaves and could implement priorities.
|
|
||||||
|
|
||||||
Thought on usage:
|
|
||||||
* Typically a single slave-type is used exclusively in one application. E.g.
|
|
||||||
http slaves are used in a web-browser. POP3 slaves used in a mail program.
|
|
||||||
|
|
||||||
* Sometimes a single program can have multiple roles. E.g. konqueror is
|
|
||||||
both a web-browser and a file-manager. As a web-browser it primarily uses
|
|
||||||
http-slaves as a file-manager file-slaves.
|
|
||||||
|
|
||||||
* Selecting a link in konqueror: konqueror does a partial download of
|
|
||||||
the file to check the mimetype (right??) then the application is
|
|
||||||
started which downloads the complete file. In this case it should
|
|
||||||
be able to pass the slave which does the partial download from konqueror
|
|
||||||
to the application where it can do the complete download.
|
|
||||||
|
|
||||||
Do we need to have a hard limit on the number of slaves/host?
|
|
||||||
It seems so, because some protocols are about to fail if you
|
|
||||||
have two slaves running in parallel (e.g. POP3)
|
|
||||||
This has to be implemented in the daemon because only at daemon
|
|
||||||
level all the slaves are known. As a consequence slaves must
|
|
||||||
be returned to the daemon before connecting to another host.
|
|
||||||
(Returning the slaves back to the daemon after every job is not
|
|
||||||
strictly needed and only causes extra overhead)
|
|
||||||
|
|
||||||
Instead of actually returning the slave to the daemon, it could
|
|
||||||
be enough to ask 'recycling permission' from the daemon: the
|
|
||||||
application asks the daemon whether it is ok to use a slave for
|
|
||||||
another host. The daemon can then update its administration of
|
|
||||||
which slave is connected to which host.
|
|
||||||
|
|
||||||
The above does of course not apply to hostless protocols (like file).
|
|
||||||
(They will never change host).
|
|
||||||
|
|
||||||
Apart from a 'hard limit' on the number of slaves/host we can have
|
|
||||||
a 'soft limit'. E.g. upon connection to a HTTP 1.1 server, the web-
|
|
||||||
server tells the slave the number of parallel connections allowed.
|
|
||||||
THe simplest solution seems to be to treat 'soft limits' the same
|
|
||||||
as 'hard limits'. This means that the slave has to communicate the
|
|
||||||
'soft limit' to the daemon.
|
|
||||||
|
|
||||||
Jobs using multiple slaves.
|
|
||||||
|
|
||||||
If a job needs multiple slaves in parallel (e.g. copying a file from
|
|
||||||
a web-server to a ftp-server or browsing a tar-file on a ftp-site)
|
|
||||||
we must make sure to request the daemon for all slaves together since
|
|
||||||
otherwise there is a risk of deadlock.
|
|
||||||
|
|
||||||
(If two applications both need a 'pop3' and a 'ftp' slave for a single
|
|
||||||
job and only a single slave/host is allowed for pop3 and ftp, we must
|
|
||||||
prevent giving the single pop3 slave to application #1 and the single
|
|
||||||
ftp slave to application #2. Both applications will then wait till the
|
|
||||||
end of times till they get the other slave so that they can start the
|
|
||||||
job. (This is a quite unlikely situation, but nevertheless possible))
|
|
||||||
|
|
||||||
|
|
||||||
File Operations:
|
|
||||||
listRecursive is implemented as listDir and finding out if in the result
|
|
||||||
is a directory. If there is, another listDir job is issued. As listDir
|
|
||||||
is a readonly operation it fails when a directory isn't readable
|
|
||||||
.. but the main job goes on and discards the error, because
|
|
||||||
bIgnoreSubJobsError is true, which is what we want (David)
|
|
||||||
|
|
||||||
del is implemented as listRecursive, removing all files and removing all
|
|
||||||
empty directories. This basically means if one directory isn't readable
|
|
||||||
we don't remove it as listRecursive didn't find it. But the del will later
|
|
||||||
on try to remove it's parent directory and fail. But there are cases when
|
|
||||||
it would be possible to delete the dir in chmod the dir before. On the
|
|
||||||
other hand del("/") shouldn't list the whole file system and remove all
|
|
||||||
user owned files just to find out it can't remove everything else (this
|
|
||||||
basically means we have to take care of things we can remove before we try)
|
|
||||||
|
|
||||||
... Well, rm -rf / refuses to do anything, so we should just do the same:
|
|
||||||
use a listRecursive with bIgnoreSubJobsError = false. If anything can't
|
|
||||||
be removed, we just abort. (David)
|
|
||||||
|
|
||||||
... My concern was more that the fact we can list / doesn't mean we can
|
|
||||||
remove it. So we shouldn't remove everything we could list without checking
|
|
||||||
we can. But then the question arises how do we check whether we can remove it?
|
|
||||||
(Stephan)
|
|
||||||
|
|
||||||
... I was wrong, rm -rf /, even as a user, lists everything and removes
|
|
||||||
everything it can (don't try this at home!). I don't think we can do
|
|
||||||
better, unless we add a protocol-dependent "canDelete(path)", which is
|
|
||||||
_really_ not easy to implement, whatever protocol. (David)
|
|
||||||
|
|
||||||
|
|
||||||
Lib docu
|
|
||||||
========
|
|
||||||
|
|
||||||
mkdir: ...
|
|
||||||
|
|
||||||
rmdir: ...
|
|
||||||
|
|
||||||
chmod: ...
|
|
||||||
|
|
||||||
special: ...
|
|
||||||
|
|
||||||
stat: ...
|
|
||||||
|
|
||||||
get is implemented as TransferJob. Clients get 'data' signals with the data.
|
|
||||||
A data block of zero size indicates end of data (EOD)
|
|
||||||
|
|
||||||
put is implemented as TransferJob. Clients have to connect to the
|
|
||||||
'dataReq' signal. The slave will call you when it needs your data.
|
|
||||||
|
|
||||||
mimetype: ...
|
|
||||||
|
|
||||||
file_copy: copies a single file, either using CMD_COPY if the slave
|
|
||||||
supports that or get & put otherwise.
|
|
||||||
|
|
||||||
file_move: moves a single file, either using CMD_RENAME if the slave
|
|
||||||
supports that, CMD_COPY + del otherwise, or eventually
|
|
||||||
get & put & del.
|
|
||||||
|
|
||||||
file_delete: delete a single file.
|
|
||||||
|
|
||||||
copy: copies a file or directory, recursively if the latter
|
|
||||||
|
|
||||||
move: moves a file or directory, recursively if the latter
|
|
||||||
|
|
||||||
del: deletes a file or directory, recursively if the latter
|
|
||||||
|
|
||||||
PROGRESS DISPLAYING : [this is outdated, and describes the kde3 situation]
|
|
||||||
=====================
|
|
||||||
Taj brought up the idea of delegating all progress information to an extern
|
|
||||||
GUI daemon which could be provided in several implementations - examples
|
|
||||||
are popup dialogs (most are annoyed by them, like me :) or a kicker applet
|
|
||||||
or something completely different. This would also remove the dependency on
|
|
||||||
libkdeui (I hope).
|
|
||||||
Conclusion: kuiserver is this single GUI daemon, but the dependency on
|
|
||||||
libkdeui couldn't be removed (for many reasons, including rename/skip dialogs)
|
|
||||||
|
|
||||||
A. progress handling
|
|
||||||
---------------------
|
|
||||||
There will be two ways how the application can display progress :
|
|
||||||
|
|
||||||
1. regular apps will use NetAccess for all kio operations and will not care
|
|
||||||
about progress handling :
|
|
||||||
- NetAccess creates Job
|
|
||||||
- NetAccess creates JobObserver that will connect to the Job's signals and
|
|
||||||
pass them via dcop to the running GUI Progress Server
|
|
||||||
|
|
||||||
2. apps that want to do some handling with progress dialogs like Caitoo or
|
|
||||||
KMail :
|
|
||||||
- app creates Job
|
|
||||||
- app creates a progress dialog : this should be a ProgressBase descendant
|
|
||||||
e.g. StatusProgress or custom progress dialog
|
|
||||||
- app calls progress->setJob( job ) in order to connect job's signals with
|
|
||||||
progress dialog slots
|
|
||||||
|
|
||||||
B. customized progress dialogs
|
|
||||||
-------------------------------
|
|
||||||
This will be similar to what we had before.
|
|
||||||
|
|
||||||
- ProgressBase class that all other dialogs will inherit.
|
|
||||||
will contain an initialization method setJob( KIO::Job*) for apps of the
|
|
||||||
second class (see A.2 above), that will connect job's signals to dialog's
|
|
||||||
slots
|
|
||||||
|
|
||||||
- DefaultProgress ( former KIOSimpleProgressDialog ) that will be used for
|
|
||||||
regular progress dialogs created by GUI Progress Server
|
|
||||||
|
|
||||||
- StatusProgress ( former KIOLittleProgressDialog ) that can be used for
|
|
||||||
embedding in status bar
|
|
||||||
|
|
||||||
C. GUI Progress Server
|
|
||||||
-----------------------
|
|
||||||
This is a special progress server.
|
|
||||||
- createProgress() will either create a DefaultProgress dialog or add new entry
|
|
||||||
in a ListProgress ( an all-jobs-in-one progress dialog )
|
|
||||||
- after receiving signals from the JobObserver via DBus it will call
|
|
||||||
appropriate method of progress dialog ( either in DefaultProgress or ListProgress )
|
|
||||||
- ListProgres can be a Caitoo style dialog, kicker applet or both in one.
|
|
||||||
|
|
||||||
D. Some notes
|
|
||||||
--------------
|
|
||||||
1. most of the apps will not care at all about the progress display
|
|
||||||
2. user will be able to choose whether he wants to see separate progress
|
|
||||||
dialogs or all-in-one ListProgress dialog
|
|
||||||
3. developers can create their custom progress dialogs that inherit
|
|
||||||
ProgressBase and do any manipulation with a dialog if they use a second
|
|
||||||
approach ( see A.2 above )
|
|
||||||
|
|
||||||
|
|
||||||
Streaming [didn't work well, has been removed]
|
|
||||||
---------
|
|
||||||
|
|
||||||
1. We currently support a streaming "GET": e.g. file:/tmp/test.gz#gzip:/
|
|
||||||
works. The following should also work: file:/tmp/test.gz.gz#gzip:/#gzip:/
|
|
||||||
The current approach makes a TransferJob for gzip:/ and then adds a
|
|
||||||
subjob for "file:/tmp/test.gz.gz#gzip:/" which itself adds a subjob
|
|
||||||
for "file:/tmp/test.gz.gz".
|
|
||||||
2. This doesn't extend very well to PUT, because there the order should
|
|
||||||
basically be the other way around, but the "input" to the job as a whole
|
|
||||||
should go to the "gzip:/" job, not to the "file:/tmp/test.gz.gz."
|
|
||||||
It would probably be easier to implement such a job in the way the
|
|
||||||
current "CopyJob" is done. Have a Job and make all sub-urls sub-jobs of
|
|
||||||
this Job.
|
|
||||||
3. As a result of 1. COPY FROM an url like file:/tmp/test.gz#gzip:/ should
|
|
||||||
work. COPY TO does not, because that would require PUT.
|
|
||||||
|
|
||||||
|
|
||||||
Resuming
|
|
||||||
--------
|
|
||||||
|
|
||||||
A rough note for now, just to have this somewhere :
|
|
||||||
(PJ=put-job, GJ=get-job)
|
|
||||||
|
|
||||||
PJ can't resume:
|
|
||||||
PJ-->app: canResume(0) (emitted by dataReq)
|
|
||||||
GJ-->app: data()
|
|
||||||
PJ-->app: dataReq()
|
|
||||||
app->PJ: data()
|
|
||||||
|
|
||||||
PJ can resume but GJ can't resume:
|
|
||||||
PJ-->app: canResume(xx)
|
|
||||||
app->GJ: start job with "resume=xxx" metadata.
|
|
||||||
GJ-->app: data()
|
|
||||||
PJ-->app: dataReq()
|
|
||||||
app->PJ: data()
|
|
||||||
|
|
||||||
PJ can resume and GJ can resume:
|
|
||||||
PJ-->app: canResume(xx)
|
|
||||||
app->GJ: start job with "resume=xxx" metadata.
|
|
||||||
GJ-->app: canResume(xx)
|
|
||||||
GJ-->app: data()
|
|
||||||
PJ-->app: dataReq()
|
|
||||||
app->PJ: canResume(xx)
|
|
||||||
app->PJ: data()
|
|
||||||
|
|
||||||
So when the slave supports resume for "put" it has to check after the first
|
|
||||||
dataRequest() whether it has got a canResume() back from the app. If it did
|
|
||||||
it must resume. Otherwise it must start from 0.
|
|
||||||
|
|
||||||
Protocols
|
|
||||||
=========
|
|
||||||
|
|
||||||
Most KIO slaves (but not all) are implementing internet protocols.
|
|
||||||
In this case, the slave name matches the URI name for the protocol.
|
|
||||||
A list of such URIs can be found here, as per RFC 4395:
|
|
||||||
http://www.iana.org/assignments/uri-schemes.html
|
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
|
|
||||||
konq_run / krun should determine the mimetype by actually
|
|
||||||
getting the contents of the URL. It should then put the slave
|
|
||||||
on hold and tell the job-scheduler which request the
|
|
||||||
slave is currently handling. (Status: implemented in konq_run)
|
|
||||||
|
|
||||||
Now krun/konq_run should determine which client should process the
|
|
||||||
result of the request.
|
|
||||||
|
|
||||||
* When the client belongs to the same process, no action needs to be
|
|
||||||
taken. When a new job is created for the request which is on hold the
|
|
||||||
existing slave will be re-used and the request resumed.
|
|
||||||
(Status: implemented)
|
|
||||||
|
|
||||||
* When the client is an external process, the on-hold-slave should be
|
|
||||||
removed from the job-scheduler and should connect itself with
|
|
||||||
klauncher. This is hard because it must ensure that the external
|
|
||||||
program does not request the slave before it has been transfered to
|
|
||||||
klauncher. (Status: to be done)
|
|
||||||
|
|
||||||
* When a slave is on hold but not used for a certain period of time,
|
|
||||||
or, when another slave is put on hold, the slave should be killed.
|
|
||||||
(Status: almost done)
|
|
||||||
|
|
||||||
=====
|
|
||||||
|
|
||||||
The slave must emit "mimetype" during a GET before the first data is send.
|
|
||||||
|
|
||||||
It may wait with sending "mimetype" until it has enough data to
|
|
||||||
determine the mimetype, but it should not pass any data along before it has
|
|
||||||
send the mimetype.
|
|
||||||
|
|
||||||
Currently only http _always_ sends a mimetype.
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue