Merge branch 'filebrowsing' into daemonsplit

This commit is contained in:
Samoilenko Yuri 2014-01-21 17:11:25 +04:00
commit 7e9ae84b4c
3 changed files with 173 additions and 31 deletions

View file

@ -20,10 +20,11 @@
#include "sftpplugin.h" #include "sftpplugin.h"
#include <QDBusConnection>
#include <QDir> #include <QDir>
#include <QTimerEvent> #include <QTimerEvent>
#include <QDBusConnection>
#include <KConfig> #include <KConfig>
#include <KConfigGroup> #include <KConfigGroup>
#include <KIconLoader> #include <KIconLoader>
@ -52,18 +53,40 @@ inline bool isTimeout(QObject* o, const KConfigGroup& cfg)
return cfg.readEntry("idle", true) && duration > (cfg.readEntry("idletimeout", 60) * 60); return cfg.readEntry("idle", true) && duration > (cfg.readEntry("idletimeout", 60) * 60);
} }
MountLoop::MountLoop()
: QEventLoop()
{
}
bool MountLoop::exec(QEventLoop::ProcessEventsFlags flags)
{
return QEventLoop::exec(flags) == 0;
}
void MountLoop::failed()
{
Q_EMIT(result(false));
exit(1);
}
void MountLoop::successed()
{
Q_EMIT(result(true));
exit(0);
}
void MountLoop::exitWith(bool status)
{
Q_EMIT(result(status));
exit(status ? 0 : 1);
}
struct SftpPlugin::Pimpl struct SftpPlugin::Pimpl
{ {
Pimpl() : waitForMount(false)
{
mountTimer.setSingleShot(true);
};
QPointer<KProcess> mountProc; QPointer<KProcess> mountProc;
KFilePlacesModel* m_placesModel; KFilePlacesModel* m_placesModel;
QTimer mountTimer;
int idleTimer; int idleTimer;
bool waitForMount; MountLoop loop;
}; };
SftpPlugin::SftpPlugin(QObject *parent, const QVariantList &args) SftpPlugin::SftpPlugin(QObject *parent, const QVariantList &args)
@ -74,7 +97,8 @@ SftpPlugin::SftpPlugin(QObject *parent, const QVariantList &args)
m_d->idleTimer = startTimer(20 * 1000); m_d->idleTimer = startTimer(20 * 1000);
connect(&m_d->mountTimer, SIGNAL(timeout()), this, SLOT(mountTimeout())); connect(this, SIGNAL(mount_succesed()), &m_d->loop, SLOT(successed()));
connect(this, SIGNAL(mount_failed()), &m_d->loop, SLOT(failed()));
//Add KIO entry to Dolphin's Places //Add KIO entry to Dolphin's Places
m_d->m_placesModel = new KFilePlacesModel(); m_d->m_placesModel = new KFilePlacesModel();
@ -119,20 +143,45 @@ void SftpPlugin::connected()
void SftpPlugin::mount() void SftpPlugin::mount()
{ {
kDebug(kdeconnect_kded()) << "start mounting device:" << device()->name(); kDebug(kdeconnect_kded()) << "start mounting device:" << device()->name();
if (m_d->mountTimer.isActive() || m_d->mountProc) if (m_d->loop.isRunning() || m_d->mountProc)
{ {
return; return;
} }
else
{
m_d->mountTimer.start(10000);
}
NetworkPackage np(PACKAGE_TYPE_SFTP); NetworkPackage np(PACKAGE_TYPE_SFTP);
np.set("startBrowsing", true); np.set("startBrowsing", true);
device()->sendPackage(np); device()->sendPackage(np);
} }
bool SftpPlugin::mountAndWait()
{
kDebug(kdeconnect_kded()) << "start mounting device and block:" << device()->name();
if (m_d->mountProc && !m_d->loop.isRunning())
{
return true;
}
if (m_d->loop.isRunning())
{
MountLoop loop;
connect(&m_d->loop, SIGNAL(result(bool)), &loop, SLOT(exitWith(bool)));
return loop.exec();
}
kDebug(kdeconnect_kded()) << "call mounting" << device()->name();
mount();
QTimer mt;
connect(&mt, SIGNAL(timeout()), &m_d->loop, SLOT(failed()));
connect(&mt, SIGNAL(timeout()), this, SLOT(mountTimeout()));
kDebug(kdeconnect_kded()) << "stargting timer";
mt.start(15000);
return m_d->loop.exec();
}
void SftpPlugin::umount() void SftpPlugin::umount()
{ {
if (m_d->mountProc) if (m_d->mountProc)
@ -149,15 +198,10 @@ void SftpPlugin::umount()
void SftpPlugin::startBrowsing() void SftpPlugin::startBrowsing()
{ {
if (m_d->mountProc) if (mountAndWait())
{ {
new KRun(KUrl::fromLocalFile(mountPoint()), 0); new KRun(KUrl::fromLocalFile(mountPoint()), 0);
} }
else
{
m_d->waitForMount = true;
mount();
}
} }
bool SftpPlugin::receivePackage(const NetworkPackage& np) bool SftpPlugin::receivePackage(const NetworkPackage& np)
@ -173,8 +217,6 @@ bool SftpPlugin::receivePackage(const NetworkPackage& np)
return true; return true;
} }
m_d->mountTimer.stop();
m_d->mountProc = new KProcess(this); m_d->mountProc = new KProcess(this);
m_d->mountProc->setOutputChannelMode(KProcess::SeparateChannels); m_d->mountProc->setOutputChannelMode(KProcess::SeparateChannels);
@ -237,14 +279,11 @@ void SftpPlugin::onStarted()
, KIconLoader::global()->loadIcon("drive-removable-media", KIconLoader::Desktop) , KIconLoader::global()->loadIcon("drive-removable-media", KIconLoader::Desktop)
); );
//Used to notify MountLoop about success.
Q_EMIT mount_succesed();
connect(m_d->mountProc, SIGNAL(readyReadStandardError()), this, SLOT(readProcessStderr())); connect(m_d->mountProc, SIGNAL(readyReadStandardError()), this, SLOT(readProcessStderr()));
connect(m_d->mountProc, SIGNAL(readyReadStandardOutput()), this, SLOT(readProcessStdout())); connect(m_d->mountProc, SIGNAL(readyReadStandardOutput()), this, SLOT(readProcessStdout()));
if (m_d->waitForMount)
{
m_d->waitForMount = false;
new KRun(KUrl::fromLocalFile(mountPoint()), 0);
}
} }
void SftpPlugin::onError(QProcess::ProcessError error) void SftpPlugin::onError(QProcess::ProcessError error)
@ -294,6 +333,10 @@ void SftpPlugin::onFinished(int exitCode, QProcess::ExitStatus exitStatus)
cleanMountPoint(); cleanMountPoint();
m_d->mountProc = 0; m_d->mountProc = 0;
//Used to notify MountLoop about error.
//There is no loop running if mount was succesful!
Q_EMIT mount_failed();
} }
void SftpPlugin::knotify(int type, const QString& text, const QPixmap& icon) const void SftpPlugin::knotify(int type, const QString& text, const QPixmap& icon) const
@ -310,6 +353,7 @@ void SftpPlugin::cleanMountPoint()
void SftpPlugin::mountTimeout() void SftpPlugin::mountTimeout()
{ {
kDebug(kdeconnect_kded()) << "loop.... TIMEOUT";
knotify(KNotification::Error knotify(KNotification::Error
, i18n("Failed to mount filesystem: device not responding") , i18n("Failed to mount filesystem: device not responding")
, KIconLoader::global()->loadIcon("dialog-error", KIconLoader::Desktop) , KIconLoader::global()->loadIcon("dialog-error", KIconLoader::Desktop)
@ -328,6 +372,23 @@ void SftpPlugin::readProcessStdout()
m_d->mountProc->readAllStandardOutput(); m_d->mountProc->readAllStandardOutput();
} }
bool SftpPlugin::waitForMount()
{
if (m_d->loop.isRunning())
{
MountLoop loop;
connect(&m_d->loop, SIGNAL(result(bool)), &loop, SLOT(exitWith(bool)));
kDebug(kdeconnect_kded()) << "start secondary loop...";
bool ret = loop.exec();
kDebug(kdeconnect_kded()) << "finish secondary loop...:" << ret;
return ret;
}
return m_d->mountProc;
}
// void SftpPlugin::startAgent() // void SftpPlugin::startAgent()
// { // {
// m_d->agentProc = new KProcess(this); // m_d->agentProc = new KProcess(this);

View file

@ -22,6 +22,7 @@
#define SFTPPLUGIN_H #define SFTPPLUGIN_H
#include <KProcess> #include <KProcess>
#include <QEventLoop>
#include "../kdeconnectplugin.h" #include "../kdeconnectplugin.h"
@ -29,6 +30,24 @@
class KNotification; class KNotification;
//TODO move to private
class MountLoop : public QEventLoop
{
Q_OBJECT
public:
MountLoop();
bool exec(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents);
Q_SIGNALS:
void result(bool status);
public Q_SLOTS:
void failed();
void successed();
void exitWith(bool status);
};
class SftpPlugin class SftpPlugin
: public KdeConnectPlugin : public KdeConnectPlugin
{ {
@ -36,6 +55,7 @@ class SftpPlugin
Q_CLASSINFO("D-Bus Interface", "org.kde.kdeconnect.device.sftp") Q_CLASSINFO("D-Bus Interface", "org.kde.kdeconnect.device.sftp")
public: public:
explicit SftpPlugin(QObject *parent, const QVariantList &args); explicit SftpPlugin(QObject *parent, const QVariantList &args);
virtual ~SftpPlugin(); virtual ~SftpPlugin();
@ -44,17 +64,25 @@ public:
return KComponentData("kdeconnect", "kdeconnect"); return KComponentData("kdeconnect", "kdeconnect");
} }
Q_SIGNALS:
void mount_succesed(); //TODO make private - for internal use
void mount_failed(); //TODO make private -for internal use
public Q_SLOTS: public Q_SLOTS:
virtual bool receivePackage(const NetworkPackage& np); virtual bool receivePackage(const NetworkPackage& np);
virtual void connected(); virtual void connected();
Q_SCRIPTABLE void mount(); Q_SCRIPTABLE void mount();
Q_SCRIPTABLE void umount(); Q_SCRIPTABLE void umount();
Q_SCRIPTABLE bool mountAndWait();
Q_SCRIPTABLE void startBrowsing(); Q_SCRIPTABLE void startBrowsing();
Q_SCRIPTABLE QString mountPoint(); Q_SCRIPTABLE QString mountPoint();
protected: protected:
void timerEvent(QTimerEvent *event); void timerEvent(QTimerEvent *event);
@ -67,6 +95,8 @@ private Q_SLOTS:
void readProcessStderr(); void readProcessStderr();
void readProcessStdout(); void readProcessStdout();
bool waitForMount();
private: private:
QString dbusPath() const { return "/modules/kdeconnect/devices/" + device()->id() + "/sftp"; } QString dbusPath() const { return "/modules/kdeconnect/devices/" + device()->id() + "/sftp"; }
void knotify(int type, const QString& text, const QPixmap& icon) const; void knotify(int type, const QString& text, const QPixmap& icon) const;
@ -79,4 +109,5 @@ private:
QScopedPointer<Pimpl> m_d; QScopedPointer<Pimpl> m_d;
}; };
#endif #endif

View file

@ -51,6 +51,36 @@ extern "C" int KDE_EXPORT kdemain(int argc, char **argv)
return 0; return 0;
} }
//Some useful error mapping
KIO::Error toKioError(const QDBusError::ErrorType type)
{
switch (type)
{
case QDBusError::NoError:
return KIO::Error(KJob::NoError);
case QDBusError::NoMemory:
return KIO::ERR_OUT_OF_MEMORY;
case QDBusError::Timeout:
return KIO::ERR_SERVER_TIMEOUT;
case QDBusError::TimedOut:
return KIO::ERR_SERVER_TIMEOUT;
default:
return KIO::ERR_INTERNAL;
};
};
template <typename T>
bool handleDBusError(QDBusReply<T>& reply, KIO::SlaveBase* slave)
{
if (!reply.isValid())
{
kDebug(kdeconnect_kio()) << "Error in DBus request:" << reply.error();
slave->error(toKioError(reply.error().type()),reply.error().message());
return true;
}
return false;
}
KioKdeconnect::KioKdeconnect(const QByteArray &pool, const QByteArray &app) KioKdeconnect::KioKdeconnect(const QByteArray &pool, const QByteArray &app)
: SlaveBase("kdeconnect", pool, app), : SlaveBase("kdeconnect", pool, app),
m_dbusInterface(new DaemonDbusInterface(this)) m_dbusInterface(new DaemonDbusInterface(this))
@ -102,8 +132,28 @@ void KioKdeconnect::listDevice()
kDebug(kdeconnect_kio()) << "ListDevice" << m_currentDevice; kDebug(kdeconnect_kio()) << "ListDevice" << m_currentDevice;
SftpDbusInterface interface(m_currentDevice); SftpDbusInterface interface(m_currentDevice);
interface.mount(); //Since this does not happen immediately, we mount it here
QString url = interface.mountPoint(); QDBusReply<bool> mountreply = interface.mountAndWait();
if (handleDBusError(mountreply, this))
{
return;
}
if (!mountreply.value())
{
error(KIO::ERR_COULD_NOT_MOUNT, i18n("Could not mount device filesystem"));
return;
}
QDBusReply<QString> urlreply = interface.mountPoint();
if (handleDBusError(urlreply, this))
{
return;
}
QString url = urlreply.value();
KIO::UDSEntry entry; KIO::UDSEntry entry;
entry.insert(KIO::UDSEntry::UDS_NAME, "files"); entry.insert(KIO::UDSEntry::UDS_NAME, "files");