mirror of
https://bitbucket.org/smil3y/kdelibs.git
synced 2025-02-23 18:32:49 +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
|
||||
KWidgetJobTracker
|
||||
KDynamicJobTracker
|
||||
KUiServerJobTracker
|
||||
KPlasmaJobTracker
|
||||
KPixmapSequence
|
||||
KPixmapSequenceWidget
|
||||
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/kabstractwidgetjobtracker.cpp
|
||||
jobs/kwidgetjobtracker.cpp
|
||||
jobs/kuiserverjobtracker.cpp
|
||||
jobs/kplasmajobtracker.cpp
|
||||
jobs/kdynamicjobtracker.cpp
|
||||
kernel/kapplication.cpp
|
||||
kernel/kuniqueapplication.cpp
|
||||
|
@ -250,13 +250,6 @@ if (X11_Xkb_FOUND AND X11_Xkbfile_FOUND)
|
|||
)
|
||||
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_source_files_properties(${kglobalaccel_xml} PROPERTIES INCLUDE "kglobalshortcutinfo_p.h")
|
||||
qt4_add_dbus_interface(kdeui_LIB_SRCS ${kglobalaccel_xml} kglobalaccel_interface )
|
||||
|
@ -407,7 +400,7 @@ install(
|
|||
jobs/kdialogjobuidelegate.h
|
||||
jobs/kabstractwidgetjobtracker.h
|
||||
jobs/kwidgetjobtracker.h
|
||||
jobs/kuiserverjobtracker.h
|
||||
jobs/kplasmajobtracker.h
|
||||
jobs/kdynamicjobtracker.h
|
||||
kernel/kapplication.h
|
||||
kernel/kuniqueapplication.h
|
||||
|
@ -518,10 +511,3 @@ install(
|
|||
PROGRAMS preparetips
|
||||
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 <kuiserverjobtracker.h>
|
||||
#include <kplasmajobtracker.h>
|
||||
#include <kwidgetjobtracker.h>
|
||||
#include <kjobtrackerinterface.h>
|
||||
#include <kdebug.h>
|
||||
|
@ -32,7 +32,7 @@
|
|||
|
||||
struct AllTrackers
|
||||
{
|
||||
KUiServerJobTracker *kuiserverTracker;
|
||||
KPlasmaJobTracker *plasmaTracker;
|
||||
KWidgetJobTracker *widgetTracker;
|
||||
};
|
||||
|
||||
|
@ -40,18 +40,18 @@ class KDynamicJobTracker::Private
|
|||
{
|
||||
public:
|
||||
Private()
|
||||
: kuiserverTracker(nullptr),
|
||||
: plasmaTracker(nullptr),
|
||||
widgetTracker(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
~Private()
|
||||
{
|
||||
delete kuiserverTracker;
|
||||
delete plasmaTracker;
|
||||
delete widgetTracker;
|
||||
}
|
||||
|
||||
KUiServerJobTracker *kuiserverTracker;
|
||||
KPlasmaJobTracker *plasmaTracker;
|
||||
KWidgetJobTracker *widgetTracker;
|
||||
QMap<KJob*, AllTrackers> trackers;
|
||||
};
|
||||
|
@ -69,19 +69,16 @@ KDynamicJobTracker::~KDynamicJobTracker()
|
|||
|
||||
void KDynamicJobTracker::registerJob(KJob *job)
|
||||
{
|
||||
if (!d->kuiserverTracker) {
|
||||
d->kuiserverTracker = new KUiServerJobTracker();
|
||||
if (!d->plasmaTracker) {
|
||||
d->plasmaTracker = new KPlasmaJobTracker();
|
||||
}
|
||||
|
||||
d->trackers[job].kuiserverTracker = d->kuiserverTracker;
|
||||
d->trackers[job].kuiserverTracker->registerJob(job);
|
||||
d->trackers[job].plasmaTracker = d->plasmaTracker;
|
||||
d->trackers[job].plasmaTracker->registerJob(job);
|
||||
|
||||
QDBusInterface interface("org.kde.kuiserver", "/JobViewServer", "",
|
||||
QDBusConnection::sessionBus(), this);
|
||||
QDBusReply<bool> reply = interface.call("requiresJobTracker");
|
||||
|
||||
if (reply.isValid() && reply.value()) {
|
||||
//create a widget tracker in addition to kuiservertracker.
|
||||
QDBusInterface interface("org.kde.plasma-desktop", "/JobTracker", "org.kde.JobTracker", QDBusConnection::sessionBus(), this);
|
||||
if (!interface.isValid()) {
|
||||
// create a widget tracker in addition to KPlasmaJobTracker.
|
||||
if (!d->widgetTracker) {
|
||||
d->widgetTracker = new KWidgetJobTracker();
|
||||
}
|
||||
|
@ -89,21 +86,21 @@ void KDynamicJobTracker::registerJob(KJob *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)
|
||||
{
|
||||
KUiServerJobTracker *kuiserverTracker = d->trackers[job].kuiserverTracker;
|
||||
KPlasmaJobTracker *plasmaTracker = d->trackers[job].plasmaTracker;
|
||||
KWidgetJobTracker *widgetTracker = d->trackers[job].widgetTracker;
|
||||
|
||||
if (!(widgetTracker || kuiserverTracker)) {
|
||||
if (!(widgetTracker || plasmaTracker)) {
|
||||
kWarning() << "Tried to unregister a kio job that hasn't been registered.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (kuiserverTracker) {
|
||||
kuiserverTracker->unregisterJob(job);
|
||||
if (plasmaTracker) {
|
||||
plasmaTracker->unregisterJob(job);
|
||||
}
|
||||
if (widgetTracker) {
|
||||
widgetTracker->unregisterJob(job);
|
||||
|
|
|
@ -25,14 +25,12 @@
|
|||
|
||||
/**
|
||||
* 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
|
||||
* available. This way, we have the old dialogs as fallback when the user doesn't use a kuiserver
|
||||
* applet or application.
|
||||
* plasma isn't available on the DBus, or to the KPlasmaJobTracker, if a plasma is available. This
|
||||
* way, we have the old dialogs as fallback when the user doesn't use a plasma applet.
|
||||
*/
|
||||
class KDEUI_EXPORT KDynamicJobTracker : public KJobTrackerInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new KDynamicJobTracker
|
||||
|
@ -48,8 +46,7 @@ public:
|
|||
|
||||
public Q_SLOTS:
|
||||
/**
|
||||
* Register a new job in this tracker. This call will get forwarded to either KWidgetJobTracker
|
||||
* or KUiServerJobTracker, depending on the availability of the Kuiserver.
|
||||
* Register a new job in this tracker.
|
||||
*
|
||||
* @param job the job to register
|
||||
*/
|
||||
|
@ -67,4 +64,4 @@ private:
|
|||
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
|
||||
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,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
|
@ -16,52 +17,30 @@
|
|||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef KUISERVERJOBTRACKER_H
|
||||
#define KUISERVERJOBTRACKER_H
|
||||
#ifndef KPLASMAJOBTRACKER_H
|
||||
#define KPLASMAJOBTRACKER_H
|
||||
|
||||
#include <kdeui_export.h>
|
||||
#include <kjobtrackerinterface.h>
|
||||
|
||||
class KJob;
|
||||
class KPlasmaJobTrackerPrivate;
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new KJobTrackerInterface
|
||||
*
|
||||
* @param parent the parent object
|
||||
*/
|
||||
KUiServerJobTracker(QObject *parent=0);
|
||||
KPlasmaJobTracker(QObject *parent = nullptr);
|
||||
virtual ~KPlasmaJobTracker();
|
||||
|
||||
/**
|
||||
* Destroys a KJobTrackerInterface
|
||||
*/
|
||||
virtual ~KUiServerJobTracker();
|
||||
|
||||
/**
|
||||
* Register a new job in this tracker.
|
||||
*
|
||||
* @param job the job to register
|
||||
*/
|
||||
virtual void registerJob(KJob *job);
|
||||
|
||||
/**
|
||||
* Unregister a job from this tracker.
|
||||
*
|
||||
* @param job the job to unregister
|
||||
*/
|
||||
virtual void unregisterJob(KJob *job);
|
||||
|
||||
protected Q_SLOTS:
|
||||
/**
|
||||
* The following slots are inherited from KJobTrackerInterface.
|
||||
*/
|
||||
virtual void finished(KJob *job);
|
||||
virtual void suspended(KJob *job);
|
||||
virtual void resumed(KJob *job);
|
||||
|
@ -69,16 +48,12 @@ protected Q_SLOTS:
|
|||
const QPair<QString, QString> &field1,
|
||||
const QPair<QString, QString> &field2);
|
||||
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 speed(KJob *job, unsigned long value);
|
||||
|
||||
private:
|
||||
class Private;
|
||||
Private *const d;
|
||||
KPlasmaJobTrackerPrivate *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());
|
||||
setMaximumHeight(sizeHint().height());
|
||||
|
||||
setWindowTitle(i18n("Progress Dialog")); // show something better than kuiserver
|
||||
setWindowTitle(i18n("Progress Dialog"));
|
||||
}
|
||||
|
||||
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