diff --git a/core/backends/lan/downloadjob.cpp b/core/backends/lan/downloadjob.cpp index ad7765c71..b51ff6cfd 100644 --- a/core/backends/lan/downloadjob.cpp +++ b/core/backends/lan/downloadjob.cpp @@ -20,30 +20,50 @@ #include "downloadjob.h" +#include + +#include +#include +#include +#include + +#include "lanlinkprovider.h" + DownloadJob::DownloadJob(const QHostAddress &address, const QVariantMap &transferInfo): KJob() { mAddress = address; mPort = transferInfo["port"].toInt(); - mSocket = QSharedPointer(new QTcpSocket); + mSocket = QSharedPointer(new QTcpSocket()); +} + +DownloadJob::~DownloadJob() +{ } void DownloadJob::start() { - //kDebug(kdeconnect_kded()) << "DownloadJob Start"; + //TODO: Timeout? + connect(mSocket.data(), &QAbstractSocket::disconnected, this, &DownloadJob::done); + connect(mSocket.data(), SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(done())); + //connect(mSocket.data(), &QAbstractSocket::connected, [=](){ qDebug() << "Connected"; }); + mSocket->connectToHost(mAddress, mPort, QIODevice::ReadOnly); - connect(mSocket.data(), SIGNAL(disconnected()), - this, SLOT(disconnected())); + + //mSocket->open(QIODevice::ReadOnly); + //TODO: Implement payload encryption somehow (create an intermediate iodevice to encrypt the payload here?) } -void DownloadJob::disconnected() +void DownloadJob::done() { - //kDebug(kdeconnect_kded()) << "DownloadJob End"; + if (mSocket->error()) { + qWarning(KDECONNECT_CORE) << mSocket->errorString(); + } emitResult(); + deleteLater(); } QSharedPointer DownloadJob::getPayload() { - //kDebug(kdeconnect_kded()) << "getPayload"; return mSocket.staticCast(); } diff --git a/core/backends/lan/downloadjob.h b/core/backends/lan/downloadjob.h index f5e0d08e1..ddc9c93f8 100644 --- a/core/backends/lan/downloadjob.h +++ b/core/backends/lan/downloadjob.h @@ -35,7 +35,8 @@ class DownloadJob Q_OBJECT public: DownloadJob(const QHostAddress &address, const QVariantMap &transferInfo); - virtual void start() override; + ~DownloadJob(); + void start() Q_DECL_OVERRIDE; QSharedPointer getPayload(); private: @@ -43,9 +44,8 @@ private: qint16 mPort; QSharedPointer mSocket; - private Q_SLOTS: - void disconnected(); + void done(); }; diff --git a/core/backends/lan/lanlinkprovider.h b/core/backends/lan/lanlinkprovider.h index 88d3f1d9f..033877db9 100644 --- a/core/backends/lan/lanlinkprovider.h +++ b/core/backends/lan/lanlinkprovider.h @@ -26,7 +26,6 @@ #include #include "../linkprovider.h" -#include "netaddress.h" class LanLinkProvider : public LinkProvider diff --git a/core/backends/lan/netaddress.h b/core/backends/lan/netaddress.h deleted file mode 100644 index 6704dbc5d..000000000 --- a/core/backends/lan/netaddress.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright 2013 Albert Vaca - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License or (at your option) version 3 or any later version - * accepted by the membership of KDE e.V. (or its successor approved - * by the membership of KDE e.V.), which shall act as a proxy - * defined in Section 14 of version 3 of the license. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef NETADDRESS_H -#define NETADDRESS_H - -#include - -struct NetAddress { - NetAddress() { } - NetAddress(const QHostAddress &_ip, quint16 _port) : ip(_ip), port(_port) { } - QHostAddress ip; - quint16 port; -}; - -inline bool operator< (const NetAddress& a, const NetAddress& b){ - return (a.ip.toString()+a.port) < (b.ip.toString()+b.port); -} - -#endif // NETADDRESS_H diff --git a/core/backends/lan/socketlinereader.cpp b/core/backends/lan/socketlinereader.cpp index a6bd85eec..b973b99a9 100644 --- a/core/backends/lan/socketlinereader.cpp +++ b/core/backends/lan/socketlinereader.cpp @@ -33,8 +33,8 @@ void SocketLineReader::dataReceived() { while (mSocket->canReadLine()) { const QByteArray line = mSocket->readLine(); - if (line.length() > 1) { - mPackages.enqueue(line);//we don't want single \n + if (line.length() > 1) { //we don't want a single \n + mPackages.enqueue(line); } } diff --git a/core/core_debug.h b/core/core_debug.h index 93a0f1d1f..d74745cb9 100644 --- a/core/core_debug.h +++ b/core/core_debug.h @@ -23,6 +23,8 @@ #include -Q_DECLARE_LOGGING_CATEGORY(KDECONNECT_CORE) +#include "kdeconnectcore_export.h" + +KDECONNECTCORE_EXPORT Q_DECLARE_LOGGING_CATEGORY(KDECONNECT_CORE) #endif //CORE_DEBUG_H diff --git a/core/filetransferjob.cpp b/core/filetransferjob.cpp index f0b7a20e1..c8f0909cf 100644 --- a/core/filetransferjob.cpp +++ b/core/filetransferjob.cpp @@ -33,7 +33,7 @@ FileTransferJob::FileTransferJob(const QSharedPointer& origin, qint64 : KJob() , mOrigin(origin) , mReply(Q_NULLPTR) - , mDeviceName("KDE Connect") //TODO: Actually fetch the device name + , mFrom("KDE Connect") , mDestination(destination) , mSpeedBytes(0) , mWritten(0) @@ -48,6 +48,7 @@ FileTransferJob::FileTransferJob(const QSharedPointer& origin, qint64 if (size >= 0) { setTotalAmount(Bytes, size); } + setCapabilities(Killable); qCDebug(KDECONNECT_CORE) << "FileTransferJob Downloading payload to" << destination; } @@ -60,9 +61,8 @@ void FileTransferJob::start() void FileTransferJob::doStart() { - description(this, i18n("Receiving file over KDE-Connect"), - QPair(i18nc("File transfer origin", "From"), - mDeviceName) + description(this, i18n("Receiving file over KDE Connect"), + QPair(i18nc("File transfer origin", "From"), mFrom) ); if (mDestination.isLocalFile() && QFile::exists(mDestination.toLocalFile())) { @@ -78,9 +78,8 @@ void FileTransferJob::startTransfer() { setProcessedAmount(Bytes, 0); mTime = QTime::currentTime(); - description(this, i18n("Receiving file over KDE-Connect"), - QPair(i18nc("File transfer origin", "From"), - mDeviceName), + description(this, i18n("Receiving file over KDE Connect"), + QPair(i18nc("File transfer origin", "From"), mFrom), QPair(i18nc("File transfer destination", "To"), mDestination.toLocalFile())); QNetworkRequest req(mDestination); diff --git a/core/filetransferjob.h b/core/filetransferjob.h index 1c5c3b88b..9d90b8bf2 100644 --- a/core/filetransferjob.h +++ b/core/filetransferjob.h @@ -55,7 +55,7 @@ public: FileTransferJob(const QSharedPointer& origin, qint64 size, const QUrl &destination); virtual void start() Q_DECL_OVERRIDE; QUrl destination() const { return mDestination; } - void setDeviceName(const QString &deviceName) { mDeviceName = deviceName; } + void setOriginName(QString from) { mFrom = from; } private Q_SLOTS: void doStart(); @@ -69,7 +69,7 @@ private: QSharedPointer mOrigin; QNetworkReply* mReply; - QString mDeviceName; + QString mFrom; QUrl mDestination; QTime mTime; qulonglong mSpeedBytes; diff --git a/kcm/kcm.ui b/kcm/kcm.ui index 6f763c843..147cf575b 100644 --- a/kcm/kcm.ui +++ b/kcm/kcm.ui @@ -70,7 +70,9 @@ - + + + @@ -91,7 +93,9 @@ - + + + @@ -295,7 +299,38 @@ - If you have an Android phone, make sure to install the <a href="https://play.google.com/store/apps/details?id=org.kde.kdeconnect_tp"><span style=" text-decoration: underline; color:#0000ff;">KDE Connect Android app</span></a> (also available <a href="https://f-droid.org/repository/browse/?fdid=org.kde.kdeconnect_tp"><span style=" text-decoration: underline; color:#0000ff;">from F-Droid</span></a>). + <html><head/><body><p>If you own Android device, make sure to install the <a href="https://play.google.com/store/apps/details?id=org.kde.kdeconnect_tp"><span style=" text-decoration: underline; color:#0000ff;">KDE Connect Android app</span></a> (also available <a href="https://f-droid.org/repository/browse/?fdid=org.kde.kdeconnect_tp"><span style=" text-decoration: underline; color:#0000ff;">from F-Droid</span></a>) and it should appear in the list.</p></body></html> + + + Qt::RichText + + + Qt::AlignCenter + + + true + + + 40 + + + true + + + Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse + + + + + + + + 0 + 0 + + + + <html><head/><body><p>If you are having problems, visit the <a href="https://community.kde.org/KDEConnect"><span style=" text-decoration: underline; color:#0000ff;">KDE Connect Community wiki</span></a> for help.</p></body></html> Qt::RichText diff --git a/kcmplugin/CMakeLists.txt b/kcmplugin/CMakeLists.txt index 3f0fb1151..324f16b3c 100644 --- a/kcmplugin/CMakeLists.txt +++ b/kcmplugin/CMakeLists.txt @@ -24,6 +24,5 @@ set_target_properties(kdeconnectpluginkcm PROPERTIES target_include_directories(kdeconnectpluginkcm PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) generate_export_header(kdeconnectpluginkcm EXPORT_FILE_NAME kdeconnectpluginkcm_export.h BASE_NAME kdeconnectpluginkcm) -# Remove NAMELINK_SKIP if/when headers are being installed and the library -# becomes public. +# Remove NAMELINK_SKIP if/when headers are being installed and the library becomes public. install(TARGETS kdeconnectpluginkcm EXPORT kdeconnectLibraryTargets ${INSTALL_TARGETS_DEFAULT_ARGS} LIBRARY NAMELINK_SKIP) diff --git a/kio/kiokdeconnect.h b/kio/kiokdeconnect.h index c30195877..2586f9ebb 100644 --- a/kio/kiokdeconnect.h +++ b/kio/kiokdeconnect.h @@ -32,7 +32,7 @@ Q_DECLARE_LOGGING_CATEGORY(KDECONNECT_KIO) class KioKdeconnect : public QObject, public KIO::SlaveBase { - Q_OBJECT + Q_OBJECT public: KioKdeconnect(const QByteArray &pool, const QByteArray &app); diff --git a/plugins/notifications/notification.cpp b/plugins/notifications/notification.cpp index b44b5f854..3e42f2aa8 100644 --- a/plugins/notifications/notification.cpp +++ b/plugins/notifications/notification.cpp @@ -25,7 +25,7 @@ Notification::Notification(const NetworkPackage& np, const QString& iconPath, QObject* parent) : QObject(parent) { - mId = np.get("id"); + mInternalId = np.get("id"); mAppName = np.get("appName"); mTicker = np.get("ticker"); mDismissable = np.get("isClearable"); @@ -40,7 +40,7 @@ Notification::~Notification() void Notification::dismiss() { if (mDismissable) { - Q_EMIT dismissRequested(this); + Q_EMIT dismissRequested(mInternalId); } } diff --git a/plugins/notifications/notification.h b/plugins/notifications/notification.h index 3c14d26d0..dcf09a77c 100644 --- a/plugins/notifications/notification.h +++ b/plugins/notifications/notification.h @@ -41,7 +41,7 @@ public: Notification(const NetworkPackage& np, const QString& iconPath, QObject* parent); virtual ~Notification(); - QString internalId() const { return mId; } + QString internalId() const { return mInternalId; } QString appName() const { return mAppName; } QString ticker() const { return mTicker; } QString iconPath() const { return mIconPath; } @@ -51,10 +51,10 @@ public Q_SLOTS: Q_SCRIPTABLE void dismiss(); Q_SIGNALS: - void dismissRequested(Notification* self); + void dismissRequested(const QString& mInternalId); private: - QString mId; + QString mInternalId; QString mAppName; QString mTicker; QString mIconPath; diff --git a/plugins/notifications/notificationsdbusinterface.cpp b/plugins/notifications/notificationsdbusinterface.cpp index e7b89f26c..3c504c646 100644 --- a/plugins/notifications/notificationsdbusinterface.cpp +++ b/plugins/notifications/notificationsdbusinterface.cpp @@ -98,8 +98,8 @@ void NotificationsDbusInterface::addNotification(Notification* noti) removeNotification(internalId); } - connect(noti, SIGNAL(dismissRequested(Notification*)), - this, SLOT(dismissRequested(Notification*))); + connect(noti, &Notification::dismissRequested, + this, &NotificationsDbusInterface::dismissRequested); const QString& publicId = newId(); mNotifications[publicId] = noti; @@ -133,10 +133,8 @@ void NotificationsDbusInterface::removeNotification(const QString& internalId) Q_EMIT notificationRemoved(publicId); } -void NotificationsDbusInterface::dismissRequested(Notification* notification) +void NotificationsDbusInterface::dismissRequested(const QString& internalId) { - const QString& internalId = notification->internalId(); - NetworkPackage np(PACKAGE_TYPE_NOTIFICATION); np.set("cancel", internalId); mPlugin->sendPackage(np); diff --git a/plugins/notifications/notificationsdbusinterface.h b/plugins/notifications/notificationsdbusinterface.h index e8d5c2a7a..21d5a6afe 100644 --- a/plugins/notifications/notificationsdbusinterface.h +++ b/plugins/notifications/notificationsdbusinterface.h @@ -44,10 +44,10 @@ public: void processPackage(const NetworkPackage& np); void clearNotifications(); + void dismissRequested(const QString& notification); public Q_SLOTS: Q_SCRIPTABLE QStringList activeNotifications(); - void dismissRequested(Notification* notification); Q_SIGNALS: Q_SCRIPTABLE void notificationPosted(const QString& publicId); diff --git a/plugins/sftp/mounter.cpp b/plugins/sftp/mounter.cpp index b83e55f85..6eebc7b84 100644 --- a/plugins/sftp/mounter.cpp +++ b/plugins/sftp/mounter.cpp @@ -48,13 +48,13 @@ Mounter::Mounter(SftpPlugin* sftp) m_connectTimer.setSingleShot(true); QTimer::singleShot(0, this, SLOT(start())); - qCDebug(KDECONNECT_PLUGIN_SFTP) << "Created"; + qCDebug(KDECONNECT_PLUGIN_SFTP) << "Created mounter"; } Mounter::~Mounter() { + qCDebug(KDECONNECT_PLUGIN_SFTP) << "Destroy mounter"; unmount(); - qCDebug(KDECONNECT_PLUGIN_SFTP) << "Destroyed"; } bool Mounter::wait() @@ -95,12 +95,14 @@ void Mounter::onPakcageReceived(const NetworkPackage& np) * Q_EMIT mounted(); */ - m_proc.reset(new KProcess(this)); + unmount(); + + m_proc = new KProcess(this); m_proc->setOutputChannelMode(KProcess::MergedChannels); - connect(m_proc.data(), SIGNAL(started()), SLOT(onStarted())); - connect(m_proc.data(), SIGNAL(error(QProcess::ProcessError)), SLOT(onError(QProcess::ProcessError))); - connect(m_proc.data(), SIGNAL(finished(int,QProcess::ExitStatus)), SLOT(onFinished(int,QProcess::ExitStatus))); + connect(m_proc, SIGNAL(started()), SLOT(onStarted())); + connect(m_proc, SIGNAL(error(QProcess::ProcessError)), SLOT(onError(QProcess::ProcessError))); + connect(m_proc, SIGNAL(finished(int,QProcess::ExitStatus)), SLOT(onFinished(int,QProcess::ExitStatus))); QDir().mkpath(m_mountPoint); @@ -125,12 +127,6 @@ void Mounter::onPakcageReceived(const NetworkPackage& np) m_proc->setProgram(program, arguments); - //To debug - //m_proc->setStandardOutputFile("/tmp/kdeconnect-sftp.out"); - //m_proc->setStandardErrorFile("/tmp/kdeconnect-sftp.err"); - - cleanMountPoint(); - qCDebug(KDECONNECT_PLUGIN_SFTP) << "Starting process: " << m_proc->program().join(" "); m_proc->start(); } @@ -140,11 +136,13 @@ void Mounter::onStarted() qCDebug(KDECONNECT_PLUGIN_SFTP) << "Process started"; m_started = true; Q_EMIT mounted(); - - connect(m_proc.data(), &KProcess::readyReadStandardError, [this]() { + + //m_proc->setStandardOutputFile("/tmp/kdeconnect-sftp.out"); + //m_proc->setStandardErrorFile("/tmp/kdeconnect-sftp.err"); + connect(m_proc, &KProcess::readyReadStandardError, [this]() { qCDebug(KDECONNECT_PLUGIN_SFTP) << "stderr: " << m_proc->readAll(); }); - connect(m_proc.data(), &KProcess::readyReadStandardOutput, [this]() { + connect(m_proc, &KProcess::readyReadStandardOutput, [this]() { qCDebug(KDECONNECT_PLUGIN_SFTP) << "stdout:" << m_proc->readAll(); }); } @@ -172,9 +170,7 @@ void Mounter::onFinished(int exitCode, QProcess::ExitStatus exitStatus) Q_EMIT failed(i18n("Error when accessing to filesystem")); } - cleanMountPoint(); - m_proc.reset(); - m_started = false; + unmount(); } void Mounter::onMountTimeout() @@ -192,25 +188,18 @@ void Mounter::start() m_connectTimer.start(); } -void Mounter::cleanMountPoint() -{ - qCDebug(KDECONNECT_PLUGIN_SFTP()) << "cleanMountPoint"; - KProcess::execute(QStringList() << "fusermount" << "-u" << m_mountPoint, 10000); -} - void Mounter::unmount() { + qCDebug(KDECONNECT_PLUGIN_SFTP) << "Unmount" << m_proc; if (m_proc) { - cleanMountPoint(); - if (m_proc) - { - m_proc->terminate(); - QTimer::singleShot(5000, m_proc.data(), SLOT(kill())); - m_proc->waitForFinished(); - } + auto toDestroy = m_proc; + m_proc = nullptr; //So we don't reenter this code path when onFinished gets called + toDestroy->kill(); + delete toDestroy; + //Free mount point (won't always succeed if the path is in use) + KProcess::execute(QStringList() << "fusermount" << "-u" << m_mountPoint, 10000); } - - m_started = false; + m_started = false; } diff --git a/plugins/sftp/mounter.h b/plugins/sftp/mounter.h index 76ac860f8..bb2d3f58f 100644 --- a/plugins/sftp/mounter.h +++ b/plugins/sftp/mounter.h @@ -51,13 +51,12 @@ private Q_SLOTS: void onMountTimeout(); void start(); -private: - void cleanMountPoint(); +private: void unmount(); private: SftpPlugin* m_sftp; - QScopedPointer m_proc; + KProcess* m_proc; QTimer m_connectTimer; QString m_mountPoint; bool m_started; diff --git a/plugins/share/shareplugin.cpp b/plugins/share/shareplugin.cpp index 4a925378f..44e52e2ca 100644 --- a/plugins/share/shareplugin.cpp +++ b/plugins/share/shareplugin.cpp @@ -96,7 +96,7 @@ bool SharePlugin::receivePackage(const NetworkPackage& np) } FileTransferJob* job = np.createPayloadTransferJob(destination); - job->setDeviceName(device()->name()); + job->setOriginName(device()->name() + ": " + filename); connect(job, SIGNAL(result(KJob*)), this, SLOT(finished(KJob*))); KIO::getJobTracker()->registerJob(job); job->start(); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0ebc91998..d585d2b45 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -18,3 +18,4 @@ ecm_add_test(pluginloadtest.cpp LINK_LIBRARIES ${kdeconnect_libraries}) ecm_add_test(sendfiletest.cpp LINK_LIBRARIES ${kdeconnect_libraries}) ecm_add_test(networkpackagetests.cpp LINK_LIBRARIES ${kdeconnect_libraries}) ecm_add_test(testsocketlinereader.cpp ../core/backends/lan/socketlinereader.cpp TEST_NAME testsocketlinereader LINK_LIBRARIES ${kdeconnect_libraries}) +ecm_add_test(downloadjobtest.cpp ../core/backends/lan/downloadjob.cpp TEST_NAME downloadjobtest LINK_LIBRARIES ${kdeconnect_libraries}) diff --git a/tests/downloadjobtest.cpp b/tests/downloadjobtest.cpp new file mode 100644 index 000000000..efaea3dc2 --- /dev/null +++ b/tests/downloadjobtest.cpp @@ -0,0 +1,107 @@ +/************************************************************************************* + * Copyright (C) 2014 by Albert Vaca Cintora * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 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 * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * + *************************************************************************************/ + +#include "../core/backends/lan/downloadjob.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class DownloadJobTest : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void failToConnectShouldDestroyTheJob(); + void closingTheConnectionShouldDestroyTheJob(); +private: + + void initServer(); + void initDownloadJob(); + void awaitToBeDestroyedOrTimeOut(); + void stopServer(); + + QTimer mTimer; + QEventLoop mLoop; + DownloadJob* test; + QTcpServer *mServer; +}; + +void DownloadJobTest::initServer() +{ + mServer = new QTcpServer(this); + QVERIFY2(mServer->listen(QHostAddress::LocalHost, 8694), "Failed to create local tcp server"); +} + +void DownloadJobTest::stopServer() +{ + mServer->close(); +} + +void DownloadJobTest::initDownloadJob() +{ + QVariantMap transferInfo; + transferInfo["port"]= 8694; + test = new DownloadJob(QHostAddress::LocalHost, transferInfo); + test->start(); +} + +void DownloadJobTest::awaitToBeDestroyedOrTimeOut() +{ + //Either the job is destroyed + connect(test, &QObject::destroyed, &mLoop, &QEventLoop::quit); + + //Or we time out + mTimer.setInterval(2000); + mTimer.setSingleShot(true); + connect(&mTimer, &QTimer::timeout, [this]() { + mLoop.quit(); + QFAIL("Test timed out"); + }); + mTimer.start(); + + //We wait + mLoop.exec(); + + mTimer.stop(); +} + +void DownloadJobTest::failToConnectShouldDestroyTheJob() +{ + initDownloadJob(); + awaitToBeDestroyedOrTimeOut(); +} + +void DownloadJobTest::closingTheConnectionShouldDestroyTheJob() +{ + initServer(); + initDownloadJob(); + stopServer(); + awaitToBeDestroyedOrTimeOut(); +} + +QTEST_GUILESS_MAIN(DownloadJobTest) + +#include "downloadjobtest.moc"