Added KIO slave and icon in Dolphin's places for file browsing

This commit is contained in:
Albert Vaca 2014-01-16 15:32:35 +01:00
parent 781c41da5b
commit 90e9ded926
11 changed files with 395 additions and 32 deletions

View file

@ -15,7 +15,7 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR})
add_subdirectory(kded)
add_subdirectory(libkdeconnect)
add_subdirectory(kcm)
#add_subdirectory(kioslave)
add_subdirectory(kio)
add_subdirectory(plasmoid)
add_subdirectory(tests)

View file

@ -21,7 +21,6 @@
#include "clipboardplugin.h"
#include <QClipboard>
#include <KDebug>
#include <QApplication>
K_PLUGIN_FACTORY( KdeConnectPluginFactory, registerPlugin< ClipboardPlugin >(); )

View file

@ -27,6 +27,7 @@ target_link_libraries(kdeconnect_sftp
${KDE4_KDECORE_LIBS}
${KDE4_KDEUI_LIBS}
${KDE4_KIO_LIBS}
${KDE4_KFILE_LIBS}
${QT_QTNETWORK_LIBRARY}
${QJSON_LIBRARIES}
${QCA2_LIBRARIES}

View file

@ -33,6 +33,7 @@
#include <KRun>
#include <KStandardDirs>
#include <kde_file.h>
#include <kfileplacesmodel.h>
#include "sftp_config.h"
#include "../../kdebugnamespace.h"
@ -43,10 +44,7 @@ K_EXPORT_PLUGIN( KdeConnectPluginFactory("kdeconnect_sftp", "kdeconnect_sftp") )
static const char* passwd_c = "sftppassword";
static const char* mountpoint_c = "sftpmountpoint";
static const char* timestamp_c = "timestamp";
static const QSet<QString> fields_c = QSet<QString>() <<
"ip" << "port" << "user" << "port" << "password" << "path";
static const QSet<QString> fields_c = QSet<QString>() << "ip" << "port" << "user" << "port" << "password" << "path";
inline bool isTimeout(QObject* o, const KConfigGroup& cfg)
{
@ -54,11 +52,6 @@ inline bool isTimeout(QObject* o, const KConfigGroup& cfg)
return cfg.readEntry("idle", true) && duration > (cfg.readEntry("idletimeout", 60) * 60);
}
inline QString mountpoint(QObject* o)
{
return o->property(mountpoint_c).toString();
}
struct SftpPlugin::Pimpl
{
Pimpl() : waitForMount(false)
@ -67,6 +60,7 @@ struct SftpPlugin::Pimpl
};
QPointer<KProcess> mountProc;
KFilePlacesModel* m_placesModel;
QTimer mountTimer;
int idleTimer;
bool waitForMount;
@ -81,16 +75,41 @@ SftpPlugin::SftpPlugin(QObject *parent, const QVariantList &args)
m_d->idleTimer = startTimer(20 * 1000);
connect(&m_d->mountTimer, SIGNAL(timeout()), this, SLOT(mountTimeout()));
//Add KIO entry to Dolphin's Places
m_d->m_placesModel = new KFilePlacesModel();
addToDolphin();
}
void SftpPlugin::addToDolphin()
{
removeFromDolphin();
KUrl kioUrl("kdeconnect://"+device()->id()+"/");
m_d->m_placesModel->addPlace(device()->name(), kioUrl, "smartphone");
kDebug(kdeconnect_kded()) << "add to dolphin";
}
void SftpPlugin::removeFromDolphin()
{
KUrl kioUrl("kdeconnect://"+device()->id()+"/");
QModelIndex index = m_d->m_placesModel->closestItem(kioUrl);
while (index.row() != -1) {
m_d->m_placesModel->removePlace(index);
index = m_d->m_placesModel->closestItem(kioUrl);
}
}
void SftpPlugin::connected()
{
}
SftpPlugin::~SftpPlugin()
{
QDBusConnection::sessionBus().unregisterObject(dbusPath(), QDBusConnection::UnregisterTree);
umount();
removeFromDolphin();
}
void SftpPlugin::mount()
@ -113,7 +132,7 @@ void SftpPlugin::umount()
{
if (m_d->mountProc)
{
cleanMountPoint(m_d->mountProc);
cleanMountPoint();
if (m_d->mountProc)
{
m_d->mountProc->terminate();
@ -127,7 +146,7 @@ void SftpPlugin::startBrowsing()
{
if (m_d->mountProc)
{
new KRun(KUrl::fromLocalFile(mountpoint(m_d->mountProc)), 0);
new KRun(KUrl::fromLocalFile(mountPoint()), 0);
}
else
{
@ -159,8 +178,7 @@ bool SftpPlugin::receivePackage(const NetworkPackage& np)
connect(m_d->mountProc, SIGNAL(finished(int,QProcess::ExitStatus)), SLOT(onFinished(int,QProcess::ExitStatus)));
connect(m_d->mountProc, SIGNAL(finished(int,QProcess::ExitStatus)), m_d->mountProc, SLOT(deleteLater()));
const QString mpoint = KConfig("kdeconnect/plugins/sftp").group("main").readEntry("mountpoint"
, KStandardDirs::locateLocal("appdata", "", true, componentData())) + "/" + device()->name() + "/";
const QString mpoint = mountPoint();
QDir().mkpath(mpoint);
const QString program = "sshfs";
@ -177,14 +195,20 @@ bool SftpPlugin::receivePackage(const NetworkPackage& np)
m_d->mountProc->setProgram(program, arguments);
m_d->mountProc->setProperty(passwd_c, np.get<QString>("password"));
m_d->mountProc->setProperty(mountpoint_c, mpoint);
cleanMountPoint(m_d->mountProc);
cleanMountPoint();
m_d->mountProc->start();
return true;
}
QString SftpPlugin::mountPoint()
{
const QString defaultMountDir = KStandardDirs::locateLocal("appdata", "", true, componentData());
const QString mountDir = KConfig("kdeconnect/plugins/sftp").group("main").readEntry("mountpoint", defaultMountDir);
return mountDir + "/" + device()->id() + "/";
}
void SftpPlugin::timerEvent(QTimerEvent* event)
{
if (event->timerId() == m_d->idleTimer)
@ -206,14 +230,14 @@ void SftpPlugin::onStarted()
m_d->mountProc->closeWriteChannel();
knotify(KNotification::Notification
, i18n("Filesystem mounted at %1").arg(mountpoint(sender()))
, i18n("Filesystem mounted at %1").arg(mountPoint())
, KIconLoader::global()->loadIcon("drive-removable-media", KIconLoader::Desktop)
);
if (m_d->waitForMount)
{
m_d->waitForMount = false;
new KRun(KUrl::fromLocalFile(mountpoint(sender())), 0);
new KRun(KUrl::fromLocalFile(mountPoint()), 0);
}
}
@ -226,7 +250,7 @@ void SftpPlugin::onError(QProcess::ProcessError error)
, i18n("Failed to start sshfs")
, KIconLoader::global()->loadIcon("dialog-error", KIconLoader::Desktop)
);
cleanMountPoint(sender());
cleanMountPoint();
}
}
@ -259,7 +283,7 @@ void SftpPlugin::onFinished(int exitCode, QProcess::ExitStatus exitStatus)
);
}
cleanMountPoint(sender());
cleanMountPoint();
m_d->mountProc = 0;
}
@ -270,16 +294,9 @@ void SftpPlugin::knotify(int type, const QString& text, const QPixmap& icon) con
, KNotification::CloseOnTimeout);
}
void SftpPlugin::cleanMountPoint(QObject* mounter)
void SftpPlugin::cleanMountPoint()
{
if (!mounter || mountpoint(mounter).isEmpty())
{
return;
}
KProcess::execute(QStringList()
<< "fusermount" << "-u"
<< mountpoint(mounter), 10000);
KProcess::execute(QStringList() << "fusermount" << "-u" << mountPoint(), 10000);
}
void SftpPlugin::mountTimeout()

View file

@ -53,6 +53,8 @@ public Q_SLOTS:
Q_SCRIPTABLE void startBrowsing();
Q_SCRIPTABLE QString mountPoint();
protected:
void timerEvent(QTimerEvent *event);
@ -63,9 +65,11 @@ private Q_SLOTS:
void mountTimeout();
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 cleanMountPoint(QObject* mounter);
void cleanMountPoint();
void addToDolphin();
void removeFromDolphin();
private:
struct Pimpl;

20
kio/CMakeLists.txt Normal file
View file

@ -0,0 +1,20 @@
set(kio_kdeconnect_PART_SRCS
kiokdeconnect.cpp
kdebugnamespace.cpp)
kde4_add_plugin(kio_kdeconnect ${kio_kdeconnect_PART_SRCS})
add_dependencies(kio_kdeconnect libkdeconnect)
target_link_libraries(kio_kdeconnect
${KDE4_KDECORE_LIBS}
${KDE4_KIO_LIBRARY}
${KDE4_KDEUI_LIBRARY}
${QT_QTCORE_LIBRARY}
${QT_QTGUI_LIBRARY}
kdeconnect
)
########### install files ###############
install(TARGETS kio_kdeconnect DESTINATION ${PLUGIN_INSTALL_DIR})
install(FILES kdeconnect.protocol DESTINATION ${SERVICES_INSTALL_DIR})

26
kio/kdebugnamespace.cpp Normal file
View file

@ -0,0 +1,26 @@
/**
* Copyright 2013 Albert Vaca <albertvaka@gmail.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "kdebugnamespace.h"
int kdeconnect_kio() {
static int s_area = KDebug::registerArea("kdeconnect_kio", true);
return s_area;
}

29
kio/kdebugnamespace.h Normal file
View file

@ -0,0 +1,29 @@
/**
* Copyright 2013 Albert Vaca <albertvaka@gmail.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef KDEBUG_KDECONNECT_KCM_H
#define KDEBUG_KDECONNECT_KCM_H
#include <KDebug>
int kdeconnect_kio();
#endif

16
kio/kdeconnect.protocol Normal file
View file

@ -0,0 +1,16 @@
[Protocol]
exec=kio_kdeconnect
protocol=kdeconnect
input=none
output=filesystem
copyToFile=false
copyFromFile=false
listing=Name,Type,Access
reading=true
writing=false
makedir=false
deleting=false
moving=false
Icon=smartphone
maxInstances=2

190
kio/kiokdeconnect.cpp Normal file
View file

@ -0,0 +1,190 @@
/**
* Copyright 2013 Albert Vaca <albertvaka@gmail.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "kiokdeconnect.h"
#include <QtCore/QThread>
#include <QDBusMetaType>
#include <KDebug>
#include <KComponentData>
#include <KCmdLineArgs>
#include <KAboutData>
#include <KProcess>
#include <KApplication>
#include <KLocale>
#include "kdebugnamespace.h"
extern "C" int KDE_EXPORT kdemain(int argc, char **argv)
{
KAboutData about("kiokdeconnect", "kdeconnect", ki18n("kiokdeconnect"), "1.0");
KCmdLineArgs::init(&about);
KApplication app;
if (argc != 4) {
fprintf(stderr, "Usage: kio_kdeconnect protocol pool app\n");
exit(-1);
}
KioKdeconnect slave(argv[2], argv[3]);
slave.dispatchLoop();
return 0;
}
KioKdeconnect::KioKdeconnect(const QByteArray &pool, const QByteArray &app)
: SlaveBase("kdeconnect", pool, app),
m_dbusInterface(new DaemonDbusInterface(this))
{
}
void KioKdeconnect::listAllDevices()
{
infoMessage(i18n("Listing devices..."));
QStringList devices = m_dbusInterface->devices(true, true); //TODO: Change to all devices and show different icons for connected and disconnected?
totalSize(devices.length());
int i = 0;
Q_FOREACH(const QString& deviceId, devices) {
DeviceDbusInterface interface(deviceId);
if (!interface.hasPlugin("kdeconnect_sftp")) continue;
const QString target = QString("kdeconnect://").append(deviceId).append("/");
const QString name = interface.name();
const QString icon = "smartphone";
KIO::UDSEntry entry;
entry.insert(KIO::UDSEntry::UDS_NAME, name);
entry.insert(KIO::UDSEntry::UDS_ICON_NAME, icon);
entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR);
entry.insert(KIO::UDSEntry::UDS_ACCESS, S_IRUSR | S_IRGRP | S_IROTH);
entry.insert(KIO::UDSEntry::UDS_MIME_TYPE, "");
entry.insert(KIO::UDSEntry::UDS_URL, target);
listEntry(entry, false);
processedSize(i++);
}
listEntry(KIO::UDSEntry(), true);
infoMessage("");
finished();
}
void KioKdeconnect::listDevice()
{
infoMessage(i18n("Accessing device..."));
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();
KIO::UDSEntry entry;
entry.insert(KIO::UDSEntry::UDS_NAME, "files");
entry.insert(KIO::UDSEntry::UDS_DISPLAY_NAME, "Browse images");
entry.insert(KIO::UDSEntry::UDS_ICON_NAME, "folder");
entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR);
entry.insert(KIO::UDSEntry::UDS_ACCESS, S_IRUSR | S_IRGRP | S_IROTH);
entry.insert(KIO::UDSEntry::UDS_MIME_TYPE, "");
entry.insert(KIO::UDSEntry::UDS_URL, url + "/DCIM/Camera");
listEntry(entry, false);
entry.insert(KIO::UDSEntry::UDS_NAME, "files");
entry.insert(KIO::UDSEntry::UDS_DISPLAY_NAME, "Browse all files");
entry.insert(KIO::UDSEntry::UDS_ICON_NAME, "folder");
entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR);
entry.insert(KIO::UDSEntry::UDS_ACCESS, S_IRUSR | S_IRGRP | S_IROTH);
entry.insert(KIO::UDSEntry::UDS_MIME_TYPE, "");
entry.insert(KIO::UDSEntry::UDS_URL, url);
listEntry(entry, false);
listEntry(KIO::UDSEntry(), true);
infoMessage("");
finished();
}
void KioKdeconnect::listDir(const KUrl &url)
{
kDebug(kdeconnect_kio()) << "Listing..." << url;
/// Url is not used here becuase all we could care about the url is the host, and that's already
/// handled in @p setHost
Q_UNUSED(url);
if (!m_dbusInterface->isValid()) {
infoMessage(i18n("Could not contact background service."));
listEntry(KIO::UDSEntry(), true);
finished();
return;
}
if (m_currentDevice.isEmpty()) {
listAllDevices();
} else {
listDevice();
}
}
void KioKdeconnect::stat(const KUrl &url)
{
kDebug(kdeconnect_kio()) << "Stat: " << url;
KIO::UDSEntry entry;
entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR);
statEntry(entry);
finished();
}
void KioKdeconnect::get(const KUrl &url)
{
kDebug(kdeconnect_kio()) << "Get: " << url;
mimeType("");
finished();
}
void KioKdeconnect::setHost(const QString &hostName, quint16 port, const QString &user, const QString &pass)
{
//This is called before everything else to set the file we want to show
kDebug(kdeconnect_kio()) << "Setting host: " << hostName;
// In this kio only the hostname is used
Q_UNUSED(port)
Q_UNUSED(user)
Q_UNUSED(pass)
m_currentDevice = hostName;
}

61
kio/kiokdeconnect.h Normal file
View file

@ -0,0 +1,61 @@
/**
* Copyright 2013 Albert Vaca <albertvaka@gmail.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef KIOKDECONNECT_H
#define KIOKDECONNECT_H
#include <QObject>
#include <kio/slavebase.h>
#include "../libkdeconnect/dbusinterfaces.h"
class KioKdeconnect : public QObject, public KIO::SlaveBase
{
Q_OBJECT
public:
KioKdeconnect(const QByteArray &pool, const QByteArray &app);
void get(const KUrl &url);
void listDir(const KUrl &url);
void stat(const KUrl &url);
void setHost(const QString &constHostname, quint16 port, const QString &user, const QString &pass);
void listAllDevices(); //List all devices exported by m_dbusInterface
void listDevice(); //List m_currentDevice
private:
/**
* Contains the ID of the current device or is empty when no device is set.
*/
QString m_currentDevice;
/**
* KDED DBus interface, used to communicate to the daemon since we need some status (like connected)
*/
DaemonDbusInterface *m_dbusInterface;
};
#endif