[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kfm-devel
Subject:    Re: Overlay icons in Dolphin and Konqueror
From:       Olivier Goffart <olivier () woboq ! com>
Date:       2014-07-17 17:55:23
Message-ID: 5982513.JsDzdt9xJa () finn
[Download RAW message or body]

On Friday 04 July 2014 10:51:16 Olivier Goffart wrote:
> Hi,
> 
> I am working with the ownCloud sync client. One of the feature we would like
> to have is to display overlay icons in the file managers. The icons should
> display the synchronization state, and more importantly the fact that
> folders are shared.
> 
> As far as I could see, there is no interface in Konqueror or Dolphin to show
> arbitrary overlay icon.
> I am aware of KVersionControlPlugin (and we already have such a plugin), but
> it's interface is too limited, as only some possibilities are available,
> but we would like to display any kind of icons.
> 
> I am then going to implement such interface.
> Where should it go?
> in a new KFileOverlayIconPlugin class?
> Should id go in kio (next KAbstractFileItemActionPlugin)?
> Or should it go in lib/konq next to KVersionControlPlugin?
> 
> For the implementation, I believe I can base myself on the
> KVersionControlPlugin but returning an QIcon instead of state.

Thanks Frank and David for your answer.

I drafted some (working) work in progress. The patch is attached.
The prototype owncloud plugin is also attached (but the communication protocol 
is not set in stone and is going to be only released in the next version of 
the client)
So I can have feedback if I'm going in the right direction.

I guess I'm too late with this to go into KDE SC 4.14?
So my next question is weather there would be another version of Dolphin based 
on kdelibs, or if I should just go for the frameworks branch.

(For some reason, the "shared" icon is suddenly a very important feature for 
owncloud, and they would like to have it ASAP for the users now that Owncloud 
7 (the server) was released)

 
> Please reply to all, I am not subscribed.

-- 
Olivier



["0001-WIP-add-KOverlayIconPlugin.patch" (0001-WIP-add-KOverlayIconPlugin.patch)]

From 813f0fba8997c079e15dd0cc2509d26c9ae5af7d Mon Sep 17 00:00:00 2001
From: Olivier Goffart <ogoffart@woboq.com>
Date: Thu, 17 Jul 2014 13:26:56 +0200
Subject: [PATCH] WIP: add KOverlayIconPlugin

---
 .../src/kitemviews/kfileitemmodelrolesupdater.cpp  | 35 ++++++++++++-
 .../src/kitemviews/kfileitemmodelrolesupdater.h    |  9 ++++
 lib/konq/CMakeLists.txt                            |  4 +-
 lib/konq/koverlayiconplugin.cpp                    | 30 ++++++++++++
 lib/konq/koverlayiconplugin.desktop                |  4 ++
 lib/konq/koverlayiconplugin.h                      | 57 ++++++++++++++++++++++
 6 files changed, 137 insertions(+), 2 deletions(-)
 create mode 100644 lib/konq/koverlayiconplugin.cpp
 create mode 100644 lib/konq/koverlayiconplugin.desktop
 create mode 100644 lib/konq/koverlayiconplugin.h

diff --git a/dolphin/src/kitemviews/kfileitemmodelrolesupdater.cpp \
b/dolphin/src/kitemviews/kfileitemmodelrolesupdater.cpp index 0865d40..840a65d 100644
--- a/dolphin/src/kitemviews/kfileitemmodelrolesupdater.cpp
+++ b/dolphin/src/kitemviews/kfileitemmodelrolesupdater.cpp
@@ -28,9 +28,11 @@
 #include <KGlobal>
 #include <KIO/JobUiDelegate>
 #include <KIO/PreviewJob>
+#include <KServiceTypeTrader>
 
 #include "private/kpixmapmodifier.h"
 #include "private/kdirectorycontentscounter.h"
+#include <koverlayiconplugin.h>
 
 #include <QApplication>
 #include <QPainter>
@@ -129,6 +131,17 @@ \
                KFileItemModelRolesUpdater::KFileItemModelRolesUpdater(KFileItemModel* \
                model, QO
     m_directoryContentsCounter = new KDirectoryContentsCounter(m_model, this);
     connect(m_directoryContentsCounter, SIGNAL(result(QString,int)),
             this,                       \
SLOT(slotDirectoryContentsCountReceived(QString,int))); +
+
+    const KService::List pluginServices = \
KServiceTypeTrader::self()->query("KOverlayIconPlugin"); +
+    for (KService::List::ConstIterator it = pluginServices.constBegin(); it != \
pluginServices.constEnd(); ++it) { +        KOverlayIconPlugin* plugin = \
(*it)->createInstance<KOverlayIconPlugin>(this); +        if (plugin) {
+            m_overlayIconsPlugin.append(plugin);
+            connect(plugin, SIGNAL(overlaysChanged(KUrl,QStringList)), this, \
SLOT(slotOverlaysChanged(KUrl,QStringList))); +        }
+    }
 }
 
 KFileItemModelRolesUpdater::~KFileItemModelRolesUpdater()
@@ -1075,7 +1088,11 @@ QHash<QByteArray, QVariant> \
KFileItemModelRolesUpdater::rolesData(const KFileIte  data.insert("type", \
item.mimeComment());  }
 
-    data.insert("iconOverlays", item.overlays());
+    QStringList overlays = item.overlays();
+    foreach(KOverlayIconPlugin *it, m_overlayIconsPlugin) {
+        overlays.append(it->getOverlays(item));
+    }
+    data.insert("iconOverlays", overlays);
 
 #ifdef HAVE_BALOO
     if (m_balooFileMonitor) {
@@ -1086,6 +1103,22 @@ QHash<QByteArray, QVariant> \
KFileItemModelRolesUpdater::rolesData(const KFileIte  return data;
 }
 
+void KFileItemModelRolesUpdater::slotOverlaysChanged(const KUrl& url, const \
QStringList &) +{
+    KFileItem item = m_model->fileItem(url);
+    if (item.isNull())
+        return;
+    int index = m_model->index(item);
+    QHash <QByteArray, QVariant> data =  m_model->data(index);
+    QStringList overlays = item.overlays();
+    foreach(KOverlayIconPlugin *it, m_overlayIconsPlugin) {
+        overlays.append(it->getOverlays(item));
+    }
+    data.insert("iconOverlays", overlays);
+    m_model->setData(index, data);
+}
+
+
 void KFileItemModelRolesUpdater::updateAllPreviews()
 {
     if (m_state == Paused) {
diff --git a/dolphin/src/kitemviews/kfileitemmodelrolesupdater.h \
b/dolphin/src/kitemviews/kfileitemmodelrolesupdater.h index a9e979a..6d3add0 100644
--- a/dolphin/src/kitemviews/kfileitemmodelrolesupdater.h
+++ b/dolphin/src/kitemviews/kfileitemmodelrolesupdater.h
@@ -32,6 +32,7 @@
 #include <QSize>
 #include <QStringList>
 
+class KOverlayIconPlugin;
 class KDirectoryContentsCounter;
 class KFileItemModel;
 class KJob;
@@ -180,6 +181,12 @@ private slots:
     void slotPreviewJobFinished();
 
     /**
+     * Is invoked when one of the KOverlayIconPlugin emit the signal that an overlay \
has changed +     */
+    void slotOverlaysChanged(const KUrl&, const QStringList&);
+
+
+    /**
      * Resolves the sort role of the next item in m_pendingSortRole, applies it
      * to the model, and invokes itself if there are any pending items left. If
      * that is not the case, \a startUpdating() is called.
@@ -331,6 +338,8 @@ private:
 
     KDirectoryContentsCounter* m_directoryContentsCounter;
 
+    QList<KOverlayIconPlugin*> m_overlayIconsPlugin;
+
 #ifdef HAVE_BALOO
     Baloo::FileMonitor* m_balooFileMonitor;
 #endif
diff --git a/lib/konq/CMakeLists.txt b/lib/konq/CMakeLists.txt
index 8ecbfa9..7381caf 100644
--- a/lib/konq/CMakeLists.txt
+++ b/lib/konq/CMakeLists.txt
@@ -22,6 +22,7 @@ set(konq_LIB_SRCS
    konq_historyprovider.cpp
    kversioncontrolplugin.cpp  # used by dolphin and its version control plugins \
(deprecated)  kversioncontrolplugin2.cpp # used by dolphin and its version control \
plugins +   koverlayiconplugin.cpp
 
    konq_nameandurlinputdialog.cpp # deprecated (functionality has moved to kdelibs)
    knewmenu.cpp # deprecated (functionality has moved to kdelibs)
@@ -67,8 +68,9 @@ install( FILES
  konq_fileitemcapabilities.h
  kversioncontrolplugin.h
  kversioncontrolplugin2.h
+ koverlayiconplugin.h
  konq_historyprovider.h
  konq_historyentry.h
 DESTINATION ${INCLUDE_INSTALL_DIR} COMPONENT Devel
 )
-install( FILES konqpopupmenuplugin.desktop konqdndpopupmenuplugin.desktop  \
DESTINATION  ${SERVICETYPES_INSTALL_DIR} ) +install( FILES \
konqpopupmenuplugin.desktop konqdndpopupmenuplugin.desktop koverlayiconplugin.desktop \
                DESTINATION  ${SERVICETYPES_INSTALL_DIR} )
diff --git a/lib/konq/koverlayiconplugin.cpp b/lib/konq/koverlayiconplugin.cpp
new file mode 100644
index 0000000..6125040
--- /dev/null
+++ b/lib/konq/koverlayiconplugin.cpp
@@ -0,0 +1,30 @@
+/*****************************************************************************
+ * Copyright (C) 2014 by Olivier Goffart <ogoffart@woboq.com>                *
+ *                                                                           *
+ * This library is free software; you can redistribute it and/or             *
+ * modify it under the terms of the GNU Library General Public               *
+ * License version 2 as published by the Free Software Foundation.           *
+ *                                                                           *
+ * This library 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         *
+ * Library General Public License for more details.                          *
+ *                                                                           *
+ * You should have received a copy of the GNU Library General Public License *
+ * along with this library; see the file COPYING.LIB.  If not, write to      *
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,      *
+ * Boston, MA 02110-1301, USA.                                               *
+ *****************************************************************************/
+
+#include "koverlayiconplugin.h"
+#include <KFileItem>
+
+KOverlayIconPlugin::KOverlayIconPlugin(QObject* parent) : QObject(parent)
+{
+}
+
+KOverlayIconPlugin::~KOverlayIconPlugin()
+{
+}
+
+#include "koverlayiconplugin.moc"
diff --git a/lib/konq/koverlayiconplugin.desktop \
b/lib/konq/koverlayiconplugin.desktop new file mode 100644
index 0000000..65a1170
--- /dev/null
+++ b/lib/konq/koverlayiconplugin.desktop
@@ -0,0 +1,4 @@
+[Desktop Entry]
+Type=ServiceType
+X-KDE-ServiceType=KOverlayIconPlugin
+Comment=Plugin to add overlay icons in Dolphin
diff --git a/lib/konq/koverlayiconplugin.h b/lib/konq/koverlayiconplugin.h
new file mode 100644
index 0000000..bcdf31b
--- /dev/null
+++ b/lib/konq/koverlayiconplugin.h
@@ -0,0 +1,57 @@
+/*****************************************************************************
+ * Copyright (C) 2014 by Olivier Goffart <ogoffart@woboq.com>                *
+ *                                                                           *
+ * This library is free software; you can redistribute it and/or             *
+ * modify it under the terms of the GNU Library General Public               *
+ * License version 2 as published by the Free Software Foundation.           *
+ *                                                                           *
+ * This library 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         *
+ * Library General Public License for more details.                          *
+ *                                                                           *
+ * You should have received a copy of the GNU Library General Public License *
+ * along with this library; see the file COPYING.LIB.  If not, write to      *
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,      *
+ * Boston, MA 02110-1301, USA.                                               *
+ *****************************************************************************/
+
+
+#ifndef OverlayIconPlugin_H
+#define OverlayIconPlugin_H
+
+#include <QtCore/QObject>
+#include <libkonq_export.h>
+
+class KUrl;
+class KFileItem;
+
+/**
+ * @brief Base class for overlay icon plugins.
+ *
+ * Enables the file manager to show custom overlay icons on files.
+ *
+ * To write a custom plugin you need to create a .desktop file for your plugin with
+ * KDE-ServiceTypes=KOverlayIconPlugin
+ */
+class LIBKONQ_EXPORT KOverlayIconPlugin : public QObject {
+    Q_OBJECT
+    void *d;
+public:
+    explicit KOverlayIconPlugin(QObject *parent = 0);
+    ~KOverlayIconPlugin();
+
+    /**
+     * Returns a list of overlay pixmap to add to a file
+     * This can be a path to an icon, or the icon name
+     */
+    virtual QStringList getOverlays(const KFileItem &item) = 0;
+signals:
+
+    /**
+     * Emit this signal when the list of overlay icon changed for a given URL
+     */
+    void overlaysChanged(const KUrl &url, const QStringList &overlays);
+};
+
+#endif
-- 
2.0.1


["ownclouddolphinplugin.cpp" (ownclouddolphinplugin.cpp)]

/******************************************************************************
 *   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 <koverlayiconplugin.h>
#include <KPluginFactory>
#include <KPluginLoader>
#include <kdebug.h>
#include <kfileitem.h>
#include <QtNetwork/QTcpSocket>
#include <QtNetwork/QHostAddress>



class OwncloudDolphinPlugin : public KOverlayIconPlugin
{
    Q_OBJECT
    QTcpSocket m_socket;
    typedef QHash<QByteArray, QByteArray> StatusMap;
    StatusMap m_status;
    QByteArray m_line;

public:
    explicit OwncloudDolphinPlugin(QObject* parent, const QList<QVariant>&) : \
KOverlayIconPlugin(parent) {  connect(&m_socket, SIGNAL(readyRead()), this, \
SLOT(readyRead()));  tryConnect();
    }

    virtual QStringList getOverlays(const KFileItem& item) {

        KUrl url = item.url();
        if (!url.isLocalFile())
            return QStringList();
        const QByteArray localFile = url.toLocalFile().toUtf8();
        kDebug() << localFile;

        tryConnect();
        if (m_socket.state() == QAbstractSocket::ConnectingState || m_socket.state() \
== QAbstractSocket::HostLookupState) {  if (!m_socket.waitForConnected(100)) {
                kWarning() << "not connected" << m_socket.errorString();
            }
        }
        if (m_socket.state() == QAbstractSocket::ConnectedState) {
            m_socket.write("RETRIEVE_FILE_STATUS:");
            m_socket.write(localFile);
            m_socket.write("\n");
        }

        StatusMap::iterator it = m_status.find(localFile);
        if (it != m_status.constEnd()) {
            return  overlaysForString(*it);
        }
        return QStringList();
    }



private:
    void tryConnect() {
        if (m_socket.state() != QAbstractSocket::UnconnectedState)
            return;
        m_socket.connectToHost(QHostAddress::LocalHost, 33001);
    }

    QStringList overlaysForString(const QByteArray status) {
        QStringList r;
        if (status.startsWith("NOP"))
            return r;

        if (status.startsWith("OK"))
            r << "dialog-ok";
        if (status.startsWith("SYNC") || status.startsWith("NEW"))
            r << "view-refresh";

        if (status.contains("+SWM"))
            r << "document-share";

        kDebug() << status << r;
        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);
            kDebug() << "got line " << line;
            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;

            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];

            emit this->overlaysChanged(KUrl::fromLocalFile(QString::fromUtf8(name)), \
overlaysForString(status));  }
    }
};

K_PLUGIN_FACTORY(OwncloudDolphinPluginFactory, \
registerPlugin<OwncloudDolphinPlugin>();) \
K_EXPORT_PLUGIN(OwncloudDolphinPluginFactory("ownclouddolhpinplugin"))


#include "ownclouddolphinplugin.moc"



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic