playing with blocking mounting
This commit is contained in:
parent
225c25197e
commit
bbca88eff2
3 changed files with 173 additions and 31 deletions
|
@ -20,10 +20,11 @@
|
|||
|
||||
#include "sftpplugin.h"
|
||||
|
||||
#include <QDBusConnection>
|
||||
#include <QDir>
|
||||
#include <QTimerEvent>
|
||||
|
||||
#include <QDBusConnection>
|
||||
|
||||
#include <KConfig>
|
||||
#include <KConfigGroup>
|
||||
#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);
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
Pimpl() : waitForMount(false)
|
||||
{
|
||||
mountTimer.setSingleShot(true);
|
||||
};
|
||||
|
||||
QPointer<KProcess> mountProc;
|
||||
KFilePlacesModel* m_placesModel;
|
||||
QTimer mountTimer;
|
||||
int idleTimer;
|
||||
bool waitForMount;
|
||||
MountLoop loop;
|
||||
};
|
||||
|
||||
SftpPlugin::SftpPlugin(QObject *parent, const QVariantList &args)
|
||||
|
@ -74,7 +97,8 @@ SftpPlugin::SftpPlugin(QObject *parent, const QVariantList &args)
|
|||
|
||||
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
|
||||
m_d->m_placesModel = new KFilePlacesModel();
|
||||
|
@ -119,20 +143,45 @@ void SftpPlugin::connected()
|
|||
void SftpPlugin::mount()
|
||||
{
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_d->mountTimer.start(10000);
|
||||
}
|
||||
|
||||
NetworkPackage np(PACKAGE_TYPE_SFTP);
|
||||
np.set("startBrowsing", true);
|
||||
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()
|
||||
{
|
||||
if (m_d->mountProc)
|
||||
|
@ -149,15 +198,10 @@ void SftpPlugin::umount()
|
|||
|
||||
void SftpPlugin::startBrowsing()
|
||||
{
|
||||
if (m_d->mountProc)
|
||||
if (mountAndWait())
|
||||
{
|
||||
new KRun(KUrl::fromLocalFile(mountPoint()), 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_d->waitForMount = true;
|
||||
mount();
|
||||
}
|
||||
}
|
||||
|
||||
bool SftpPlugin::receivePackage(const NetworkPackage& np)
|
||||
|
@ -173,8 +217,6 @@ bool SftpPlugin::receivePackage(const NetworkPackage& np)
|
|||
return true;
|
||||
}
|
||||
|
||||
m_d->mountTimer.stop();
|
||||
|
||||
m_d->mountProc = new KProcess(this);
|
||||
m_d->mountProc->setOutputChannelMode(KProcess::SeparateChannels);
|
||||
|
||||
|
@ -237,14 +279,11 @@ void SftpPlugin::onStarted()
|
|||
, 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(readyReadStandardOutput()), this, SLOT(readProcessStdout()));
|
||||
|
||||
if (m_d->waitForMount)
|
||||
{
|
||||
m_d->waitForMount = false;
|
||||
new KRun(KUrl::fromLocalFile(mountPoint()), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void SftpPlugin::onError(QProcess::ProcessError error)
|
||||
|
@ -294,6 +333,10 @@ void SftpPlugin::onFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
|||
|
||||
cleanMountPoint();
|
||||
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
|
||||
|
@ -310,6 +353,7 @@ void SftpPlugin::cleanMountPoint()
|
|||
|
||||
void SftpPlugin::mountTimeout()
|
||||
{
|
||||
kDebug(kdeconnect_kded()) << "loop.... TIMEOUT";
|
||||
knotify(KNotification::Error
|
||||
, i18n("Failed to mount filesystem: device not responding")
|
||||
, KIconLoader::global()->loadIcon("dialog-error", KIconLoader::Desktop)
|
||||
|
@ -328,6 +372,23 @@ void SftpPlugin::readProcessStdout()
|
|||
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()
|
||||
// {
|
||||
// m_d->agentProc = new KProcess(this);
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#define SFTPPLUGIN_H
|
||||
|
||||
#include <KProcess>
|
||||
#include <QEventLoop>
|
||||
|
||||
#include "../kdeconnectplugin.h"
|
||||
|
||||
|
@ -29,6 +30,24 @@
|
|||
|
||||
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
|
||||
: public KdeConnectPlugin
|
||||
{
|
||||
|
@ -36,6 +55,7 @@ class SftpPlugin
|
|||
Q_CLASSINFO("D-Bus Interface", "org.kde.kdeconnect.device.sftp")
|
||||
|
||||
public:
|
||||
|
||||
explicit SftpPlugin(QObject *parent, const QVariantList &args);
|
||||
virtual ~SftpPlugin();
|
||||
|
||||
|
@ -44,17 +64,25 @@ public:
|
|||
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:
|
||||
virtual bool receivePackage(const NetworkPackage& np);
|
||||
virtual void connected();
|
||||
|
||||
Q_SCRIPTABLE void mount();
|
||||
Q_SCRIPTABLE void umount();
|
||||
Q_SCRIPTABLE bool mountAndWait();
|
||||
|
||||
Q_SCRIPTABLE void startBrowsing();
|
||||
|
||||
Q_SCRIPTABLE QString mountPoint();
|
||||
|
||||
|
||||
protected:
|
||||
void timerEvent(QTimerEvent *event);
|
||||
|
||||
|
@ -67,6 +95,8 @@ private Q_SLOTS:
|
|||
void readProcessStderr();
|
||||
void readProcessStdout();
|
||||
|
||||
bool waitForMount();
|
||||
|
||||
private:
|
||||
QString dbusPath() const { return "/modules/kdeconnect/devices/" + device()->id() + "/sftp"; }
|
||||
void knotify(int type, const QString& text, const QPixmap& icon) const;
|
||||
|
@ -79,4 +109,5 @@ private:
|
|||
QScopedPointer<Pimpl> m_d;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -51,6 +51,36 @@ extern "C" int KDE_EXPORT kdemain(int argc, char **argv)
|
|||
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)
|
||||
: SlaveBase("kdeconnect", pool, app),
|
||||
m_dbusInterface(new DaemonDbusInterface(this))
|
||||
|
@ -102,8 +132,28 @@ void KioKdeconnect::listDevice()
|
|||
kDebug(kdeconnect_kio()) << "ListDevice" << 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;
|
||||
entry.insert(KIO::UDSEntry::UDS_NAME, "files");
|
||||
|
|
Loading…
Reference in a new issue