Drop dependency of KIO from kdeconnectcore
Use QNetworkAccessManager for storing the files we receive instead of directly KIO, then provide the KIO-based QNetworkAccessManager from the daemon. This way we'll still get the KIO network-transparency, but the library only depenends on QtNetwork, which will be easier to get in some platforms. After this change, we only depend on KConfig, KI18n and KCoreAddons, which are tier1 and really easy to work with on any platform. REVIEW: 123325
This commit is contained in:
parent
ba4c87abc1
commit
11996f56ca
8 changed files with 77 additions and 101 deletions
|
@ -11,7 +11,7 @@ find_package(ECM 0.0.9 REQUIRED NO_MODULE)
|
||||||
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR} ${CMAKE_SOURCE_DIR}/cmake)
|
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR} ${CMAKE_SOURCE_DIR}/cmake)
|
||||||
|
|
||||||
find_package(Qt5 5.2 REQUIRED COMPONENTS Quick Test)
|
find_package(Qt5 5.2 REQUIRED COMPONENTS Quick Test)
|
||||||
find_package(KF5 REQUIRED COMPONENTS I18n KIO ConfigWidgets DBusAddons KCMUtils IconThemes)
|
find_package(KF5 REQUIRED COMPONENTS I18n ConfigWidgets DBusAddons IconThemes)
|
||||||
find_package(Qca-qt5 2.1.0 REQUIRED)
|
find_package(Qca-qt5 2.1.0 REQUIRED)
|
||||||
|
|
||||||
include_directories(${CMAKE_SOURCE_DIR})
|
include_directories(${CMAKE_SOURCE_DIR})
|
||||||
|
|
|
@ -33,7 +33,7 @@ add_library(kdeconnectcore ${kdeconnectcore_SRCS})
|
||||||
target_link_libraries(kdeconnectcore
|
target_link_libraries(kdeconnectcore
|
||||||
PUBLIC
|
PUBLIC
|
||||||
Qt5::Network
|
Qt5::Network
|
||||||
KF5::KIOCore
|
KF5::CoreAddons
|
||||||
qca-qt5
|
qca-qt5
|
||||||
PRIVATE
|
PRIVATE
|
||||||
Qt5::DBus
|
Qt5::DBus
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <QNetworkConfigurationManager>
|
#include <QNetworkConfigurationManager>
|
||||||
#include <QNetworkAccessManager>
|
#include <QNetworkAccessManager>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QPointer>
|
||||||
|
|
||||||
#include "core_debug.h"
|
#include "core_debug.h"
|
||||||
#include "kdeconnectconfig.h"
|
#include "kdeconnectconfig.h"
|
||||||
|
@ -185,6 +186,15 @@ QString Daemon::announcedName()
|
||||||
return KdeConnectConfig::instance()->name();
|
return KdeConnectConfig::instance()->name();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QNetworkAccessManager* Daemon::networkAccessManager()
|
||||||
|
{
|
||||||
|
static QPointer<QNetworkAccessManager> manager;
|
||||||
|
if (!manager) {
|
||||||
|
manager = new QNetworkAccessManager(this);
|
||||||
|
}
|
||||||
|
return manager;
|
||||||
|
}
|
||||||
|
|
||||||
Daemon::~Daemon()
|
Daemon::~Daemon()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
class NetworkPackage;
|
class NetworkPackage;
|
||||||
class DeviceLink;
|
class DeviceLink;
|
||||||
class Device;
|
class Device;
|
||||||
|
class QNetworkAccessManager;
|
||||||
|
|
||||||
class KDECONNECTCORE_EXPORT Daemon
|
class KDECONNECTCORE_EXPORT Daemon
|
||||||
: public QObject
|
: public QObject
|
||||||
|
@ -62,6 +63,7 @@ public Q_SLOTS:
|
||||||
|
|
||||||
virtual void requestPairing(Device *d) = 0;
|
virtual void requestPairing(Device *d) = 0;
|
||||||
virtual void reportError(const QString &title, const QString &description) = 0;
|
virtual void reportError(const QString &title, const QString &description) = 0;
|
||||||
|
virtual QNetworkAccessManager* networkAccessManager();
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
Q_SCRIPTABLE void deviceAdded(const QString& id);
|
Q_SCRIPTABLE void deviceAdded(const QString& id);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2013 Albert Vaca <albertvaka@gmail.com>
|
* Copyright 2013 Albert Vaca <albertvaka@gmail.com>
|
||||||
|
* Copyright 2015 Aleix Pol i Gonzalez <aleixpol@kde.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License as
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
@ -19,6 +20,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "filetransferjob.h"
|
#include "filetransferjob.h"
|
||||||
|
#include "daemon.h"
|
||||||
#include <core_debug.h>
|
#include <core_debug.h>
|
||||||
|
|
||||||
#include <qalgorithms.h>
|
#include <qalgorithms.h>
|
||||||
|
@ -30,28 +32,25 @@
|
||||||
FileTransferJob::FileTransferJob(const QSharedPointer<QIODevice>& origin, qint64 size, const QUrl& destination)
|
FileTransferJob::FileTransferJob(const QSharedPointer<QIODevice>& origin, qint64 size, const QUrl& destination)
|
||||||
: KJob()
|
: KJob()
|
||||||
, mOrigin(origin)
|
, mOrigin(origin)
|
||||||
, mDestinationJob(0)
|
, mReply(Q_NULLPTR)
|
||||||
, mDeviceName("KDE Connect")
|
, mDeviceName("KDE Connect") //TODO: Actually fetch the device name
|
||||||
, mDestination(destination)
|
, mDestination(destination)
|
||||||
, mSpeedBytes(0)
|
, mSpeedBytes(0)
|
||||||
, mSize(size)
|
|
||||||
, mWritten(0)
|
, mWritten(0)
|
||||||
{
|
{
|
||||||
|
Q_ASSERT(mOrigin);
|
||||||
if (mDestination.scheme().isEmpty()) {
|
if (mDestination.scheme().isEmpty()) {
|
||||||
qWarning() << "Destination QUrl" << mDestination << "lacks a scheme. Setting its scheme to 'file'.";
|
qWarning() << "Destination QUrl" << mDestination << "lacks a scheme. Setting its scheme to 'file'.";
|
||||||
mDestination.setScheme("file");
|
mDestination.setScheme("file");
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_ASSERT(destination.isLocalFile());
|
if (size >= 0) {
|
||||||
|
setTotalAmount(Bytes, size);
|
||||||
|
}
|
||||||
setCapabilities(Killable);
|
setCapabilities(Killable);
|
||||||
qCDebug(KDECONNECT_CORE) << "FileTransferJob Downloading payload to" << destination;
|
qCDebug(KDECONNECT_CORE) << "FileTransferJob Downloading payload to" << destination;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileTransferJob::openFinished(KJob* job)
|
|
||||||
{
|
|
||||||
qCDebug(KDECONNECT_CORE) << job->errorString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileTransferJob::start()
|
void FileTransferJob::start()
|
||||||
{
|
{
|
||||||
QMetaObject::invokeMethod(this, "doStart", Qt::QueuedConnection);
|
QMetaObject::invokeMethod(this, "doStart", Qt::QueuedConnection);
|
||||||
|
@ -62,10 +61,10 @@ void FileTransferJob::doStart()
|
||||||
{
|
{
|
||||||
description(this, i18n("Receiving file over KDE-Connect"),
|
description(this, i18n("Receiving file over KDE-Connect"),
|
||||||
QPair<QString, QString>(i18nc("File transfer origin", "From"),
|
QPair<QString, QString>(i18nc("File transfer origin", "From"),
|
||||||
QString(mDeviceName))
|
mDeviceName)
|
||||||
);
|
);
|
||||||
QUrl destCheck = mDestination;
|
|
||||||
if (destCheck.isLocalFile() && QFile::exists(destCheck.toLocalFile())) {
|
if (mDestination.isLocalFile() && QFile::exists(mDestination.toLocalFile())) {
|
||||||
setError(2);
|
setError(2);
|
||||||
setErrorText(i18n("Filename already present"));
|
setErrorText(i18n("Filename already present"));
|
||||||
emitResult();
|
emitResult();
|
||||||
|
@ -76,7 +75,6 @@ void FileTransferJob::doStart()
|
||||||
|
|
||||||
void FileTransferJob::startTransfer()
|
void FileTransferJob::startTransfer()
|
||||||
{
|
{
|
||||||
setTotalAmount(Bytes, mSize);
|
|
||||||
setProcessedAmount(Bytes, 0);
|
setProcessedAmount(Bytes, 0);
|
||||||
mTime = QTime::currentTime();
|
mTime = QTime::currentTime();
|
||||||
description(this, i18n("Receiving file over KDE-Connect"),
|
description(this, i18n("Receiving file over KDE-Connect"),
|
||||||
|
@ -84,90 +82,32 @@ void FileTransferJob::startTransfer()
|
||||||
QString(mDeviceName)),
|
QString(mDeviceName)),
|
||||||
QPair<QString, QString>(i18nc("File transfer destination", "To"), mDestination.toLocalFile()));
|
QPair<QString, QString>(i18nc("File transfer destination", "To"), mDestination.toLocalFile()));
|
||||||
|
|
||||||
mDestinationJob = KIO::open(mDestination, QIODevice::WriteOnly);
|
mReply = Daemon::instance()->networkAccessManager()->put(QNetworkRequest(mDestination), mOrigin.data());
|
||||||
QFile(mDestination.toLocalFile()).open(QIODevice::WriteOnly | QIODevice::Truncate); //KIO won't create the file if it doesn't exist
|
connect(mReply, &QNetworkReply::uploadProgress, this, [this](qint64 bytesSent, qint64 /*bytesTotal*/) {
|
||||||
connect(mDestinationJob, SIGNAL(open(KIO::Job*)), this, SLOT(open(KIO::Job*)));
|
setProcessedAmount(Bytes, bytesSent);
|
||||||
connect(mDestinationJob, SIGNAL(result(KJob*)), this, SLOT(openFinished(KJob*)));
|
emitSpeed(bytesSent/mTime.elapsed());
|
||||||
|
});
|
||||||
//Open destination file
|
connect(mReply, &QNetworkReply::finished, this, &FileTransferJob::transferFinished);
|
||||||
mDestinationJob->start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileTransferJob::open(KIO::Job* job)
|
void FileTransferJob::transferFinished()
|
||||||
{
|
{
|
||||||
Q_UNUSED(job);
|
|
||||||
|
|
||||||
//qCDebug(KDECONNECT_CORE) << "FileTransferJob open";
|
|
||||||
|
|
||||||
if (!mOrigin) {
|
|
||||||
qCDebug(KDECONNECT_CORE) << "FileTransferJob: Origin is null";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Open source file
|
|
||||||
mOrigin->open(QIODevice::ReadOnly);
|
|
||||||
Q_ASSERT(mOrigin->isOpen());
|
|
||||||
|
|
||||||
connect(mOrigin.data(), SIGNAL(readyRead()),this, SLOT(readyRead()));
|
|
||||||
connect(mOrigin.data(), SIGNAL(aboutToClose()),this, SLOT(sourceFinished()));
|
|
||||||
if (mOrigin->bytesAvailable() > 0) readyRead();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileTransferJob::readyRead()
|
|
||||||
{
|
|
||||||
int bytes = qMin(qint64(4096), mOrigin->bytesAvailable());
|
|
||||||
QByteArray data = mOrigin->read(bytes);
|
|
||||||
mDestinationJob->write(data);
|
|
||||||
mWritten += data.size();
|
|
||||||
setProcessedAmount(Bytes, mWritten);
|
|
||||||
|
|
||||||
//qCDebug(KDECONNECT_CORE) << "readyRead" << mSize << mWritten << bytes;
|
|
||||||
|
|
||||||
if (mSize > -1) {
|
|
||||||
//If a least 1 second has passed since last update
|
|
||||||
int secondsSinceLastTime = mTime.secsTo(QTime::currentTime());
|
|
||||||
if (secondsSinceLastTime > 0 && mSpeedBytes > 0) {
|
|
||||||
float speed = (mWritten - mSpeedBytes) / float(secondsSinceLastTime);
|
|
||||||
emitSpeed(speed);
|
|
||||||
|
|
||||||
mTime = QTime::currentTime();
|
|
||||||
mSpeedBytes = mWritten;
|
|
||||||
} else if(mSpeedBytes == 0) {
|
|
||||||
mSpeedBytes = mWritten;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mSize > -1 && mWritten >= mSize) { //At the end or expected size reached
|
|
||||||
mOrigin->close();
|
|
||||||
//sourceFinished();
|
|
||||||
} else if (mOrigin->bytesAvailable() > 0) {
|
|
||||||
QMetaObject::invokeMethod(this, "readyRead", Qt::QueuedConnection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileTransferJob::sourceFinished()
|
|
||||||
{
|
|
||||||
//Make sure we do not enter this function again
|
|
||||||
disconnect(mOrigin.data(), SIGNAL(aboutToClose()),this, SLOT(sourceFinished()));
|
|
||||||
|
|
||||||
//TODO: MD5-check the file
|
//TODO: MD5-check the file
|
||||||
if (mSize > -1 && mWritten != mSize) {
|
if (mReply->error()) {
|
||||||
qCDebug(KDECONNECT_CORE) << "Received incomplete file (" << mWritten << " of " << mSize << " bytes)";
|
qCDebug(KDECONNECT_CORE) << "Couldn't transfer the file successfully" << mReply->errorString();
|
||||||
setError(1);
|
setError(mReply->error());
|
||||||
setErrorText(i18n("Received incomplete file"));
|
setErrorText(i18n("Received incomplete file: %1", mReply->errorString()));
|
||||||
} else {
|
} else {
|
||||||
qCDebug(KDECONNECT_CORE) << "Finished transfer" << mDestinationJob->url();
|
qCDebug(KDECONNECT_CORE) << "Finished transfer" << mDestination;
|
||||||
}
|
}
|
||||||
mDestinationJob->close();
|
|
||||||
mDestinationJob->deleteLater();
|
|
||||||
emitResult();
|
emitResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileTransferJob::doKill()
|
bool FileTransferJob::doKill()
|
||||||
{
|
{
|
||||||
if (mDestinationJob) {
|
if (mReply) {
|
||||||
mDestinationJob->close();
|
mReply->close();
|
||||||
}
|
}
|
||||||
if (mOrigin) {
|
if (mOrigin) {
|
||||||
mOrigin->close();
|
mOrigin->close();
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2013 Albert Vaca <albertvaka@gmail.com>
|
* Copyright 2013 Albert Vaca <albertvaka@gmail.com>
|
||||||
|
* Copyright 2015 Aleix Pol i Gonzalez <aleixpol@kde.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License as
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
@ -28,39 +29,48 @@
|
||||||
|
|
||||||
#include <KJob>
|
#include <KJob>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <KIO/FileJob>
|
#include <QNetworkAccessManager>
|
||||||
#include <KIO/Job>
|
#include <QNetworkReply>
|
||||||
|
#include <QBuffer>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @short It will stream a device into a url destination
|
||||||
|
*
|
||||||
|
* Given a QIODevice, the file transfer job will use the system's QNetworkAccessManager
|
||||||
|
* for putting the stream into the requested location.
|
||||||
|
*/
|
||||||
class FileTransferJob
|
class FileTransferJob
|
||||||
: public KJob
|
: public KJob
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @p origin specifies the data to read from.
|
||||||
|
* @p size specifies the expected size of the stream we're reading.
|
||||||
|
* @p destination specifies where these contents should be stored
|
||||||
|
*/
|
||||||
FileTransferJob(const QSharedPointer<QIODevice>& origin, qint64 size, const QUrl &destination);
|
FileTransferJob(const QSharedPointer<QIODevice>& origin, qint64 size, const QUrl &destination);
|
||||||
virtual void start();
|
virtual void start() Q_DECL_OVERRIDE;
|
||||||
QUrl destination() const { return mDestination; }
|
QUrl destination() const { return mDestination; }
|
||||||
void setDeviceName(const QString &deviceName) { mDeviceName = deviceName; }
|
void setDeviceName(const QString &deviceName) { mDeviceName = deviceName; }
|
||||||
|
|
||||||
public Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void doStart();
|
void doStart();
|
||||||
void readyRead();
|
|
||||||
void open(KIO::Job*);
|
|
||||||
void sourceFinished();
|
|
||||||
void openFinished(KJob*);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool doKill();
|
bool doKill() Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void startTransfer();
|
void startTransfer();
|
||||||
|
void transferFinished();
|
||||||
|
|
||||||
QSharedPointer<QIODevice> mOrigin;
|
QSharedPointer<QIODevice> mOrigin;
|
||||||
KIO::FileJob* mDestinationJob;
|
QNetworkReply* mReply;
|
||||||
QString mDeviceName;
|
QString mDeviceName;
|
||||||
QUrl mDestination;
|
QUrl mDestination;
|
||||||
QTime mTime;
|
QTime mTime;
|
||||||
qulonglong mSpeedBytes;
|
qulonglong mSpeedBytes;
|
||||||
qint64 mSize;
|
|
||||||
qint64 mWritten;
|
qint64 mWritten;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
project(kdeconnectd)
|
project(kdeconnectd)
|
||||||
|
|
||||||
find_package(KF5 REQUIRED COMPONENTS Notifications)
|
find_package(KF5 REQUIRED COMPONENTS Notifications KIO)
|
||||||
|
|
||||||
add_definitions(-DTRANSLATION_DOMAIN="kdeconnect-kded")
|
add_definitions(-DTRANSLATION_DOMAIN="kdeconnect-kded")
|
||||||
|
|
||||||
add_executable(kdeconnectd kdeconnectd.cpp)
|
add_executable(kdeconnectd kdeconnectd.cpp)
|
||||||
target_link_libraries(kdeconnectd kdeconnectcore KF5::DBusAddons KF5::Notifications KF5::I18n Qt5::Widgets)
|
target_link_libraries(kdeconnectd kdeconnectcore KF5::KIOWidgets KF5::DBusAddons KF5::Notifications KF5::I18n Qt5::Widgets)
|
||||||
|
|
||||||
configure_file(kdeconnectd.desktop.cmake ${CMAKE_CURRENT_BINARY_DIR}/kdeconnectd.desktop)
|
configure_file(kdeconnectd.desktop.cmake ${CMAKE_CURRENT_BINARY_DIR}/kdeconnectd.desktop)
|
||||||
configure_file(org.kde.kdeconnect.service.in ${CMAKE_CURRENT_BINARY_DIR}/org.kde.kdeconnect.service)
|
configure_file(org.kde.kdeconnect.service.in ${CMAKE_CURRENT_BINARY_DIR}/org.kde.kdeconnect.service)
|
||||||
|
|
|
@ -25,10 +25,12 @@
|
||||||
|
|
||||||
#include <QSocketNotifier>
|
#include <QSocketNotifier>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
|
|
||||||
#include <KDBusService>
|
#include <KDBusService>
|
||||||
#include <KNotification>
|
#include <KNotification>
|
||||||
#include <KLocalizedString>
|
#include <KLocalizedString>
|
||||||
|
#include <KIO/AccessManager>
|
||||||
|
|
||||||
#include "core/daemon.h"
|
#include "core/daemon.h"
|
||||||
#include "core/device.h"
|
#include "core/device.h"
|
||||||
|
@ -68,6 +70,7 @@ class DesktopDaemon : public Daemon
|
||||||
public:
|
public:
|
||||||
DesktopDaemon(QObject* parent = Q_NULLPTR)
|
DesktopDaemon(QObject* parent = Q_NULLPTR)
|
||||||
: Daemon(parent)
|
: Daemon(parent)
|
||||||
|
, m_nam(Q_NULLPTR)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void requestPairing(Device* d) Q_DECL_OVERRIDE
|
void requestPairing(Device* d) Q_DECL_OVERRIDE
|
||||||
|
@ -87,6 +90,17 @@ public:
|
||||||
{
|
{
|
||||||
KNotification::event(KNotification::Error, title, description);
|
KNotification::event(KNotification::Error, title, description);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QNetworkAccessManager* networkAccessManager() Q_DECL_OVERRIDE
|
||||||
|
{
|
||||||
|
if (!m_nam) {
|
||||||
|
m_nam = new KIO::AccessManager(this);
|
||||||
|
}
|
||||||
|
return m_nam;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QNetworkAccessManager* m_nam;
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
|
|
Loading…
Reference in a new issue