From 82d1d0477404cdb8024b63de25862c80bfe60f46 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 11 Sep 2015 12:50:07 +0200 Subject: [PATCH] Dolphin shell integration: share code between two plugins --- shell_integration/dolphin_kf5/CMakeLists.txt | 5 +- .../dolphin_kf5/ownclouddolphinplugin.cpp | 83 ++++++---------- .../dolphin_kf5/ownclouddolphinplugin.desktop | 6 -- .../ownclouddolphinpluginaction.cpp | 85 +++------------- .../ownclouddolphinpluginaction.desktop | 2 +- .../ownclouddolphinpluginhelper.cpp | 98 +++++++++++++++++++ .../dolphin_kf5/ownclouddolphinpluginhelper.h | 51 ++++++++++ 7 files changed, 192 insertions(+), 138 deletions(-) delete mode 100644 shell_integration/dolphin_kf5/ownclouddolphinplugin.desktop create mode 100644 shell_integration/dolphin_kf5/ownclouddolphinpluginhelper.cpp create mode 100644 shell_integration/dolphin_kf5/ownclouddolphinpluginhelper.h diff --git a/shell_integration/dolphin_kf5/CMakeLists.txt b/shell_integration/dolphin_kf5/CMakeLists.txt index 0a22cbe815..23286c1a67 100644 --- a/shell_integration/dolphin_kf5/CMakeLists.txt +++ b/shell_integration/dolphin_kf5/CMakeLists.txt @@ -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}) diff --git a/shell_integration/dolphin_kf5/ownclouddolphinplugin.cpp b/shell_integration/dolphin_kf5/ownclouddolphinplugin.cpp index c039bd42ea..983cb9628d 100644 --- a/shell_integration/dolphin_kf5/ownclouddolphinplugin.cpp +++ b/shell_integration/dolphin_kf5/ownclouddolphinplugin.cpp @@ -21,41 +21,34 @@ #include #include #include - +#include +#include "ownclouddolphinpluginhelper.h" class OwncloudDolphinPlugin : public KOverlayIconPlugin { Q_PLUGIN_METADATA(IID "com.owncloud.ovarlayiconplugin" FILE "ownclouddolphinplugin.json"); Q_OBJECT - QLocalSocket m_socket; typedef QHash 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 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 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)); } }; diff --git a/shell_integration/dolphin_kf5/ownclouddolphinplugin.desktop b/shell_integration/dolphin_kf5/ownclouddolphinplugin.desktop deleted file mode 100644 index 07fc63f337..0000000000 --- a/shell_integration/dolphin_kf5/ownclouddolphinplugin.desktop +++ /dev/null @@ -1,6 +0,0 @@ -[Desktop Entry] -Type=Service -Name=Owncloud -X-KDE-ServiceTypes=KOverlayIconPlugin -MimeType=text/plain; -X-KDE-Library=ownclouddolphinplugin diff --git a/shell_integration/dolphin_kf5/ownclouddolphinpluginaction.cpp b/shell_integration/dolphin_kf5/ownclouddolphinpluginaction.cpp index 81d04c45a3..9299156e9b 100644 --- a/shell_integration/dolphin_kf5/ownclouddolphinpluginaction.cpp +++ b/shell_integration/dolphin_kf5/ownclouddolphinpluginaction.cpp @@ -24,102 +24,39 @@ #include #include #include - - -class Connector : QObject { - Q_OBJECT -public: - QLocalSocket m_socket; - QByteArray m_line; - QVector 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 +#include "ownclouddolphinpluginhelper.h" class OwncloudDolphinPluginAction : public KAbstractFileItemActionPlugin { public: - explicit OwncloudDolphinPluginAction(QObject* parent, const QList&) : KAbstractFileItemActionPlugin(parent) { - } + explicit OwncloudDolphinPluginAction(QObject* parent, const QList&) + : KAbstractFileItemActionPlugin(parent) { } QList actions(const KFileItemListProperties& fileItemInfos, QWidget* parentWidget) Q_DECL_OVERRIDE { - static Connector connector; - connector.tryConnect(); - + auto helper = OwncloudDolphinPluginHelper::instance(); QList 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 }; - } }; diff --git a/shell_integration/dolphin_kf5/ownclouddolphinpluginaction.desktop b/shell_integration/dolphin_kf5/ownclouddolphinpluginaction.desktop index 0fdc00c058..5cc4589a08 100644 --- a/shell_integration/dolphin_kf5/ownclouddolphinpluginaction.desktop +++ b/shell_integration/dolphin_kf5/ownclouddolphinpluginaction.desktop @@ -2,5 +2,5 @@ Type=Service Name=OwncloudAction ServiceTypes=KFileItemAction/Plugin -MimeType=text/plain; +MimeType=application/octet-stream;inode/directory; X-KDE-Library=ownclouddolphinpluginaction diff --git a/shell_integration/dolphin_kf5/ownclouddolphinpluginhelper.cpp b/shell_integration/dolphin_kf5/ownclouddolphinpluginhelper.cpp new file mode 100644 index 0000000000..027e0e68ee --- /dev/null +++ b/shell_integration/dolphin_kf5/ownclouddolphinpluginhelper.cpp @@ -0,0 +1,98 @@ +/****************************************************************************** + * Copyright (C) 2014 by Olivier Goffart +#include +#include +#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); + } +} diff --git a/shell_integration/dolphin_kf5/ownclouddolphinpluginhelper.h b/shell_integration/dolphin_kf5/ownclouddolphinpluginhelper.h new file mode 100644 index 0000000000..e8386df779 --- /dev/null +++ b/shell_integration/dolphin_kf5/ownclouddolphinpluginhelper.h @@ -0,0 +1,51 @@ +/****************************************************************************** + * Copyright (C) 2014 by Olivier Goffart +#include +#include + +class OwncloudDolphinPluginHelper : public QObject { + Q_OBJECT +public: + static OwncloudDolphinPluginHelper *instance(); + + QString shareActionString() const { return _shareActionString; } + bool isConnected() const; + void sendCommand(const char *data); + QVector 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 _paths; + QString _shareActionString; + QBasicTimer _connectTimer; +};