Dolphin shell integration: share code between two plugins

This commit is contained in:
Olivier Goffart 2015-09-11 12:50:07 +02:00
parent 731d4b3d4d
commit 82d1d04774
7 changed files with 192 additions and 138 deletions

View File

@ -32,10 +32,11 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR})
add_definitions(-DQT_USE_FAST_CONCATENATION -DQT_USE_FAST_OPERATOR_PLUS)
kcoreaddons_add_plugin(ownclouddolphinplugin INSTALL_NAMESPACE "kf5/overlayicon" JSON ownclouddolphinplugin.json SOURCES ownclouddolphinplugin.cpp)
kcoreaddons_add_plugin(ownclouddolphinplugin INSTALL_NAMESPACE "kf5/overlayicon" JSON ownclouddolphinplugin.json
SOURCES ownclouddolphinplugin.cpp ownclouddolphinpluginhelper.cpp)
target_link_libraries(ownclouddolphinplugin Qt5::Network KF5::CoreAddons KF5::KIOCore KF5::KIOWidgets)
add_library(ownclouddolphinpluginaction MODULE ownclouddolphinpluginaction.cpp)
add_library(ownclouddolphinpluginaction MODULE ownclouddolphinpluginaction.cpp ownclouddolphinpluginhelper.cpp)
target_link_libraries(ownclouddolphinpluginaction Qt5::Network KF5::CoreAddons KF5::KIOCore KF5::KIOWidgets)
install(FILES ownclouddolphinpluginaction.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR})
install(TARGETS ownclouddolphinpluginaction DESTINATION ${KDE_INSTALL_PLUGINDIR})

View File

@ -21,41 +21,34 @@
#include <KPluginFactory>
#include <QtNetwork/QLocalSocket>
#include <KIOCore/kfileitem.h>
#include <QTimer>
#include "ownclouddolphinpluginhelper.h"
class OwncloudDolphinPlugin : public KOverlayIconPlugin
{
Q_PLUGIN_METADATA(IID "com.owncloud.ovarlayiconplugin" FILE "ownclouddolphinplugin.json");
Q_OBJECT
QLocalSocket m_socket;
typedef QHash<QByteArray, QByteArray> StatusMap;
StatusMap m_status;
QByteArray m_line;
public:
explicit OwncloudDolphinPlugin(QObject* parent = 0) : KOverlayIconPlugin(parent) {
connect(&m_socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
tryConnect();
OwncloudDolphinPlugin() {
auto helper = OwncloudDolphinPluginHelper::instance();
QObject::connect(helper, &OwncloudDolphinPluginHelper::commandRecieved,
this, &OwncloudDolphinPlugin::slotCommandRecieved);
}
virtual QStringList getOverlays(const QUrl& url) override {
QStringList getOverlays(const QUrl& url) override {
auto helper = OwncloudDolphinPluginHelper::instance();
if (!helper->isConnected())
return QStringList();
if (!url.isLocalFile())
return QStringList();
const QByteArray localFile = url.toLocalFile().toUtf8();
// kDebug() << localFile;
tryConnect();
if (m_socket.state() == QLocalSocket::ConnectingState) {
if (!m_socket.waitForConnected(100)) {
// kWarning() << "not connected" << m_socket.errorString();
}
}
if (m_socket.state() == QLocalSocket::ConnectedState) {
m_socket.write("RETRIEVE_FILE_STATUS:");
m_socket.write(localFile);
m_socket.write("\n");
}
helper->sendCommand("RETRIEVE_FILE_STATUS:" + localFile + "\n");
StatusMap::iterator it = m_status.find(localFile);
if (it != m_status.constEnd()) {
@ -64,18 +57,8 @@ public:
return QStringList();
}
private:
void tryConnect() {
if (m_socket.state() != QLocalSocket::UnconnectedState)
return;
QString runtimeDir = QFile::decodeName(qgetenv("XDG_RUNTIME_DIR"));
QString socketPath = runtimeDir + "/" + "ownCloud" + "/socket";
m_socket.connectToServer(socketPath);
}
QStringList overlaysForString(const QByteArray status) {
QStringList overlaysForString(const QByteArray &status) {
QStringList r;
if (status.startsWith("NOP"))
return r;
@ -91,33 +74,23 @@ private:
return r;
}
private slots:
void readyRead() {
while (m_socket.bytesAvailable()) {
m_line += m_socket.readLine();
if (!m_line.endsWith("\n"))
continue;
QByteArray line;
qSwap(line, m_line);
line.chop(1);
if (line.isEmpty())
continue;
QList<QByteArray> tokens = line.split(':');
if (tokens.count() != 3)
continue;
if (tokens[0] != "STATUS" && tokens[0] != "BROADCAST")
continue;
if (tokens[2].isEmpty())
continue;
void slotCommandRecieved(const QByteArray &line) {
const QByteArray name = tokens[2];
QByteArray &status = m_status[name]; // reference to the item in the hash
if (status == tokens[1])
continue;
status = tokens[1];
QList<QByteArray> tokens = line.split(':');
if (tokens.count() != 3)
return;
if (tokens[0] != "STATUS" && tokens[0] != "BROADCAST")
return;
if (tokens[2].isEmpty())
return;
emit this->overlaysChanged(QUrl::fromLocalFile(QString::fromUtf8(name)), overlaysForString(status));
}
const QByteArray name = tokens[2];
QByteArray &status = m_status[name]; // reference to the item in the hash
if (status == tokens[1])
return;
status = tokens[1];
emit overlaysChanged(QUrl::fromLocalFile(QString::fromUtf8(name)), overlaysForString(status));
}
};

View File

@ -1,6 +0,0 @@
[Desktop Entry]
Type=Service
Name=Owncloud
X-KDE-ServiceTypes=KOverlayIconPlugin
MimeType=text/plain;
X-KDE-Library=ownclouddolphinplugin

View File

@ -24,102 +24,39 @@
#include <KIOCore/kfileitem.h>
#include <KIOCore/KFileItemListProperties>
#include <QtWidgets/QAction>
class Connector : QObject {
Q_OBJECT
public:
QLocalSocket m_socket;
QByteArray m_line;
QVector<QString> m_paths;
QString m_shareActionString;
Connector() {
connect(&m_socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
tryConnect();
}
void tryConnect() {
if (m_socket.state() != QLocalSocket::UnconnectedState)
return;
QString runtimeDir = QFile::decodeName(qgetenv("XDG_RUNTIME_DIR"));
QString socketPath = runtimeDir + "/" + "ownCloud" + "/socket";
m_socket.connectToServer(socketPath);
if (m_socket.state() == QLocalSocket::ConnectingState) {
m_socket.waitForConnected(100);
}
if (m_socket.state() == QLocalSocket::ConnectedState) {
m_socket.write("SHARE_MENU_TITLE:\n");
m_socket.flush();
}
}
private slots:
void readyRead() {
while (m_socket.bytesAvailable()) {
m_line += m_socket.readLine();
if (!m_line.endsWith("\n"))
continue;
QByteArray line;
qSwap(line, m_line);
line.chop(1);
if (line.isEmpty())
continue;
if (line.startsWith("REGISTER_PATH:")) {
QString file = QString::fromUtf8(line.mid(line.indexOf(':') + 1));
m_paths.append(file);
continue;
} else if (line.startsWith("SHARE_MENU_TITLE:")) {
m_shareActionString = QString::fromUtf8(line.mid(line.indexOf(':') + 1));
continue;
}
}
}
};
#include <QtCore/QTimer>
#include "ownclouddolphinpluginhelper.h"
class OwncloudDolphinPluginAction : public KAbstractFileItemActionPlugin
{
public:
explicit OwncloudDolphinPluginAction(QObject* parent, const QList<QVariant>&) : KAbstractFileItemActionPlugin(parent) {
}
explicit OwncloudDolphinPluginAction(QObject* parent, const QList<QVariant>&)
: KAbstractFileItemActionPlugin(parent) { }
QList<QAction*> actions(const KFileItemListProperties& fileItemInfos, QWidget* parentWidget) Q_DECL_OVERRIDE
{
static Connector connector;
connector.tryConnect();
auto helper = OwncloudDolphinPluginHelper::instance();
QList<QUrl> urls = fileItemInfos.urlList();
if (urls.count() != 1 || connector.m_socket.state() != QLocalSocket::ConnectedState)
if (urls.count() != 1 || !helper->isConnected())
return {};
auto url = urls.first();
if (!url.isLocalFile())
return {};
auto localFile = url.toLocalFile();
if (!std::any_of(connector.m_paths.begin(), connector.m_paths.end(), [&](const QString &s) {
const auto paths = helper->paths();
if (!std::any_of(paths.begin(), paths.end(), [&](const QString &s) {
return localFile.startsWith(s);
} ))
return {};
auto act = new QAction(parentWidget);
act->setText(connector.m_shareActionString);
auto socket = &connector.m_socket;
connect(act, &QAction::triggered, this, [localFile, socket] {
socket->write("SHARE:");
socket->write(localFile.toUtf8());
socket->write("\n");
socket->flush();
act->setText(helper->shareActionString());
connect(act, &QAction::triggered, this, [localFile, helper] {
helper->sendCommand("SHARE:"+localFile.toUtf8()+"\n");
} );
return { act };
}
};

View File

@ -2,5 +2,5 @@
Type=Service
Name=OwncloudAction
ServiceTypes=KFileItemAction/Plugin
MimeType=text/plain;
MimeType=application/octet-stream;inode/directory;
X-KDE-Library=ownclouddolphinpluginaction

View File

@ -0,0 +1,98 @@
/******************************************************************************
* Copyright (C) 2014 by Olivier Goffart <ogoffart@woboq.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) any later version. *
* *
* 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, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
******************************************************************************/
#include <QtNetwork/QLocalSocket>
#include <qcoreevent.h>
#include <QFile>
#include "ownclouddolphinpluginhelper.h"
OwncloudDolphinPluginHelper* OwncloudDolphinPluginHelper::instance()
{
static OwncloudDolphinPluginHelper self;
return &self;
}
OwncloudDolphinPluginHelper::OwncloudDolphinPluginHelper()
{
connect(&_socket, &QLocalSocket::connected, this, &OwncloudDolphinPluginHelper::slotConnected);
connect(&_socket, &QLocalSocket::readyRead, this, &OwncloudDolphinPluginHelper::slotReadyRead);
_connectTimer.start(45 * 1000, Qt::VeryCoarseTimer, this);
tryConnect();
}
void OwncloudDolphinPluginHelper::timerEvent(QTimerEvent *e)
{
if (e->timerId() == _connectTimer.timerId()) {
tryConnect();
return;
}
QObject::timerEvent(e);
}
bool OwncloudDolphinPluginHelper::isConnected() const
{
return _socket.state() == QLocalSocket::ConnectedState;
}
void OwncloudDolphinPluginHelper::sendCommand(const char* data)
{
_socket.write(data);
_socket.flush();
}
void OwncloudDolphinPluginHelper::slotConnected()
{
sendCommand("SHARE_MENU_TITLE:\n");
}
void OwncloudDolphinPluginHelper::tryConnect()
{
if (_socket.state() != QLocalSocket::UnconnectedState) {
return;
}
QString runtimeDir = QFile::decodeName(qgetenv("XDG_RUNTIME_DIR"));
QString socketPath = runtimeDir + QLatin1String("/ownCloud/socket");
_socket.connectToServer(socketPath);
}
void OwncloudDolphinPluginHelper::slotReadyRead()
{
while (_socket.bytesAvailable()) {
_line += _socket.readLine();
if (!_line.endsWith("\n"))
continue;
QByteArray line;
qSwap(line, _line);
line.chop(1);
if (line.isEmpty())
continue;
if (line.startsWith("REGISTER_PATH:")) {
auto col = line.indexOf(':');
QString file = QString::fromUtf8(line.constData() + col + 1, line.size() - col - 1);
_paths.append(file);
continue;
} else if (line.startsWith("SHARE_MENU_TITLE:")) {
auto col = line.indexOf(':');
_shareActionString = QString::fromUtf8(line.constData() + col + 1, line.size() - col - 1);
continue;
}
emit commandRecieved(line);
}
}

View File

@ -0,0 +1,51 @@
/******************************************************************************
* Copyright (C) 2014 by Olivier Goffart <ogoffart@woboq.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) any later version. *
* *
* 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, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
******************************************************************************/
#pragma once
#include <QObject>
#include <QBasicTimer>
#include <QLocalSocket>
class OwncloudDolphinPluginHelper : public QObject {
Q_OBJECT
public:
static OwncloudDolphinPluginHelper *instance();
QString shareActionString() const { return _shareActionString; }
bool isConnected() const;
void sendCommand(const char *data);
QVector<QString> paths() const { return _paths; }
signals:
void commandRecieved(const QByteArray &cmd);
protected:
void timerEvent(QTimerEvent*) override;
private:
OwncloudDolphinPluginHelper();
void slotConnected();
void slotReadyRead();
void tryConnect();
QLocalSocket _socket;
QByteArray _line;
QVector<QString> _paths;
QString _shareActionString;
QBasicTimer _connectTimer;
};