File kdebase-trident-udisks2-backend.patch of Package kdebase3

From 27cc062c6b172fd6e93addb510269b360cb7eb8d Mon Sep 17 00:00:00 2001
From: Serghei Amelian <serghei.amelian@gmail.com>
Date: Wed, 30 May 2012 22:46:50 +0300
Subject: [PATCH] [mediamanager] initial support for UDisks2

---
 CMakeLists.txt                                     |    4 +
 kioslave/media/kcmodule/CMakeLists.txt             |   21 +-
 kioslave/media/kcmodule/managermodule.cpp          |   13 +-
 kioslave/media/kcmodule/managermoduleview.ui       |   16 +-
 .../media/libmediacommon/mediamanagersettings.kcfg |    5 +
 kioslave/media/mediamanager/CMakeLists.txt         |   47 +-
 kioslave/media/mediamanager/mediamanager.cpp       |   36 ++
 kioslave/media/mediamanager/mediamanager.h         |    4 +-
 kioslave/media/mediamanager/udisks2backend.cpp     |  654 ++++++++++++++++++++
 kioslave/media/mediamanager/udisks2backend.h       |   45 ++
 10 files changed, 800 insertions(+), 45 deletions(-)
 create mode 100644 kioslave/media/mediamanager/udisks2backend.cpp
 create mode 100644 kioslave/media/mediamanager/udisks2backend.h

diff --git a/kioslave/media/kcmodule/managermodule.cpp b/kioslave/media/kcmodule/managermodule.cpp
index e5f493d..e97344b 100644
--- a/kioslave/media/kcmodule/managermodule.cpp
+++ b/kioslave/media/kcmodule/managermodule.cpp
@@ -35,19 +35,26 @@
 
 	addConfig(  MediaManagerSettings::self(), view );
 
+#ifndef COMPILE_UDISKS2BACKEND
+	QString udisks2_text = view->kcfg_UDisks2BackendEnabled->text();
+	udisks2_text += " ("+i18n("No support for UDisks2 on this system")+")";
+	view->kcfg_UDisks2BackendEnabled->setText( udisks2_text );
+	view->kcfg_UDisks2BackendEnabled->setEnabled( false );
+#endif
+
 #ifndef COMPILE_HALBACKEND
 	QString hal_text = view->kcfg_HalBackendEnabled->text();
 	hal_text += " ("+i18n("No support for HAL on this system")+")";
 	view->kcfg_HalBackendEnabled->setText( hal_text );
-#endif
 	view->kcfg_HalBackendEnabled->setEnabled( false );
+#endif
 
 #ifndef COMPILE_LINUXCDPOLLING
 	QString poll_text = view->kcfg_CdPollingEnabled->text();
 	poll_text += " ("+i18n("No support for CD polling on this system")+")";
 	view->kcfg_CdPollingEnabled->setText( poll_text );
-#endif
 	view->kcfg_CdPollingEnabled->setEnabled( false );
+#endif
 
 	load();
 }
diff --git a/kioslave/media/kcmodule/managermoduleview.ui b/kioslave/media/kcmodule/managermoduleview.ui
index 5987183..1cca62f 100644
--- a/kioslave/media/kcmodule/managermoduleview.ui
+++ b/kioslave/media/kcmodule/managermoduleview.ui
@@ -12,12 +12,26 @@
             <height>480</height>
         </rect>
     </property>
+    <property name="caption">
+        <string>ManagerModuleView</string>
+    </property>
     <vbox>
         <property name="name">
             <cstring>unnamed</cstring>
         </property>
         <widget class="QCheckBox">
             <property name="name">
+                <cstring>kcfg_UDisks2BackendEnabled</cstring>
+            </property>
+            <property name="text">
+                <string>Enable UDisks2 backend</string>
+            </property>
+            <property name="whatsThis" stdset="0">
+                <string>Select this if you want to enable the UDisks2 (http://www.freedesktop.org/wiki/Software/udisks) support.</string>
+            </property>
+        </widget>
+        <widget class="QCheckBox">
+            <property name="name">
                 <cstring>kcfg_HalBackendEnabled</cstring>
             </property>
             <property name="text">
@@ -62,7 +76,7 @@
             <property name="sizeHint">
                 <size>
                     <width>21</width>
-                    <height>360</height>
+                    <height>320</height>
                 </size>
             </property>
         </spacer>
diff --git a/kioslave/media/libmediacommon/mediamanagersettings.kcfg b/kioslave/media/libmediacommon/mediamanagersettings.kcfg
index 4c9615a..5ad1e83 100644
--- a/kioslave/media/libmediacommon/mediamanagersettings.kcfg
+++ b/kioslave/media/libmediacommon/mediamanagersettings.kcfg
@@ -4,6 +4,11 @@
 <kcfg>
   <kcfgfile name="mediamanagerrc"/>
   <group name="Global">
+    <entry name="UDisks2BackendEnabled" type="Bool">
+      <label>Enable UDisks2 backend</label>
+      <whatsthis>When UDisks2 support is enabled, KDE will use it to gather information on the storage media available in your system.</whatsthis>
+      <default>true</default>
+    </entry>
     <entry name="HalBackendEnabled" type="Bool">
       <label>Enable HAL backend</label>
       <whatsthis>When HAL (Hardware Abstraction Layer) support is enabled, KDE will use it to gather information on the storage media available in your system.</whatsthis>
diff --git a/kioslave/media/mediamanager/mediamanager.cpp b/kioslave/media/mediamanager/mediamanager.cpp
index ad8f1b4..c52c668 100644
--- a/kioslave/media/mediamanager/mediamanager.cpp
+++ b/kioslave/media/mediamanager/mediamanager.cpp
@@ -32,6 +32,10 @@
 
 #include "fstabbackend.h"
 
+#ifdef COMPILE_UDISKS2BACKEND
+#include "udisks2backend.h"
+#endif // COMPILE_UDISKS2BACKEND
+
 #ifdef COMPILE_HALBACKEND
 #include "halbackend.h"
 #endif //COMPILE_HALBACKEND
@@ -77,9 +81,29 @@ void MediaManager::loadBackends()
     }
 
     mp_removableBackend = 0L;
+    m_udisks2backend = 0L;
     m_halbackend = 0L;
     m_fstabbackend = 0L;
 
+#ifdef COMPILE_UDISKS2BACKEND
+    if ( MediaManagerSettings::self()->uDisks2BackendEnabled() )
+    {
+        m_udisks2backend = new UDisks2Backend(m_mediaList);
+        if( m_udisks2backend->initialize() )
+        {
+            m_backends.append( m_udisks2backend );
+            // No need to load something else...
+            m_mediaList.blockSignals(false);
+            return;
+        }
+        else
+        {
+            delete m_udisks2backend;
+            m_udisks2backend = 0;
+        }
+    }
+#endif // COMPILE_UDISKS2BACKEND
+
 #ifdef COMPILE_HALBACKEND
     if ( MediaManagerSettings::self()->halBackendEnabled() )
     {
@@ -208,6 +232,11 @@ bool MediaManager::setMountoptions(const QString &name, const QStringList &optio
 
 QString MediaManager::mount(const QString &name)
 {
+#ifdef COMPILE_UDISKS2BACKEND
+    if (!m_udisks2backend)
+        return i18n("Feature only available with UDisks2");
+    return m_udisks2backend->mount(name);
+#else
 #ifdef COMPILE_HALBACKEND
     if (!m_halbackend)
         return i18n("Feature only available with HAL");
@@ -217,10 +246,16 @@ QString MediaManager::mount(const QString &name)
         return i18n("Feature only available with HAL");
     return m_fstabbackend->mount( name );
 #endif
+#endif
 }
 
 QString MediaManager::unmount(const QString &name)
 {
+#ifdef COMPILE_UDISKS2BACKEND
+    if (!m_udisks2backend)
+        return i18n("Feature only available with UDisks2");
+    return m_udisks2backend->unmount(name);
+#else
 #ifdef COMPILE_HALBACKEND
     if (!m_halbackend)
         return i18n("Feature only available with HAL");
@@ -230,6 +265,7 @@ QString MediaManager::unmount(const QString &name)
         return i18n("Feature only available with HAL");
     return m_fstabbackend->unmount( name );
 #endif
+#endif
 }
 
 QString MediaManager::nameForLabel(const QString &label)
diff --git a/kioslave/media/mediamanager/mediamanager.h b/kioslave/media/mediamanager/mediamanager.h
index 1e5aa1d..291ab32 100644
--- a/kioslave/media/mediamanager/mediamanager.h
+++ b/kioslave/media/mediamanager/mediamanager.h
@@ -28,6 +28,7 @@
 #include "removablebackend.h"
 #include "mediadirnotify.h"
 
+class UDisks2Backend;
 class HALBackend;
 class FstabBackend;
 
@@ -82,6 +83,7 @@ class MediaManager : public KDEDModule
 	MediaList m_mediaList;
 	QValueList<BackendBase*> m_backends;
 	RemovableBackend *mp_removableBackend;
+	UDisks2Backend *m_udisks2backend;
 	HALBackend *m_halbackend;
 	MediaDirNotify m_dirNotify;
 	FstabBackend *m_fstabbackend;
diff --git a/kioslave/media/mediamanager/udisks2backend.cpp b/kioslave/media/mediamanager/udisks2backend.cpp
new file mode 100644
index 0000000..e2e84a1
--- /dev/null
+++ b/kioslave/media/mediamanager/udisks2backend.cpp
@@ -0,0 +1,654 @@
+/*
+   This file is part of the KDE3 Fork Project
+   Copyright (c) 2012 Serghei Amelian <serghei.amelian@gmail.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 <qdict.h>
+
+#include <dbus/qdbusconnection.h>
+#include <dbus/qdbuserror.h>
+#include <dbus/qdbusdata.h>
+#include <dbus/qdbusdatalist.h>
+#include <dbus/qdbusdatamap.h>
+#include <dbus/qdbusmessage.h>
+#include <dbus/qdbusobjectpath.h>
+#include <dbus/qdbusproxy.h>
+#include <dbus/qdbusvariant.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+
+#include "udisks2backend.h"
+
+
+namespace UDisks2 {
+
+
+/***** Class declarations **************************/
+
+
+class Property {
+public:
+    Property(){}
+    Property(const QDBusData &data);
+
+    bool toBool() const;
+    int toInt() const;
+    QString toString() const;
+    QStringList toStringList() const;
+    QDBusObjectPath toObjectPath() const;
+
+private:
+    QDBusData m_data;
+};
+
+
+/***************************************************/
+
+
+class Object : public QDBusProxy {
+public:
+    Object(ObjectManager *objectManager, const QDBusObjectPath &objectPath, const QDBusConnection &dbusConnection);
+    ~Object();
+
+    bool isEmpty() const { return m_interfaces.isEmpty(); }
+
+    void addInterfaces(const QDBusDataMap<QString> &interfaces);
+    void removeInterfaces(const QValueList<QDBusData> &interfaces);
+
+    bool callMethod(const QString &interface, const QString &method, const QValueList<QDBusData> &params, QDBusData &response, QDBusError &error);
+
+private:
+    Medium *createMountableMedium();
+    Medium *createBlankOrAudioMedium();
+    bool checkMediaAvailability();
+    void propertiesChanged(const QString &interface, const QDBusDataMap<QString> &properties);
+    void handleDBusSignal(const QDBusMessage &message);
+
+private:
+    ObjectManager *m_objectManager;
+    QStringList m_interfaces;
+
+    bool m_mediaAvailable;
+
+    // drive interface
+    bool m_optical;
+    bool m_opticalBlank;
+    bool m_opticalAudio;
+    bool m_removable;
+    bool m_ejectable;
+    QString m_media;
+
+    // block device interface
+    bool m_mountable;
+    QDBusObjectPath m_drive;
+    QString m_device;
+    QString m_label;
+    QString m_fsType;
+
+    // filesystem interface
+    bool m_filesystem;
+    bool m_mounted;
+    QString m_mountPoint;
+};
+
+
+/***************************************************/
+
+
+class ObjectManager : public QDBusProxy {
+
+    friend class Object;
+
+public:
+    ObjectManager(MediaList &mediaList);
+    bool initialize();
+
+    Object *findObject(const QString &path) { return m_objects.find(path); }
+
+protected:
+    void handleDBusSignal(const QDBusMessage &message);
+
+private:
+    void interfacesAdded(const QDBusObjectPath &objectPath, const QDBusDataMap<QString> &interfaces);
+    void interfacesRemoved(const QDBusObjectPath &objectPath, const QValueList<QDBusData> &interfaces);
+
+private:
+    MediaList &m_mediaList;
+    QDict<Object> m_objects;
+    bool allowNotification;
+};
+
+
+
+/***** Helpers *************************************/
+
+
+inline QString qDBusByteListToString(const QDBusData &data)
+{
+    QValueList<Q_UINT8> byteList = data.toList().toByteList();
+
+    QString result;
+    for(QValueList<Q_UINT8>::const_iterator it = byteList.begin(); it != byteList.end() && (*it); ++it)
+      result.append(*it);
+    return result;
+}
+
+
+
+/***** class Property ******************************/
+
+
+Property::Property(const QDBusData &data)
+    : m_data(data)
+{
+}
+
+
+bool Property::toBool() const
+{
+    return m_data.toBool();
+}
+
+
+int Property::toInt() const
+{
+    if(QDBusData::UInt32 == m_data.type())
+        return m_data.toUInt32();
+    return m_data.toInt32();
+}
+
+
+QString Property::toString() const
+{
+    if(QDBusData::List == m_data.type())
+      return qDBusByteListToString(m_data);
+    return m_data.toString();
+}
+
+
+QStringList Property::toStringList() const
+{
+    QStringList stringList;
+
+    QValueList<QDBusData> list = m_data.toList().toQValueList();
+    for(QValueList<QDBusData>::const_iterator it = list.begin(); it != list.end(); ++it)
+        stringList << qDBusByteListToString(*it);
+
+    return stringList;
+}
+
+
+QDBusObjectPath Property::toObjectPath() const
+{
+    return m_data.toObjectPath();
+}
+
+
+
+/***** class Object ********************************/
+
+
+Object::Object(ObjectManager *objectManager, const QDBusObjectPath &objectPath, const QDBusConnection &dbusConnection)
+    : QDBusProxy(dbusConnection), m_objectManager(objectManager)
+{
+    setService("org.freedesktop.UDisks2");
+    setPath(objectPath);
+
+    m_mediaAvailable = false;
+    m_optical = false;
+    m_opticalBlank = false;
+    m_opticalAudio = false;
+    m_removable = false;
+    m_ejectable = false;
+    m_mountable = false;
+    m_filesystem = false;
+    m_mounted = false;
+}
+
+
+Object::~Object()
+{
+}
+
+
+void Object::addInterfaces(const QDBusDataMap<QString> &interfaces)
+{
+    for(QDBusDataMap<QString>::const_iterator it = interfaces.begin(); it != interfaces.end(); ++it) {
+        QString interface = it.key();
+
+        // add the interface to list
+        m_interfaces.append(interface);
+
+        // update properties for given interface
+        propertiesChanged(it.key(), it.data().toStringKeyMap());
+
+        // filesystem interface was added
+        if("org.freedesktop.UDisks2.Filesystem" == interface) {
+            m_filesystem = true;
+            checkMediaAvailability();
+        }
+    }
+}
+
+
+void Object::removeInterfaces(const QValueList<QDBusData> &interfaces)
+{
+    for(QValueList<QDBusData>::const_iterator it = interfaces.begin(); it != interfaces.end(); ++it) {
+        QString interface = (*it).toString();
+
+        // remove interface from list
+        m_interfaces.remove(interface);
+
+        // filesystem interface was removed
+        if("org.freedesktop.UDisks2.Filesystem" == interface) {
+            m_filesystem = false;
+            checkMediaAvailability();
+        }
+    }
+}
+
+
+bool Object::callMethod(const QString &interface, const QString &method, const QValueList<QDBusData> &params, QDBusData &response, QDBusError &error)
+{
+    QDBusProxy proxy(service(), path(), interface, connection());
+
+    QDBusMessage reply = proxy.sendWithReply(method, params);
+    if(reply.count() != 1 || reply.type() != QDBusMessage::ReplyMessage) {
+        error = proxy.lastError();
+        if(QDBusError::InvalidError != error.type())
+            return false;
+    }
+
+    response = reply.front();
+    return true;
+}
+
+
+Medium *Object::createMountableMedium()
+{
+    Object *drive =  m_objectManager->m_objects.find(m_drive);
+    Q_ASSERT(drive);
+
+    QString name = (m_label.isEmpty() ? QString(m_device).section('/', -1, -1) : m_label);
+
+    QString mimeType;
+    QString iconName;
+
+    // optical media
+    if(drive->m_optical) {
+        if("optical_cd_r" == drive->m_media.left(12))
+            mimeType = "media/cdwriter";
+        else if("optical_dvd" == drive->m_media.left(11))
+            mimeType = "media/dvd";
+        else
+            mimeType = "media/cdrom";
+    }
+
+    // removable media
+    else if(drive->m_removable) {
+        mimeType = "media/removable";
+    }
+
+    // other media
+    else {
+        mimeType = "media/hdd";
+    }
+
+    if("thumb" == drive->m_media)
+        iconName = "usbpendrive";
+    else if("flash_cf" == drive->m_media)
+        iconName = "compact_flash";
+    else if("flash_ms" == drive->m_media)
+        iconName = "memory_stick";
+    else if("flash_sm" == drive->m_media)
+        iconName = "smart_media";
+    else if("flash_sd" == drive->m_media.left(8))
+        iconName = "sd_mmc";
+    else if("flash_mmc" == drive->m_media)
+        iconName = "sd_mmc";
+    else if("floppy" == drive->m_media)
+        iconName = "3floppy";
+    else if("floppy_zip" == drive->m_media)
+        iconName = "zip";
+
+    mimeType += (m_mounted ? "_mounted" : "_unmounted");
+
+    if(!iconName.isEmpty())
+        iconName += (m_mounted ? "_mount" : "_unmount");
+
+    Medium *medium = new Medium(path(), name);
+    medium->setLabel(name);
+    medium->mountableState(m_device, m_mountPoint, m_fsType, m_mounted);
+    medium->setMimeType(mimeType);
+    medium->setIconName(iconName);
+
+    return medium;
+}
+
+
+Medium *Object::createBlankOrAudioMedium()
+{
+    QString name;
+    QString mimeType;
+    QString iconName;
+
+    // blank cd or dvd
+    if(m_opticalBlank) {
+        if("optical_dvd" == m_media.left(11)) {
+            name = i18n("Blank DVD");
+            mimeType = "media/blankdvd";
+        } else {
+            name = i18n("Blank CD");
+            mimeType = "media/blankcd";
+        }
+    }
+
+    // audio cd
+    else if(m_opticalAudio) {
+        name = i18n("Audio CD");
+        mimeType = "media/audiocd";
+    }
+
+    Medium *medium = new Medium(path(), name);
+    medium->setLabel(name);
+    medium->unmountableState("");
+    medium->setMimeType(mimeType);
+
+    return medium;
+}
+
+
+bool Object::checkMediaAvailability()
+{
+    bool mediaAvailable = (m_opticalBlank || m_opticalAudio || m_mountable && m_filesystem);
+    bool availabilityChanged = (m_mediaAvailable != mediaAvailable);
+
+    if(!availabilityChanged)
+        return false;
+
+    // media become available
+    if(mediaAvailable) {
+        Medium *medium = (m_mountable && m_filesystem ? createMountableMedium() : createBlankOrAudioMedium());
+        m_objectManager->m_mediaList.addMedium(medium, m_objectManager->allowNotification);
+    }
+
+    // media is not available anymore
+    else {
+        m_objectManager->m_mediaList.removeMedium(path(), true);
+    }
+
+    m_mediaAvailable = mediaAvailable;
+    return true;
+}
+
+
+void Object::propertiesChanged(const QString &interface, const QDBusDataMap<QString> &properties)
+{
+    QMap<QString, QDBusVariant> map = properties.toVariantMap();
+
+    bool mediumNeedUpdate = false;
+
+    for(QMap<QString, QDBusVariant>::Iterator it = map.begin(); it != map.end(); ++it) {
+        QString propertyName = it.key();
+        Property propertyValue(it.data().value);
+
+        // properties of drive
+        if("org.freedesktop.UDisks2.Drive" == interface) {
+            if("Optical" == propertyName)
+                m_optical = propertyValue.toBool();
+            else if("OpticalBlank" == propertyName)
+                m_opticalBlank = propertyValue.toBool();
+            else if("OpticalNumAudioTracks" == propertyName)
+                m_opticalAudio = (0 < propertyValue.toInt());
+            else if("Media" == propertyName)
+                m_media = propertyValue.toString();
+            else if("Removable" == propertyName)
+                m_removable = propertyValue.toBool();
+        }
+
+        // properties of block device
+        else if("org.freedesktop.UDisks2.Block" == interface) {
+            if("IdUsage" == propertyName)
+                m_mountable = ("filesystem" == propertyValue.toString());
+            else if("Drive" == propertyName)
+                m_drive = propertyValue.toObjectPath();
+            else if("PreferredDevice" == propertyName)
+                m_device = propertyValue.toString();
+            else if("IdLabel" == propertyName) {
+                m_label = propertyValue.toString();
+                mediumNeedUpdate = true;
+            }
+            else if("IdType" == propertyName)
+                m_fsType = propertyValue.toString();
+        }
+
+        // properties of filesystem
+        else if("org.freedesktop.UDisks2.Filesystem" == interface) {
+            if("MountPoints" == propertyName) {
+                QStringList mountPoints = propertyValue.toStringList();
+                m_mounted = (0 < mountPoints.count());
+                m_mountPoint = mountPoints.last();
+                mediumNeedUpdate = true;
+            }
+        }
+    }
+
+    // media availability was changed
+    if(checkMediaAvailability())
+        return;
+
+    if(mediumNeedUpdate) {
+        Medium *medium = (m_mountable && m_filesystem ? createMountableMedium() : createBlankOrAudioMedium());
+        m_objectManager->m_mediaList.changeMediumState(*medium, false);
+        delete medium;
+    }
+}
+
+
+void Object::handleDBusSignal(const QDBusMessage &message)
+{
+    // the message is not for our object
+    if(path() != message.path())
+        return;
+
+    // the message is not coming from dbus properties interface
+    if("org.freedesktop.DBus.Properties" != message.interface())
+        return;
+
+    // this object haven't this kind of udisks2 interface
+    QString interface = message[0].toString();
+    if(!m_interfaces.contains(interface))
+        return;
+
+    QString method = message.member();
+    if("PropertiesChanged" == method)
+        propertiesChanged(interface, message[1].toStringKeyMap());
+}
+
+
+
+/***** class ObjectManager *************************/
+
+
+ObjectManager::ObjectManager(MediaList &mediaList)
+    : m_mediaList(mediaList)
+{
+    setService("org.freedesktop.UDisks2");
+    setPath("/org/freedesktop/UDisks2");
+    setInterface("org.freedesktop.DBus.ObjectManager");
+
+    m_objects.setAutoDelete(true);
+    allowNotification = false;
+}
+
+
+bool ObjectManager::initialize()
+{
+    // try to establish a connection to system bus
+    QDBusConnection dbusConnection = QDBusConnection::systemBus();
+    if(!dbusConnection.isConnected()) {
+        kdDebug() << "UDisks2::ObjectManager: " << dbusConnection.lastError().message() << endl;
+        return false;
+    }
+
+    setConnection(dbusConnection);
+
+    // get udisks2 managed objects
+    QDBusMessage reply = sendWithReply("GetManagedObjects", QValueList<QDBusData>());
+    if(reply.count() != 1 || reply.type() != QDBusMessage::ReplyMessage) {
+        kdDebug() << "UDisks2::ObjectManager: " << lastError().message() << endl;
+        return false;
+    }
+
+    // convert dbus reply to array of ObjectPath
+    QDBusDataMap<QDBusObjectPath> objectPathMap = reply.front().toObjectPathKeyMap();
+
+    // we need to enumerate the drives first
+    for(QDBusDataMap<QDBusObjectPath>::const_iterator it = objectPathMap.begin(); it != objectPathMap.end(); ++it) {
+        if("/org/freedesktop/UDisks2/drives" == it.key().parentNode())
+            interfacesAdded(it.key(), it.data().toStringKeyMap());
+    }
+
+    // enumerate block devices
+    for(QDBusDataMap<QDBusObjectPath>::const_iterator it = objectPathMap.begin(); it != objectPathMap.end(); ++it) {
+        if("/org/freedesktop/UDisks2/block_devices" == it.key().parentNode())
+            interfacesAdded(it.key(), it.data().toStringKeyMap());
+    }
+
+    allowNotification = true;
+
+    return true;
+}
+
+
+void ObjectManager::handleDBusSignal(const QDBusMessage &message)
+{
+    if((service().startsWith(":") && service() != message.sender()) || path() != message.path() || interface() != message.interface())
+        return;
+
+    QString method = message.member();
+    QDBusObjectPath objectPath = message[0].toObjectPath();
+
+    if("InterfacesAdded" == method)
+        interfacesAdded(objectPath, message[1].toStringKeyMap());
+    else if("InterfacesRemoved" == method)
+        interfacesRemoved(objectPath, message[1].toQValueList());
+}
+
+
+void ObjectManager::interfacesAdded(const QDBusObjectPath &objectPath, const QDBusDataMap<QString> &interfaces)
+{
+    Object *object = m_objects.find(objectPath);
+
+    if(!object) {
+        object = new Object(this, objectPath, connection());
+        m_objects.insert(objectPath, object);
+    }
+
+    object->addInterfaces(interfaces);
+}
+
+
+void ObjectManager::interfacesRemoved(const QDBusObjectPath &objectPath, const QValueList<QDBusData> &interfaces)
+{
+    Object *object = m_objects.find(objectPath);
+
+    if(object) {
+        object->removeInterfaces(interfaces);
+
+        // destroy the object if it have no more interfaces
+        if(object->isEmpty())
+            m_objects.remove(objectPath);
+    }
+}
+
+
+} // namespace UDisks2
+
+
+
+/***** class UDisks2Backend ************************/
+
+
+UDisks2Backend::UDisks2Backend(MediaList &mediaList)
+    : BackendBase(mediaList)
+{
+    d = new UDisks2::ObjectManager(mediaList);
+}
+
+
+UDisks2Backend::~UDisks2Backend()
+{
+    delete d;
+}
+
+
+bool UDisks2Backend::initialize()
+{
+    return d->initialize();
+}
+
+
+QString UDisks2Backend::mount(const QString &name)
+{
+    const Medium *medium = m_mediaList.findById(name);
+    if(!medium)
+        return i18n("No such medium: %1").arg(name);
+
+    UDisks2::Object *obj = d->findObject(name);
+    if(!obj)
+        return i18n("No such udisks2 object in cache: %1").arg(name);
+
+    QMap<QString, QDBusVariant> options;
+
+    QValueList<QDBusData> params;
+    params << QDBusData::fromStringKeyMap(QDBusDataMap<QString>(options));
+
+    QDBusError error;
+    QDBusData response;
+
+    if(!obj->callMethod("org.freedesktop.UDisks2.Filesystem", "Mount", params, response, error))
+      return i18n("Unable to mount medium \"%1\".\nReason: %2").arg(medium->label()).arg(error.message());
+
+   return QString::null;
+}
+
+
+QString UDisks2Backend::unmount(const QString &name)
+{
+    const Medium *medium = m_mediaList.findById(name);
+    if(!medium)
+        return i18n("No such medium: %1").arg(name);
+
+    UDisks2::Object *obj = d->findObject(name);
+    if(!obj)
+        return i18n("No such udisks2 object in cache: %1").arg(name);
+
+    QMap<QString, QDBusVariant> options;
+
+    QValueList<QDBusData> params;
+    params << QDBusData::fromStringKeyMap(QDBusDataMap<QString>(options));
+
+    QDBusError error;
+    QDBusData response;
+
+    if(!obj->callMethod("org.freedesktop.UDisks2.Filesystem", "Unmount", params, response, error))
+      return i18n("Unable to unmount medium \"%1\".\nReason: %2").arg(medium->label()).arg(error.message());
+
+   return QString::null;
+}
diff --git a/kioslave/media/mediamanager/udisks2backend.h b/kioslave/media/mediamanager/udisks2backend.h
new file mode 100644
index 0000000..e02c4aa
--- /dev/null
+++ b/kioslave/media/mediamanager/udisks2backend.h
@@ -0,0 +1,45 @@
+/* This file is part of the KDE3 Fork Project
+   Copyright (c) 2012 Serghei Amelian <serghei.amelian@gmail.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 _UDISKS2BACKEND_H_
+#define _UDISKS2BACKEND_H_
+
+#include "backendbase.h"
+
+
+namespace UDisks2 {
+    class ObjectManager;
+}
+
+
+class UDisks2Backend : public BackendBase {
+public:
+    UDisks2Backend(MediaList &mediaList);
+    ~UDisks2Backend();
+
+    bool initialize();
+
+    QString mount(const QString &name);
+    QString unmount(const QString &name);
+
+private:
+    UDisks2::ObjectManager *d;
+};
+
+
+#endif
-- 
1.7.10

openSUSE Build Service is sponsored by