[kdelibs] add udisks2 Solid backend plus RHEL conditional

Lukas Tinkl ltinkl at fedoraproject.org
Mon Apr 16 17:50:35 UTC 2012


commit 7dbe0c221e01d037f17fe9faa0d68750d7ca5097
Author: Lukas Tinkl <lukas at kde.org>
Date:   Mon Apr 16 19:50:29 2012 +0200

    add udisks2 Solid backend plus RHEL conditional

 kdelibs-udisks2-backend.patch | 3661 +++++++++++++++++++++++++++++++++++++++++
 kdelibs.spec                  |   14 +-
 2 files changed, 3674 insertions(+), 1 deletions(-)
---
diff --git a/kdelibs-udisks2-backend.patch b/kdelibs-udisks2-backend.patch
new file mode 100644
index 0000000..fc4838d
--- /dev/null
+++ b/kdelibs-udisks2-backend.patch
@@ -0,0 +1,3661 @@
+diff --git a/tier1/solid/src/solid/CMakeLists.txt b/tier1/solid/src/solid/CMakeLists.txt
+index 5deadcf..40af6bc 100644
+--- a/tier1/solid/src/solid/CMakeLists.txt
++++ b/tier1/solid/src/solid/CMakeLists.txt
+@@ -32,7 +32,6 @@ configure_file(config-processor.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-proce
+ 
+ file(MAKE_DIRECTORY
+    ${CMAKE_CURRENT_BINARY_DIR}/backends/fakehw
+-   ${CMAKE_CURRENT_BINARY_DIR}/backends/hal
+    ${CMAKE_CURRENT_BINARY_DIR}/backends/udev
+    ${CMAKE_CURRENT_BINARY_DIR}/backends/wmi
+ )
+@@ -198,33 +197,6 @@ if(NOT WIN32 AND NOT APPLE)
+    endif( UDEV_FOUND )
+ 
+ 
+-   message(STATUS "Building Solid HAL backend." )
+-   set(solid_LIB_SRCS ${solid_LIB_SRCS}
+-   backends/hal/halacadapter.cpp
+-   backends/hal/halaudiointerface.cpp
+-   backends/hal/halbattery.cpp
+-   backends/hal/halblock.cpp
+-   backends/hal/halbutton.cpp
+-   backends/hal/halcamera.cpp
+-   backends/hal/halcdrom.cpp
+-   backends/hal/haldeviceinterface.cpp
+-   backends/hal/haldvbinterface.cpp
+-   backends/hal/halfstabhandling.cpp
+-   backends/hal/halgenericinterface.cpp
+-   backends/hal/haldevice.cpp
+-   backends/hal/halmanager.cpp
+-   backends/hal/halnetworkinterface.cpp
+-   backends/hal/halserialinterface.cpp
+-   backends/hal/halopticaldisc.cpp
+-   backends/hal/halportablemediaplayer.cpp
+-   backends/hal/halprocessor.cpp
+-   backends/hal/halstorageaccess.cpp
+-   backends/hal/halstorage.cpp
+-   backends/hal/halvideo.cpp
+-   backends/hal/halvolume.cpp
+-   backends/hal/halsmartcardreader.cpp
+-   )
+-
+    message(STATUS "Building Solid UPower backend." )
+    set(solid_LIB_SRCS ${solid_LIB_SRCS}
+    backends/upower/upowermanager.cpp
+@@ -237,18 +209,19 @@ if(NOT WIN32 AND NOT APPLE)
+ 
+    # FIXME: this should work on more Unix systems
+    if (CMAKE_SYSTEM_NAME MATCHES Linux)
+-      message(STATUS "Building Solid UDisks backend." )
++      message(STATUS "Building Solid UDisks2 backend." )
+       set(solid_LIB_SRCS ${solid_LIB_SRCS}
+-      backends/udisks/udisksmanager.cpp
+-      backends/udisks/udisksdevice.cpp
+-      backends/udisks/udisksblock.cpp
+-      backends/udisks/udisksstoragevolume.cpp
+-      backends/udisks/udisksdeviceinterface.cpp
+-      backends/udisks/udisksopticaldisc.cpp
+-      backends/udisks/udisksopticaldrive.cpp
+-      backends/udisks/udisksstoragedrive.cpp
+-      backends/udisks/udisksstorageaccess.cpp
+-      backends/udisks/udisksgenericinterface.cpp
++      backends/udisks2/udisksmanager.cpp
++      backends/udisks2/udisksdevice.cpp
++      backends/udisks2/udisksblock.cpp
++      backends/udisks2/udisksstoragevolume.cpp
++      backends/udisks2/udisksdeviceinterface.cpp
++      backends/udisks2/udisksopticaldisc.cpp
++      backends/udisks2/udisksopticaldrive.cpp
++      backends/udisks2/udisksstoragedrive.cpp
++      backends/udisks2/udisksstorageaccess.cpp
++      backends/udisks2/udisksgenericinterface.cpp
++      backends/udisks2/dbus/manager.cpp
+       )
+    endif (CMAKE_SYSTEM_NAME MATCHES Linux)
+ 
+diff --git a/tier1/solid/src/solid/managerbase.cpp b/tier1/solid/src/solid/managerbase.cpp
+index e228b48..7a7cc7d 100644
+--- a/tier1/solid/src/solid/managerbase.cpp
++++ b/tier1/solid/src/solid/managerbase.cpp
+@@ -30,8 +30,7 @@
+ #if defined (Q_OS_MAC)
+ #include "backends/iokit/iokitmanager.h"
+ #elif defined (Q_OS_UNIX)
+-#include "backends/hal/halmanager.h"
+-#include "backends/udisks/udisksmanager.h"
++#include "backends/udisks2/udisksmanager.h"
+ #include "backends/upower/upowermanager.h"
+ 
+ #if defined (HUPNP_FOUND)
+@@ -71,22 +70,13 @@ void Solid::ManagerBasePrivate::loadBackends()
+ #        elif defined(Q_OS_WIN) && defined(HAVE_WBEM) && !defined(_WIN32_WCE)
+             m_backends << new Solid::Backends::Wmi::WmiManager(0);
+ 
+-#        elif defined(Q_OS_UNIX) && !defined(Q_OS_LINUX)
+-            m_backends << new Solid::Backends::Hal::HalManager(0);
+-
+ #        elif defined(Q_OS_LINUX)
+-            bool solidHalLegacyEnabled
+-                = QString::fromLocal8Bit(qgetenv("SOLID_HAL_LEGACY")).toInt()==1;
+-            if (solidHalLegacyEnabled) {
+-                m_backends << new Solid::Backends::Hal::HalManager(0);
+-            } else {
+ #               if defined(UDEV_FOUND)
+                     m_backends << new Solid::Backends::UDev::UDevManager(0);
+ #               endif
+-                m_backends << new Solid::Backends::UDisks::UDisksManager(0)
++                m_backends << new Solid::Backends::UDisks2::Manager(0)
+                            << new Solid::Backends::UPower::UPowerManager(0)
+                            << new Solid::Backends::Fstab::FstabManager(0);
+-            }
+ #        endif
+ 
+ #        if defined (HUPNP_FOUND)
+diff --git a/tier1/solid/src/solid/backends/udisks2/dbus/manager.cpp b/tier1/solid/src/solid/backends/udisks2/dbus/manager.cpp
+new file mode 100644
+index 0000000..7ea4aa8
+--- /dev/null
++++ b/tier1/solid/src/solid/backends/udisks2/dbus/manager.cpp
+@@ -0,0 +1,26 @@
++/*
++ * This file was generated by qdbusxml2cpp version 0.7
++ * Command line was: qdbusxml2cpp -p manager manager.xml
++ *
++ * qdbusxml2cpp is Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
++ *
++ * This is an auto-generated file.
++ * This file may have been hand-edited. Look for HAND-EDIT comments
++ * before re-generating it.
++ */
++
++#include "manager.h"
++
++/*
++ * Implementation of interface class OrgFreedesktopDBusObjectManagerInterface
++ */
++
++OrgFreedesktopDBusObjectManagerInterface::OrgFreedesktopDBusObjectManagerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
++    : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
++{
++}
++
++OrgFreedesktopDBusObjectManagerInterface::~OrgFreedesktopDBusObjectManagerInterface()
++{
++}
++
+diff --git a/tier1/solid/src/solid/backends/udisks2/dbus/manager.h b/tier1/solid/src/solid/backends/udisks2/dbus/manager.h
+new file mode 100644
+index 0000000..11f0be8
+--- /dev/null
++++ b/tier1/solid/src/solid/backends/udisks2/dbus/manager.h
+@@ -0,0 +1,59 @@
++/*
++ * This file was generated by qdbusxml2cpp version 0.7
++ * Command line was: qdbusxml2cpp -p manager manager.xml
++ *
++ * qdbusxml2cpp is Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
++ *
++ * This is an auto-generated file.
++ * Do not edit! All changes made to it will be lost.
++ */
++
++#ifndef MANAGER_H_1329493525
++#define MANAGER_H_1329493525
++
++#include <QtCore/QObject>
++#include <QtCore/QByteArray>
++#include <QtCore/QList>
++#include <QtCore/QMap>
++#include <QtCore/QString>
++#include <QtCore/QStringList>
++#include <QtCore/QVariant>
++#include <QtDBus/QtDBus>
++
++#include "../udisks2.h"
++
++/*
++ * Proxy class for interface org.freedesktop.DBus.ObjectManager
++ */
++class OrgFreedesktopDBusObjectManagerInterface: public QDBusAbstractInterface
++{
++    Q_OBJECT
++public:
++    static inline const char *staticInterfaceName()
++    { return "org.freedesktop.DBus.ObjectManager"; }
++
++public:
++    OrgFreedesktopDBusObjectManagerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
++
++    ~OrgFreedesktopDBusObjectManagerInterface();
++
++public Q_SLOTS: // METHODS
++    inline QDBusPendingReply<DBUSManagerStruct> GetManagedObjects()
++    {
++        QList<QVariant> argumentList;
++        return asyncCallWithArgumentList(QLatin1String("GetManagedObjects"), argumentList);
++    }
++
++Q_SIGNALS: // SIGNALS
++    void InterfacesAdded(const QDBusObjectPath &object_path, const QVariantMapMap &interfaces_and_properties);
++    void InterfacesRemoved(const QDBusObjectPath &object_path, const QStringList &interfaces);
++};
++
++namespace org {
++  namespace freedesktop {
++    namespace DBus {
++      typedef ::OrgFreedesktopDBusObjectManagerInterface ObjectManager;
++    }
++  }
++}
++#endif
+diff --git a/tier1/solid/src/solid/backends/udisks2/dbus/manager.xml b/tier1/solid/src/solid/backends/udisks2/dbus/manager.xml
+new file mode 100644
+index 0000000..8f25cb6
+--- /dev/null
++++ b/tier1/solid/src/solid/backends/udisks2/dbus/manager.xml
+@@ -0,0 +1,21 @@
++<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
++                      "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
++<node>
++  <interface name="org.freedesktop.DBus.ObjectManager">
++    <method name="GetManagedObjects">
++      <arg type="a{oa{sa{sv}}}" name="object_paths_interfaces_and_properties" direction="out">
++        <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="DBUSManagerStruct"/>
++      </arg>
++    </method>
++    <signal name="InterfacesAdded">
++      <arg type="o" name="object_path"/>
++      <arg type="a{sa{sv}}" name="interfaces_and_properties">
++        <annotation name="com.trolltech.QtDBus.QtTypeName.In1" value="QVariantMapMap"/>
++      </arg>
++    </signal>
++    <signal name="InterfacesRemoved">
++      <arg type="o" name="object_path"/>
++      <arg type="as" name="interfaces"/>
++    </signal>
++  </interface>
++</node>
+diff --git a/tier1/solid/src/solid/backends/udisks2/udisks2.h b/tier1/solid/src/solid/backends/udisks2/udisks2.h
+new file mode 100644
+index 0000000..25a1dc0
+--- /dev/null
++++ b/tier1/solid/src/solid/backends/udisks2/udisks2.h
+@@ -0,0 +1,77 @@
++/*
++    Copyright 2012 Lukáš Tinkl <ltinkl at redhat.com>
++
++    This library is free software; you can redistribute it and/or
++    modify it under the terms of the GNU Lesser General Public
++    License as published by the Free Software Foundation; either
++    version 2.1 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 6 of version 3 of the license.
++
++    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
++    Lesser General Public License for more details.
++
++    You should have received a copy of the GNU Lesser General Public
++    License along with this library. If not, see <http://www.gnu.org/licenses/>.
++*/
++
++#ifndef SOLID_BACKENDS_UDISKS2_H
++#define SOLID_BACKENDS_UDISKS2_H
++
++#include <QMetaType>
++#include <QtDBus>
++#include <QVariant>
++#include <QMap>
++#include <QList>
++
++typedef QList<QByteArray> QByteArrayList;
++Q_DECLARE_METATYPE(QByteArrayList)
++
++typedef QMap<QString,QVariantMap> QVariantMapMap;
++Q_DECLARE_METATYPE(QVariantMapMap)
++
++typedef QMap<QDBusObjectPath, QVariantMapMap> DBUSManagerStruct;
++Q_DECLARE_METATYPE(DBUSManagerStruct)
++
++/* UDisks2 */
++#define UD2_DBUS_SERVICE                 "org.freedesktop.UDisks2"
++#define UD2_DBUS_PATH                    "/org/freedesktop/UDisks2"
++#define UD2_UDI_DISKS_PREFIX             "/org/freedesktop/UDisks2"
++#define UD2_DBUS_PATH_MANAGER            "/org/freedesktop/UDisks2/Manager"
++#define UD2_DBUS_PATH_DRIVES             "/org/freedesktop/UDisks2/drives/"
++#define UD2_DBUS_PATH_JOBS               "/org/freedesktop/UDisks2/jobs/"
++#define DBUS_INTERFACE_PROPS             "org.freedesktop.DBus.Properties"
++#define DBUS_INTERFACE_INTROSPECT        "org.freedesktop.DBus.Introspectable"
++#define DBUS_INTERFACE_MANAGER           "org.freedesktop.DBus.ObjectManager"
++#define UD2_DBUS_INTERFACE_BLOCK         "org.freedesktop.UDisks2.Block"
++#define UD2_DBUS_INTERFACE_DRIVE         "org.freedesktop.UDisks2.Drive"
++#define UD2_DBUS_INTERFACE_PARTITION     "org.freedesktop.UDisks2.Partition"
++#define UD2_DBUS_INTERFACE_PARTITIONTABLE   "org.freedesktop.UDisks2.PartitionTable"
++#define UD2_DBUS_INTERFACE_FILESYSTEM    "org.freedesktop.UDisks2.Filesystem"
++#define UD2_DBUS_INTERFACE_ENCRYPTED     "org.freedesktop.UDisks2.Encrypted"
++#define UD2_DBUS_INTERFACE_SWAP          "org.freedesktop.UDisks2.Swapspace"
++
++/* errors */
++#define UD2_ERROR_UNAUTHORIZED            "org.freedesktop.PolicyKit.Error.NotAuthorized"
++#define UD2_ERROR_BUSY                    "org.freedesktop.UDisks2.Error.DeviceBusy"
++#define UD2_ERROR_FAILED                  "org.freedesktop.UDisks2.Error.Failed"
++#define UD2_ERROR_CANCELED                "org.freedesktop.UDisks2.Error.Cancelled"
++#define UD2_ERROR_INVALID_OPTION          "org.freedesktop.UDisks2.Error.OptionNotPermitted"
++#define UD2_ERROR_MISSING_DRIVER          "org.freedesktop.UDisks2.Error.NotSupported"
++
++#define UD2_ERROR_ALREADY_MOUNTED         "org.freedesktop.UDisks2.Error.AlreadyMounted"
++#define UD2_ERROR_NOT_MOUNTED             "org.freedesktop.UDisks2.Error.NotMounted"
++#define UD2_ERROR_MOUNTED_BY_OTHER_USER   "org.freedesktop.UDisks2.Error.MountedByOtherUser"
++#define UD2_ERROR_ALREADY_UNMOUNTING      "org.freedesktop.UDisks2.Error.AlreadyUnmounting"
++#define UD2_ERROR_TIMED_OUT               "org.freedesktop.UDisks2.Error.Timedout"
++#define UD2_ERROR_WOULD_WAKEUP            "org.freedesktop.UDisks2.Error.WouldWakeup"
++#define UD2_ERROR_ALREADY_CANCELLED       "org.freedesktop.UDisks2.Error.AlreadyCancelled"
++
++#define UD2_ERROR_NOT_AUTHORIZED          "org.freedesktop.UDisks2.Error.NotAuthorized"
++#define UD2_ERROR_NOT_AUTHORIZED_CAN_OBTAIN  "org.freedesktop.UDisks2.Error.NotAuthorizedCanObtain"
++#define UD2_ERROR_NOT_AUTHORIZED_DISMISSED   "org.freedesktop.UDisks2.Error.NotAuthorizedDismissed"
++
++#endif // SOLID_BACKENDS_UDISKS2_H
+diff --git a/tier1/solid/src/solid/backends/udisks2/udisksblock.cpp b/tier1/solid/src/solid/backends/udisks2/udisksblock.cpp
+new file mode 100644
+index 0000000..8a7a0b5
+--- /dev/null
++++ b/tier1/solid/src/solid/backends/udisks2/udisksblock.cpp
+@@ -0,0 +1,52 @@
++/*
++    Copyright 2012 Lukáš Tinkl <ltinkl at redhat.com>
++
++    This library is free software; you can redistribute it and/or
++    modify it under the terms of the GNU Lesser General Public
++    License as published by the Free Software Foundation; either
++    version 2.1 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 6 of version 3 of the license.
++
++    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
++    Lesser General Public License for more details.
++
++    You should have received a copy of the GNU Lesser General Public
++    License along with this library. If not, see <http://www.gnu.org/licenses/>.
++*/
++
++#include <linux/kdev_t.h>
++
++#include <QFile>
++
++#include "udisksblock.h"
++
++using namespace Solid::Backends::UDisks2;
++
++Block::Block(Device *device)
++    : DeviceInterface(device)
++{
++    m_devNum = m_device->prop("DeviceNumber").toULongLong();
++}
++
++Block::~Block()
++{
++}
++
++QString Block::device() const
++{
++    return QFile::decodeName(m_device->prop("Device").toByteArray());
++}
++
++int Block::deviceMinor() const
++{
++    return MINOR(m_devNum);
++}
++
++int Block::deviceMajor() const
++{
++    return MAJOR(m_devNum);
++}
+diff --git a/tier1/solid/src/solid/backends/udisks2/udisksblock.h b/tier1/solid/src/solid/backends/udisks2/udisksblock.h
+new file mode 100644
+index 0000000..804d712
+--- /dev/null
++++ b/tier1/solid/src/solid/backends/udisks2/udisksblock.h
+@@ -0,0 +1,55 @@
++/*
++    Copyright 2012 Lukáš Tinkl <ltinkl at redhat.com>
++
++    This library is free software; you can redistribute it and/or
++    modify it under the terms of the GNU Lesser General Public
++    License as published by the Free Software Foundation; either
++    version 2.1 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 6 of version 3 of the license.
++
++    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
++    Lesser General Public License for more details.
++
++    You should have received a copy of the GNU Lesser General Public
++    License along with this library. If not, see <http://www.gnu.org/licenses/>.
++*/
++
++#ifndef UDISKS2BLOCK_H
++#define UDISKS2BLOCK_H
++
++#include <solid/ifaces/block.h>
++#include "udisksdeviceinterface.h"
++
++namespace Solid
++{
++namespace Backends
++{
++namespace UDisks2
++{
++
++class Block: public DeviceInterface, virtual public Solid::Ifaces::Block
++{
++
++    Q_OBJECT
++    Q_INTERFACES(Solid::Ifaces::Block)
++
++public:
++    Block(Device *device);
++    virtual ~Block();
++
++    virtual QString device() const;
++    virtual int deviceMinor() const;
++    virtual int deviceMajor() const;
++private:
++    dev_t m_devNum;
++};
++
++}
++}
++}
++
++#endif // UDISKS2BLOCK_H
+diff --git a/tier1/solid/src/solid/backends/udisks2/udisksdevice.cpp b/tier1/solid/src/solid/backends/udisks2/udisksdevice.cpp
+new file mode 100644
+index 0000000..628c0b0
+--- /dev/null
++++ b/tier1/solid/src/solid/backends/udisks2/udisksdevice.cpp
+@@ -0,0 +1,906 @@
++/*
++    Copyright 2010 Michael Zanetti <mzanetti at kde.org>
++    Copyright 2010-2012 Lukáš Tinkl <ltinkl at redhat.com>
++
++    This library is free software; you can redistribute it and/or
++    modify it under the terms of the GNU Lesser General Public
++    License as published by the Free Software Foundation; either
++    version 2.1 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 6 of version 3 of the license.
++
++    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
++    Lesser General Public License for more details.
++
++    You should have received a copy of the GNU Lesser General Public
++    License along with this library. If not, see <http://www.gnu.org/licenses/>.
++*/
++
++#include "udisksdevice.h"
++#include "udisksblock.h"
++#include "udisksdeviceinterface.h"
++#include "udisksstoragevolume.h"
++#include "udisksopticaldisc.h"
++#include "udisksopticaldrive.h"
++#include "udisksstorageaccess.h"
++#include "udisksgenericinterface.h"
++
++#include <solid/genericinterface.h>
++#include <solid/deviceinterface.h>
++#include <solid/device.h>
++
++#include <QtCore/QDebug>
++
++#include <QtDBus/QDBusMessage>
++#include <QtDBus/QDBusMetaType>
++#include <QtDBus/QDBusPendingReply>
++#include <QtDBus/QDBusArgument>
++
++#include <QtXml/QDomDocument>
++
++using namespace Solid::Backends::UDisks2;
++
++// Adapted from KLocale as Solid needs to be Qt-only
++static QString formatByteSize(double size)
++{
++    // Per IEC 60027-2
++
++    // Binary prefixes
++    //Tebi-byte             TiB             2^40    1,099,511,627,776 bytes
++    //Gibi-byte             GiB             2^30    1,073,741,824 bytes
++    //Mebi-byte             MiB             2^20    1,048,576 bytes
++    //Kibi-byte             KiB             2^10    1,024 bytes
++
++    QString s;
++    // Gibi-byte
++    if ( size >= 1073741824.0 )
++    {
++        size /= 1073741824.0;
++        if ( size > 1024 ) // Tebi-byte
++            s = QObject::tr("%1 TiB").arg(QLocale().toString(size / 1024.0, 'f', 1));
++        else
++            s = QObject::tr("%1 GiB").arg(QLocale().toString(size, 'f', 1));
++    }
++    // Mebi-byte
++    else if ( size >= 1048576.0 )
++    {
++        size /= 1048576.0;
++        s = QObject::tr("%1 MiB").arg(QLocale().toString(size, 'f', 1));
++    }
++    // Kibi-byte
++    else if ( size >= 1024.0 )
++    {
++        size /= 1024.0;
++        s = QObject::tr("%1 KiB").arg(QLocale().toString(size, 'f', 1));
++    }
++    // Just byte
++    else if ( size > 0 )
++    {
++        s = QObject::tr("%1 B").arg(QLocale().toString(size, 'f', 1));
++    }
++    // Nothing
++    else
++    {
++        s = QObject::tr("0 B");
++    }
++    return s;
++}
++
++Device::Device(const QString &udi)
++    : Solid::Ifaces::Device()
++    , m_udi(udi)
++{
++    m_device = new QDBusInterface(UD2_DBUS_SERVICE, m_udi,
++                                  QString(), // no interface, we aggregate them
++                                  QDBusConnection::systemBus());
++
++    if (m_device->isValid()) {
++        QDBusConnection::systemBus().connect(UD2_DBUS_SERVICE, m_udi, DBUS_INTERFACE_PROPS, "PropertiesChanged", this,
++                                             SLOT(slotPropertiesChanged(QString,QVariantMap,QStringList)));
++
++        QDBusConnection::systemBus().connect(UD2_DBUS_SERVICE, UD2_DBUS_PATH, DBUS_INTERFACE_MANAGER, "InterfacesAdded",
++                                             this, SLOT(slotInterfacesAdded(QDBusObjectPath,QVariantMapMap)));
++        QDBusConnection::systemBus().connect(UD2_DBUS_SERVICE, UD2_DBUS_PATH, DBUS_INTERFACE_MANAGER, "InterfacesRemoved",
++                                             this, SLOT(slotInterfacesRemoved(QDBusObjectPath,QStringList)));
++
++        initInterfaces();
++    }
++}
++
++Device::~Device()
++{
++    delete m_device;
++}
++
++QObject* Device::createDeviceInterface(const Solid::DeviceInterface::Type& type)
++{
++    if (!queryDeviceInterface(type)) {
++        return 0;
++    }
++
++    DeviceInterface *iface = 0;
++    switch (type)
++    {
++    case Solid::DeviceInterface::GenericInterface:
++        iface = new GenericInterface(this);
++        break;
++    case Solid::DeviceInterface::Block:
++        iface = new Block(this);
++        break;
++    case Solid::DeviceInterface::StorageAccess:
++        iface = new StorageAccess(this);
++        break;
++    case Solid::DeviceInterface::StorageDrive:
++        iface = new StorageDrive(this);
++        break;
++    case Solid::DeviceInterface::OpticalDrive:
++        iface = new OpticalDrive(this);
++        break;
++    case Solid::DeviceInterface::StorageVolume:
++        iface = new StorageVolume(this);
++        break;
++    case Solid::DeviceInterface::OpticalDisc:
++        iface = new OpticalDisc(this);
++        break;
++    default:
++        break;
++    }
++    return iface;
++}
++
++bool Device::queryDeviceInterface(const Solid::DeviceInterface::Type& type) const
++{
++    switch (type) {
++    case Solid::DeviceInterface::GenericInterface:
++        return true;
++    case Solid::DeviceInterface::Block:
++        return isBlock();
++    case Solid::DeviceInterface::StorageVolume:
++        return isStorageVolume();
++    case Solid::DeviceInterface::StorageAccess:
++        return isStorageAccess();
++    case Solid::DeviceInterface::StorageDrive:
++        return isDrive();
++    case Solid::DeviceInterface::OpticalDrive:
++        return isOpticalDrive();
++    case Solid::DeviceInterface::OpticalDisc:
++        return isOpticalDisc();
++    default:
++        return false;
++    }
++}
++
++QStringList Device::emblems() const
++{
++    QStringList res;
++
++    if (queryDeviceInterface(Solid::DeviceInterface::StorageAccess))
++    {
++        const UDisks2::StorageAccess accessIface(const_cast<Device *>(this));
++        if (accessIface.isAccessible())
++        {
++            if (isEncryptedContainer())
++                res << "emblem-encrypted-unlocked";
++            else
++                res << "emblem-mounted";
++        }
++        else
++        {
++            if (isEncryptedContainer())
++                res << "emblem-encrypted-locked";
++            else
++                res << "emblem-unmounted";
++        }
++    }
++
++    return res;
++}
++
++QString Device::description() const
++{
++    const QString hintName = prop("HintName").toString();
++    if (!hintName.isEmpty())
++        return hintName;
++
++    if (queryDeviceInterface(Solid::DeviceInterface::StorageDrive))
++        return storageDescription();
++    else if (queryDeviceInterface(Solid::DeviceInterface::StorageVolume))
++        return volumeDescription();
++    else
++        return product();
++}
++
++QString Device::storageDescription() const
++{
++    QString description;
++    const UDisks2::StorageDrive storageDrive(const_cast<Device*>(this));
++    Solid::StorageDrive::DriveType drive_type = storageDrive.driveType();
++    bool drive_is_hotpluggable = storageDrive.isHotpluggable();
++
++    if (drive_type == Solid::StorageDrive::CdromDrive)
++    {
++        const UDisks2::OpticalDrive opticalDrive(const_cast<Device*>(this));
++        Solid::OpticalDrive::MediumTypes mediumTypes = opticalDrive.supportedMedia();
++        QString first;
++        QString second;
++
++        first = QObject::tr("CD-ROM", "First item of %1%2 Drive sentence");
++        if (mediumTypes & Solid::OpticalDrive::Cdr)
++            first = QObject::tr("CD-R", "First item of %1%2 Drive sentence");
++        if (mediumTypes & Solid::OpticalDrive::Cdrw)
++            first = QObject::tr("CD-RW", "First item of %1%2 Drive sentence");
++
++        if (mediumTypes & Solid::OpticalDrive::Dvd)
++            second = QObject::tr("/DVD-ROM", "Second item of %1%2 Drive sentence");
++        if (mediumTypes & Solid::OpticalDrive::Dvdplusr)
++            second = QObject::tr("/DVD+R", "Second item of %1%2 Drive sentence");
++        if (mediumTypes & Solid::OpticalDrive::Dvdplusrw)
++            second = QObject::tr("/DVD+RW", "Second item of %1%2 Drive sentence");
++        if (mediumTypes & Solid::OpticalDrive::Dvdr)
++            second = QObject::tr("/DVD-R", "Second item of %1%2 Drive sentence");
++        if (mediumTypes & Solid::OpticalDrive::Dvdrw)
++            second = QObject::tr("/DVD-RW", "Second item of %1%2 Drive sentence");
++        if (mediumTypes & Solid::OpticalDrive::Dvdram)
++            second = QObject::tr("/DVD-RAM", "Second item of %1%2 Drive sentence");
++        if ((mediumTypes & Solid::OpticalDrive::Dvdr) && (mediumTypes & Solid::OpticalDrive::Dvdplusr))
++        {
++            if(mediumTypes & Solid::OpticalDrive::Dvdplusdl)
++                second = QObject::trUtf8("/DVD±R DL", "Second item of %1%2 Drive sentence");
++            else
++                second = QObject::trUtf8("/DVD±R", "Second item of %1%2 Drive sentence");
++        }
++        if ((mediumTypes & Solid::OpticalDrive::Dvdrw) && (mediumTypes & Solid::OpticalDrive::Dvdplusrw))
++        {
++            if((mediumTypes & Solid::OpticalDrive::Dvdplusdl) || (mediumTypes & Solid::OpticalDrive::Dvdplusdlrw))
++                second = QObject::trUtf8("/DVD±RW DL", "Second item of %1%2 Drive sentence");
++            else
++                second = QObject::trUtf8("/DVD±RW", "Second item of %1%2 Drive sentence");
++        }
++        if (mediumTypes & Solid::OpticalDrive::Bd)
++            second = QObject::tr("/BD-ROM", "Second item of %1%2 Drive sentence");
++        if (mediumTypes & Solid::OpticalDrive::Bdr)
++            second = QObject::tr("/BD-R", "Second item of %1%2 Drive sentence");
++        if (mediumTypes & Solid::OpticalDrive::Bdre)
++            second = QObject::tr("/BD-RE", "Second item of %1%2 Drive sentence");
++        if (mediumTypes & Solid::OpticalDrive::HdDvd)
++            second = QObject::tr("/HD DVD-ROM", "Second item of %1%2 Drive sentence");
++        if (mediumTypes & Solid::OpticalDrive::HdDvdr)
++            second = QObject::tr("/HD DVD-R", "Second item of %1%2 Drive sentence");
++        if (mediumTypes & Solid::OpticalDrive::HdDvdrw)
++            second = QObject::tr("/HD DVD-RW", "Second item of %1%2 Drive sentence");
++
++        if (drive_is_hotpluggable)
++            description = QObject::tr("External %1%2 Drive", "%1 is CD-ROM/CD-R/etc; %2 is '/DVD-ROM'/'/DVD-R'/etc (with leading slash)").arg(first).arg(second);
++        else
++            description = QObject::tr("%1%2 Drive", "%1 is CD-ROM/CD-R/etc; %2 is '/DVD-ROM'/'/DVD-R'/etc (with leading slash)").arg(first).arg(second);
++
++        return description;
++    }
++
++    if (drive_type == Solid::StorageDrive::Floppy)
++    {
++        if (drive_is_hotpluggable)
++            description = QObject::tr("External Floppy Drive");
++        else
++            description = QObject::tr("Floppy Drive");
++
++        return description;
++    }
++
++    bool drive_is_removable = storageDrive.isRemovable();
++
++    if (drive_type == Solid::StorageDrive::HardDisk && !drive_is_removable)
++    {
++        QString size_str = formatByteSize(storageDrive.size());
++        if (!size_str.isEmpty())
++        {
++            if (drive_is_hotpluggable)
++                description = QObject::tr("%1 External Hard Drive", "%1 is the size").arg(size_str);
++            else
++                description = QObject::tr("%1 Hard Drive", "%1 is the size").arg(size_str);
++        } else {
++            if (drive_is_hotpluggable)
++                description = QObject::tr("External Hard Drive");
++            else
++                description = QObject::tr("Hard Drive");
++        }
++
++        return description;
++    }
++
++    QString vendormodel_str;
++    QString model = product();
++    QString vendor_str = vendor();
++
++    if (vendor_str.isEmpty())
++    {
++        if (!model.isEmpty())
++            vendormodel_str = model;
++    }
++    else
++    {
++        if (model.isEmpty())
++            vendormodel_str = vendor_str;
++        else
++        {
++            if (model.startsWith(vendor_str))
++            {
++                // e.g. vendor is "Nokia" and model is "Nokia N950" we do not want "Nokia Nokia N950" as description
++                vendormodel_str = model;
++            }
++            else
++            {
++                vendormodel_str = QObject::tr("%1 %2", "%1 is the vendor, %2 is the model of the device").arg(vendor_str).arg(model);
++            }
++        }
++    }
++
++    if (vendormodel_str.isEmpty())
++        description = QObject::tr("Drive");
++    else
++        description = vendormodel_str;
++
++    return description;
++}
++
++QString Device::volumeDescription() const
++{
++    QString description;
++    const UDisks2::StorageVolume storageVolume(const_cast<Device*>(this));
++    QString volume_label = prop("IdLabel").toString();
++    if (volume_label.isEmpty())
++        volume_label = prop("Name").toString();
++    if (!volume_label.isEmpty())
++        return volume_label;
++
++    const QString drivePath = prop("Drive").value<QDBusObjectPath>().path();
++    UDisks2::Device storageDevice(drivePath);
++    const UDisks2::StorageDrive storageDrive(&storageDevice);
++    Solid::StorageDrive::DriveType drive_type = storageDrive.driveType();
++
++    // Handle media in optical drives
++    if (drive_type == Solid::StorageDrive::CdromDrive)
++    {
++        const UDisks2::OpticalDisc disc(const_cast<Device*>(this));
++        switch (disc.discType())
++        {
++            case Solid::OpticalDisc::UnknownDiscType:
++            case Solid::OpticalDisc::CdRom:
++                description = QObject::tr("CD-ROM");
++                break;
++
++            case Solid::OpticalDisc::CdRecordable:
++                if (disc.isBlank())
++                    description = QObject::tr("Blank CD-R");
++                else
++                    description = QObject::tr("CD-R");
++                break;
++
++            case Solid::OpticalDisc::CdRewritable:
++                if (disc.isBlank())
++                    description = QObject::tr("Blank CD-RW");
++                else
++                    description = QObject::tr("CD-RW");
++                break;
++
++            case Solid::OpticalDisc::DvdRom:
++                description = QObject::tr("DVD-ROM");
++                break;
++
++            case Solid::OpticalDisc::DvdRam:
++                if (disc.isBlank())
++                    description = QObject::tr("Blank DVD-RAM");
++                else
++                    description = QObject::tr("DVD-RAM");
++                break;
++
++            case Solid::OpticalDisc::DvdRecordable:
++                if (disc.isBlank())
++                    description = QObject::tr("Blank DVD-R");
++                else
++                    description = QObject::tr("DVD-R");
++                break;
++
++            case Solid::OpticalDisc::DvdPlusRecordableDuallayer:
++                if (disc.isBlank())
++                    description = QObject::tr("Blank DVD+R Dual-Layer");
++                else
++                    description = QObject::tr("DVD+R Dual-Layer");
++                break;
++
++            case Solid::OpticalDisc::DvdRewritable:
++                if (disc.isBlank())
++                    description = QObject::tr("Blank DVD-RW");
++                else
++                    description = QObject::tr("DVD-RW");
++                break;
++
++            case Solid::OpticalDisc::DvdPlusRecordable:
++                if (disc.isBlank())
++                    description = QObject::tr("Blank DVD+R");
++                else
++                    description = QObject::tr("DVD+R");
++                break;
++
++            case Solid::OpticalDisc::DvdPlusRewritable:
++                if (disc.isBlank())
++                    description = QObject::tr("Blank DVD+RW");
++                else
++                    description = QObject::tr("DVD+RW");
++                break;
++
++            case Solid::OpticalDisc::DvdPlusRewritableDuallayer:
++                if (disc.isBlank())
++                    description = QObject::tr("Blank DVD+RW Dual-Layer");
++                else
++                    description = QObject::tr("DVD+RW Dual-Layer");
++                break;
++
++            case Solid::OpticalDisc::BluRayRom:
++                description = QObject::tr("BD-ROM");
++                break;
++
++            case Solid::OpticalDisc::BluRayRecordable:
++                if (disc.isBlank())
++                    description = QObject::tr("Blank BD-R");
++                else
++                    description = QObject::tr("BD-R");
++                break;
++
++            case Solid::OpticalDisc::BluRayRewritable:
++                if (disc.isBlank())
++                    description = QObject::tr("Blank BD-RE");
++                else
++                    description = QObject::tr("BD-RE");
++                break;
++
++            case Solid::OpticalDisc::HdDvdRom:
++                description = QObject::tr("HD DVD-ROM");
++                break;
++
++            case Solid::OpticalDisc::HdDvdRecordable:
++                if (disc.isBlank())
++                    description = QObject::tr("Blank HD DVD-R");
++                else
++                    description = QObject::tr("HD DVD-R");
++                break;
++
++            case Solid::OpticalDisc::HdDvdRewritable:
++                if (disc.isBlank())
++                    description = QObject::tr("Blank HD DVD-RW");
++                else
++                    description = QObject::tr("HD DVD-RW");
++                break;
++            }
++
++        // Special case for pure audio disc
++        if (disc.availableContent() == Solid::OpticalDisc::Audio)
++            description = QObject::tr("Audio CD");
++
++        return description;
++    }
++
++    const bool drive_is_removable = storageDrive.isRemovable();
++    const bool drive_is_hotpluggable = storageDrive.isHotpluggable();
++
++    QString size_str = formatByteSize(storageVolume.size());
++    if (isEncryptedContainer())
++    {
++        if (!size_str.isEmpty())
++            description = QObject::tr("%1 Encrypted Container", "%1 is the size").arg(size_str);
++        else
++            description = QObject::tr("Encrypted Container");
++    }
++    else if (drive_type == Solid::StorageDrive::HardDisk && !drive_is_removable)
++    {
++        if (!size_str.isEmpty())
++        {
++            if (drive_is_hotpluggable)
++                description = QObject::tr("%1 External Hard Drive", "%1 is the size").arg(size_str);
++            else
++                description = QObject::tr("%1 Hard Drive", "%1 is the size").arg(size_str);
++        }
++        else
++        {
++            if (drive_is_hotpluggable)
++                description = QObject::tr("External Hard Drive");
++            else
++                description = QObject::tr("Hard Drive");
++        }
++    }
++    else
++    {
++        if (drive_is_removable)
++            description = QObject::tr("%1 Removable Media", "%1 is the size").arg(size_str);
++        else
++            description = QObject::tr("%1 Media", "%1 is the size").arg(size_str);
++    }
++
++    return description;
++}
++
++QString Device::icon() const
++{
++    QString iconName = prop( "HintIconName" ).toString();
++
++    if ( !iconName.isEmpty() )
++    {
++        return iconName;
++    }
++    else if (isDrive()) {
++        const bool isRemovable = prop("Removable").toBool();
++        const QString conn = prop("ConnectionBus").toString();
++
++        if (isOpticalDrive())
++            return "drive-optical";
++        else if (isRemovable && !isOpticalDisc()) {
++            if (conn == "usb")
++                return "drive-removable-media-usb";
++            else
++                return "drive-removable-media";
++        }
++    }
++    else if (isBlock()) {
++        const QString drivePath = prop("Drive").value<QDBusObjectPath>().path();
++        Device drive(drivePath);
++
++        // handle media
++        const QString media = drive.prop("Media").toString();
++
++        if ( !media.isEmpty() )
++        {
++            if ( isOpticalDisc() )    // optical stuff
++            {
++                bool isWritable = drive.prop("OpticalBlank").toBool();
++
++                const UDisks2::OpticalDisc disc(const_cast<Device*>(this));
++                Solid::OpticalDisc::ContentTypes availContent = disc.availableContent();
++
++                if (availContent & Solid::OpticalDisc::VideoDvd) // Video DVD
++                    return "media-optical-dvd-video";
++                else if ((availContent & Solid::OpticalDisc::VideoCd) || (availContent & Solid::OpticalDisc::SuperVideoCd)) // Video CD
++                    return "media-optical-video";
++                else if ((availContent & Solid::OpticalDisc::Data) && (availContent & Solid::OpticalDisc::Audio)) // Mixed CD
++                    return "media-optical-mixed-cd";
++                else if (availContent & Solid::OpticalDisc::Audio) // Audio CD
++                    return "media-optical-audio";
++                else if (availContent & Solid::OpticalDisc::Data) // Data CD
++                    return "media-optical-data";
++                else if ( isWritable )
++                    return "media-optical-recordable";
++                else
++                {
++                    if ( media.startsWith( "optical_dvd" ) || media.startsWith( "optical_hddvd" ) ) // DVD
++                        return "media-optical-dvd";
++                    else if ( media.startsWith( "optical_bd" ) ) // BluRay
++                        return "media-optical-blu-ray";
++                }
++
++                // fallback for every other optical disc
++                return "media-optical";
++            }
++
++            if ( media == "flash_ms" ) // Flash & Co.
++                return "media-flash-memory-stick";
++            else if ( media == "flash_sd" || media == "flash_sdhc" || media == "flash_sdxc" || media == "flash_mmc" )
++                return "media-flash-sd-mmc";
++            else if ( media == "flash_sm" )
++                return "media-flash-smart-media";
++            else if ( media == "thumb" )
++                return "drive-removable-media-usb-pendrive";
++            else if ( media.startsWith( "flash" ) )
++                return "media-flash";
++            else if ( media == "floppy" ) // the good ol' floppy
++                return "media-floppy";
++        }
++
++        if (drive.prop("ConnectionBus").toString() == "sdio")  // hack for SD cards connected thru sdio bus
++            return "media-flash-sd-mmc";
++
++        return drive.icon();
++    }
++
++    return "drive-harddisk";    // general fallback
++}
++
++QString Device::product() const
++{
++    QString product = prop("Model").toString();
++
++    if (!isDrive()) {
++        QString label = prop("IdLabel").toString();
++        if (!label.isEmpty()) {
++            product = label;
++        }
++    }
++
++    return product;
++}
++
++QString Device::vendor() const
++{
++    return prop("Vendor").toString();
++}
++
++QString Device::udi() const
++{
++    return m_udi;
++}
++
++QString Device::parentUdi() const
++{
++    QString parent;
++
++    if (isEncryptedContainer())
++        parent = prop("CryptoBackingDevice").value<QDBusObjectPath>().path();
++    else if (propertyExists("Drive"))  // block
++        parent = prop("Drive").value<QDBusObjectPath>().path();
++    else if (propertyExists("Table"))  // partition
++        parent = prop("Table").value<QDBusObjectPath>().path();
++    else if (parent.isEmpty() || parent=="/") {
++        parent = UD2_UDI_DISKS_PREFIX;
++    }
++    return parent;
++}
++
++void Device::checkCache(const QString &key) const
++{
++    if (m_cache.isEmpty()) // recreate the cache
++        allProperties();
++
++    if (m_cache.contains(key))
++        return;
++
++    QVariant reply = m_device->property(key.toUtf8());
++
++    if (reply.isValid()) {
++        m_cache.insert(key, reply);
++    } else {
++        //qDebug() << "got invalid reply for cache:" << key;
++        //m_cache.insert(key, QVariant());
++    }
++}
++
++QString Device::introspect() const
++{
++    QDBusMessage call = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, m_udi,
++                                                       DBUS_INTERFACE_INTROSPECT, "Introspect");
++    QDBusPendingReply<QString> reply = QDBusConnection::systemBus().asyncCall(call);
++    reply.waitForFinished();
++
++    if (reply.isValid())
++        return reply.value();
++    else {
++        return QString();
++    }
++}
++
++QVariant Device::prop(const QString &key) const
++{
++    checkCache(key);
++    return m_cache.value(key);
++}
++
++bool Device::propertyExists(const QString &key) const
++{
++    checkCache(key);
++    return m_cache.contains(key);
++}
++
++QVariantMap Device::allProperties() const
++{
++    Q_FOREACH (const QString & iface, m_interfaces) {
++        if (iface.startsWith("org.freedesktop.DBus"))
++            continue;
++        QDBusMessage call = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, m_udi, DBUS_INTERFACE_PROPS, "GetAll");
++        call.setArguments(QList<QVariant>() << iface);
++        QDBusPendingReply<QVariantMap> reply = QDBusConnection::systemBus().asyncCall(call);
++        reply.waitForFinished();
++
++        if (reply.isValid())
++            m_cache.unite(reply.value());
++        else
++            qWarning() << "Error getting props:" << reply.error().name() << reply.error().message();
++        //qDebug() << "After iface" << iface << ", cache now contains" << m_cache.size() << "items";
++    }
++
++    return m_cache;
++}
++
++bool Device::hasInterface(const QString &name) const
++{
++    return m_interfaces.contains(name);
++}
++
++QStringList Device::interfaces() const
++{
++    return m_interfaces;
++}
++
++void Device::initInterfaces()
++{
++    m_interfaces.clear();
++    const QString xmlData = introspect();
++    QDomDocument dom;
++    dom.setContent(xmlData);
++    QDomNodeList ifaceNodeList = dom.elementsByTagName("interface");
++    for (int i = 0; i < ifaceNodeList.count(); i++) {
++        QDomElement ifaceElem = ifaceNodeList.item(i).toElement();
++        if (!ifaceElem.isNull())
++            m_interfaces.append(ifaceElem.attribute("name"));
++    }
++    //qDebug() << "Device" << m_udi << "has interfaces:" << m_interfaces;
++}
++
++void Device::slotPropertiesChanged(const QString &ifaceName, const QVariantMap &changedProps, const QStringList &invalidatedProps)
++{
++    //Q_UNUSED(ifaceName);
++
++    qDebug() << m_udi << "'s interface" << ifaceName << "changed props:";
++
++    QMap<QString, int> changeMap;
++
++    Q_FOREACH(const QString & key, invalidatedProps) {
++        m_cache.remove(key);
++        changeMap.insert(key, Solid::GenericInterface::PropertyRemoved);
++        qDebug() << "\t invalidated:" << key;
++    }
++
++    QMapIterator<QString, QVariant> i(changedProps);
++    while (i.hasNext()) {
++        i.next();
++        m_cache.insert(i.key(), i.value());  // replace the value
++        changeMap.insert(i.key(), Solid::GenericInterface::PropertyModified);
++        qDebug() << "\t modified:" << i.key() << ":" << m_cache.value(i.key());
++    }
++
++    Q_EMIT propertyChanged(changeMap);
++    Q_EMIT changed();
++}
++
++void Device::slotInterfacesAdded(const QDBusObjectPath &object_path, const QVariantMapMap &interfaces_and_properties)
++{
++    if (object_path.path() == m_udi) {
++        m_interfaces.append(interfaces_and_properties.keys());
++    }
++}
++
++void Device::slotInterfacesRemoved(const QDBusObjectPath &object_path, const QStringList &interfaces)
++{
++    if (object_path.path() == m_udi) {
++        Q_FOREACH(const QString & iface, interfaces) {
++            m_interfaces.removeAll(iface);
++        }
++    }
++}
++
++
++QString Device::errorToString(const QString & error) const
++{
++    if (error == UD2_ERROR_UNAUTHORIZED || error == UD2_ERROR_NOT_AUTHORIZED)
++        return QObject::tr("You are not authorized to perform this operation");
++    else if (error == UD2_ERROR_BUSY)
++        return QObject::tr("The device is currently busy");
++    else if (error == UD2_ERROR_FAILED)
++        return QObject::tr("The requested operation has failed");
++    else if (error == UD2_ERROR_CANCELED)
++        return QObject::tr("The requested operation has been canceled");
++    else if (error == UD2_ERROR_INVALID_OPTION)
++        return QObject::tr("An invalid or malformed option has been given");
++    else if (error == UD2_ERROR_MISSING_DRIVER)
++        return QObject::tr("The kernel driver for this filesystem type is not available");
++    else if (error == UD2_ERROR_ALREADY_MOUNTED)
++        return QObject::tr("The device is already mounted");
++    else if (error == UD2_ERROR_NOT_MOUNTED)
++        return QObject::tr("The device is not mounted");
++    else if (error == UD2_ERROR_MOUNTED_BY_OTHER_USER)
++        return QObject::tr("The device is mounted by another user");
++    else if (error == UD2_ERROR_ALREADY_UNMOUNTING)
++        return QObject::tr("The device is already unmounting");
++    else if (error == UD2_ERROR_TIMED_OUT)
++        return QObject::tr("The operation timed out");
++    else if (error == UD2_ERROR_WOULD_WAKEUP)
++        return QObject::tr("The operation would wake up a disk that is in a deep-sleep state");
++    else if (error == UD2_ERROR_ALREADY_CANCELLED)
++        return QObject::tr("The operation has already been canceled");
++    else
++        return QObject::tr("An unspecified error has occurred");
++}
++
++Solid::ErrorType Device::errorToSolidError(const QString & error) const
++{
++    if (error == UD2_ERROR_BUSY)
++        return Solid::DeviceBusy;
++    else if (error == UD2_ERROR_FAILED)
++        return Solid::OperationFailed;
++    else if (error == UD2_ERROR_CANCELED)
++        return Solid::UserCanceled;
++    else if (error == UD2_ERROR_INVALID_OPTION)
++        return Solid::InvalidOption;
++    else if (error == UD2_ERROR_MISSING_DRIVER)
++        return Solid::MissingDriver;
++    else
++        return Solid::UnauthorizedOperation;
++}
++
++bool Device::isBlock() const
++{
++    return hasInterface(UD2_DBUS_INTERFACE_BLOCK);
++}
++
++bool Device::isPartition() const
++{
++    return hasInterface(UD2_DBUS_INTERFACE_PARTITION);
++}
++
++bool Device::isPartitionTable() const
++{
++    return hasInterface(UD2_DBUS_INTERFACE_PARTITIONTABLE);
++}
++
++bool Device::isStorageVolume() const
++{
++    return isPartition() || isPartitionTable() || isStorageAccess() || isOpticalDisc();
++}
++
++bool Device::isStorageAccess() const
++{
++    return hasInterface(UD2_DBUS_INTERFACE_FILESYSTEM) || isEncryptedContainer();
++}
++
++bool Device::isDrive() const
++{
++    return hasInterface(UD2_DBUS_INTERFACE_DRIVE);
++}
++
++bool Device::isOpticalDrive() const
++{
++    return isDrive() && !prop("MediaCompatibility").toStringList().filter("optical_").isEmpty();
++}
++
++bool Device::isOpticalDisc() const
++{
++    QString drivePath = prop("Drive").value<QDBusObjectPath>().path();
++    if (drivePath.isEmpty() || drivePath == "/")
++        return false;
++
++    Device drive(drivePath);
++    return drive.prop("Optical").toBool();
++}
++
++bool Device::mightBeOpticalDisc() const
++{
++    QString drivePath = prop("Drive").value<QDBusObjectPath>().path();
++    if (drivePath.isEmpty() || drivePath == "/")
++        return false;
++
++    Device drive(drivePath);
++    return drive.isOpticalDrive();
++}
++
++bool Device::isMounted() const
++{
++    return propertyExists("MountPoints") && !qdbus_cast<QByteArrayList>(prop("MountPoints")).isEmpty();
++}
++
++bool Device::isEncryptedContainer() const
++{
++    return hasInterface(UD2_DBUS_INTERFACE_ENCRYPTED);
++}
++
++bool Device::isEncryptedCleartext() const
++{
++    const QString holderDevice = prop("CryptoBackingDevice").toString();
++    if (holderDevice.isEmpty() || holderDevice == "/")
++        return false;
++    else
++        return true;
++}
++
++bool Device::isSwap() const
++{
++    return hasInterface(UD2_DBUS_INTERFACE_SWAP);
++}
+diff --git a/tier1/solid/src/solid/backends/udisks2/udisksdevice.h b/tier1/solid/src/solid/backends/udisks2/udisksdevice.h
+new file mode 100644
+index 0000000..6f8056b
+--- /dev/null
++++ b/tier1/solid/src/solid/backends/udisks2/udisksdevice.h
+@@ -0,0 +1,110 @@
++/*
++    Copyright 2010 Michael Zanetti <mzanetti at kde.org>
++    Copyright 2010-2012 Lukáš Tinkl <ltinkl at redhat.com>
++
++    This library is free software; you can redistribute it and/or
++    modify it under the terms of the GNU Lesser General Public
++    License as published by the Free Software Foundation; either
++    version 2.1 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 6 of version 3 of the license.
++
++    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
++    Lesser General Public License for more details.
++
++    You should have received a copy of the GNU Lesser General Public
++    License along with this library. If not, see <http://www.gnu.org/licenses/>.
++*/
++
++#ifndef UDISKS2DEVICE_H
++#define UDISKS2DEVICE_H
++
++#include "udisks2.h"
++
++#include <ifaces/device.h>
++#include <solid/deviceinterface.h>
++#include <solid/solidnamespace.h>
++
++#include <QtDBus/QDBusInterface>
++#include <QtDBus/QDBusObjectPath>
++#include <QtCore/QStringList>
++
++namespace Solid
++{
++namespace Backends
++{
++namespace UDisks2
++{
++
++class Device: public Solid::Ifaces::Device
++{
++    Q_OBJECT
++public:
++    Device(const QString &udi);
++    virtual ~Device();
++
++    virtual QObject* createDeviceInterface(const Solid::DeviceInterface::Type& type);
++    virtual bool queryDeviceInterface(const Solid::DeviceInterface::Type& type) const;
++    virtual QString description() const;
++    virtual QStringList emblems() const;
++    virtual QString icon() const;
++    virtual QString product() const;
++    virtual QString vendor() const;
++    virtual QString udi() const;
++    virtual QString parentUdi() const;
++
++    QVariant prop(const QString &key) const;
++    bool propertyExists(const QString &key) const;
++    QVariantMap allProperties() const;
++
++    bool hasInterface(const QString & name) const;
++    QStringList interfaces() const;
++
++    QString errorToString(const QString & error) const;
++    Solid::ErrorType errorToSolidError(const QString & error) const;
++
++    bool isBlock() const;
++    bool isPartition() const;
++    bool isPartitionTable() const;
++    bool isStorageVolume() const;
++    bool isStorageAccess() const;
++    bool isDrive() const;
++    bool isOpticalDrive() const;
++    bool isOpticalDisc() const;
++    bool mightBeOpticalDisc() const;
++    bool isMounted() const;
++    bool isEncryptedContainer() const;
++    bool isEncryptedCleartext() const;
++    bool isSwap() const;
++
++Q_SIGNALS:
++    void changed();
++    void propertyChanged(const QMap<QString,int> &changes);
++
++private Q_SLOTS:
++    void slotPropertiesChanged(const QString & ifaceName, const QVariantMap & changedProps, const QStringList & invalidatedProps);
++    void slotInterfacesAdded(const QDBusObjectPath &object_path, const QVariantMapMap &interfaces_and_properties);
++    void slotInterfacesRemoved(const QDBusObjectPath &object_path, const QStringList &interfaces);
++
++private:
++    QString storageDescription() const;
++    QString volumeDescription() const;
++    mutable QDBusInterface *m_device;
++    QString m_udi;
++    mutable QVariantMap m_cache;
++
++    void initInterfaces();
++    QStringList m_interfaces;
++
++    void checkCache(const QString &key) const;
++    QString introspect() const;
++};
++
++}
++}
++}
++
++#endif // UDISKS2DEVICE_H
+diff --git a/tier1/solid/src/solid/backends/udisks2/udisksdeviceinterface.cpp b/tier1/solid/src/solid/backends/udisks2/udisksdeviceinterface.cpp
+new file mode 100644
+index 0000000..9fa60e5
+--- /dev/null
++++ b/tier1/solid/src/solid/backends/udisks2/udisksdeviceinterface.cpp
+@@ -0,0 +1,33 @@
++/*
++    Copyright 2010 Michael Zanetti <mzanetti at kde.org>
++
++    This library is free software; you can redistribute it and/or
++    modify it under the terms of the GNU Lesser General Public
++    License as published by the Free Software Foundation; either
++    version 2.1 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 6 of version 3 of the license.
++
++    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
++    Lesser General Public License for more details.
++
++    You should have received a copy of the GNU Lesser General Public
++    License along with this library. If not, see <http://www.gnu.org/licenses/>.
++*/
++
++#include "udisksdeviceinterface.h"
++
++using namespace Solid::Backends::UDisks2;
++
++DeviceInterface::DeviceInterface(Device *device)
++    : QObject(device), m_device(device)
++{
++
++}
++
++DeviceInterface::~DeviceInterface()
++{
++}
+diff --git a/tier1/solid/src/solid/backends/udisks2/udisksdeviceinterface.h b/tier1/solid/src/solid/backends/udisks2/udisksdeviceinterface.h
+new file mode 100644
+index 0000000..43a1b6f
+--- /dev/null
++++ b/tier1/solid/src/solid/backends/udisks2/udisksdeviceinterface.h
+@@ -0,0 +1,148 @@
++/*
++    Copyright 2010 Michael Zanetti <mzanetti at kde.org>
++
++    This library is free software; you can redistribute it and/or
++    modify it under the terms of the GNU Lesser General Public
++    License as published by the Free Software Foundation; either
++    version 2.1 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 6 of version 3 of the license.
++
++    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
++    Lesser General Public License for more details.
++
++    You should have received a copy of the GNU Lesser General Public
++    License along with this library. If not, see <http://www.gnu.org/licenses/>.
++*/
++
++#ifndef UDISKS2DEVICEINTERFACE_H
++#define UDISKS2DEVICEINTERFACE_H
++
++#include <ifaces/deviceinterface.h>
++#include "udisksdevice.h"
++
++#include <QtCore/QObject>
++#include <QtCore/QStringList>
++
++namespace Solid
++{
++namespace Backends
++{
++namespace UDisks2
++{
++
++class DeviceInterface : public QObject, virtual public Solid::Ifaces::DeviceInterface
++{
++    Q_OBJECT
++    Q_INTERFACES(Solid::Ifaces::DeviceInterface)
++public:
++    DeviceInterface(Device *device);
++    virtual ~DeviceInterface();
++
++protected:
++    Device *m_device;
++
++public:
++    inline static QStringList toStringList(Solid::DeviceInterface::Type type)
++    {
++        QStringList list;
++
++        switch(type)
++        {
++        case Solid::DeviceInterface::GenericInterface:
++            list << "generic";
++            break;
++        case Solid::DeviceInterface::Processor:
++            // Doesn't exist with UDisks
++            break;
++        case Solid::DeviceInterface::Block:
++            list << "block";
++            break;
++        case Solid::DeviceInterface::StorageAccess:
++            list << "volume";
++            break;
++        case Solid::DeviceInterface::StorageDrive:
++            list << "storage";
++            break;
++        case Solid::DeviceInterface::OpticalDrive:
++            list << "storage.cdrom";
++            break;
++        case Solid::DeviceInterface::StorageVolume:
++            list << "volume";
++            break;
++        case Solid::DeviceInterface::OpticalDisc:
++            list << "volume.disc";
++            break;
++        case Solid::DeviceInterface::Camera:
++            // Doesn't exist with UDisks
++            break;
++        case Solid::DeviceInterface::PortableMediaPlayer:
++            // Doesn't exist with UDisks
++            break;
++        case Solid::DeviceInterface::NetworkInterface:
++            // Doesn't exist with UDisks
++            break;
++        case Solid::DeviceInterface::AcAdapter:
++            // Doesn't exist with UDisks
++            break;
++        case Solid::DeviceInterface::Battery:
++            // Doesn't exist with UDisks
++            break;
++        case Solid::DeviceInterface::Button:
++            // Doesn't exist with UDisks
++            break;
++        case Solid::DeviceInterface::AudioInterface:
++            // Doesn't exist with UDisks
++            break;
++        case Solid::DeviceInterface::DvbInterface:
++            // Doesn't exist with UDisks
++            break;
++        case Solid::DeviceInterface::Video:
++            // Doesn't exist with UDisks
++            break;
++        case Solid::DeviceInterface::SerialInterface:
++            // Doesn't exist with UDisks
++            break;
++        case Solid::DeviceInterface::InternetGateway:
++            break;
++        case Solid::DeviceInterface::SmartCardReader:
++            // Doesn't exist with UDisks
++        case Solid::DeviceInterface::NetworkShare:
++            // Doesn't exist with UDisks
++            break;
++        case Solid::DeviceInterface::Unknown:
++            break;
++        case Solid::DeviceInterface::Last:
++            break;
++        }
++
++        return list;
++    }
++
++    inline static Solid::DeviceInterface::Type fromString(const QString &capability)
++    {
++        if (capability == "generic")
++            return Solid::DeviceInterface::GenericInterface;
++        else if (capability == "block")
++            return Solid::DeviceInterface::Block;
++        else if (capability == "storage")
++            return Solid::DeviceInterface::StorageDrive;
++        else if (capability == "storage.cdrom")
++            return Solid::DeviceInterface::OpticalDrive;
++        else if (capability == "volume")
++            return Solid::DeviceInterface::StorageVolume;
++        else if (capability == "volume.disc")
++            return Solid::DeviceInterface::OpticalDisc;
++        else
++            return Solid::DeviceInterface::Unknown;
++    }
++};
++
++}
++}
++}
++
++#endif // UDISKS2DEVICEINTERFACE_H
+diff --git a/tier1/solid/src/solid/backends/udisks2/udisksgenericinterface.cpp b/tier1/solid/src/solid/backends/udisks2/udisksgenericinterface.cpp
+new file mode 100644
+index 0000000..2d8cea2
+--- /dev/null
++++ b/tier1/solid/src/solid/backends/udisks2/udisksgenericinterface.cpp
+@@ -0,0 +1,53 @@
++/*
++    Copyright 2009 Pino Toscano <pino at kde.org>
++    Copyright 2012 Lukáš Tinkl <ltinkl at redhat.com>
++
++    This library is free software; you can redistribute it and/or
++    modify it under the terms of the GNU Lesser General Public
++    License as published by the Free Software Foundation; either
++    version 2.1 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 6 of version 3 of the license.
++
++    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
++    Lesser General Public License for more details.
++
++    You should have received a copy of the GNU Lesser General Public
++    License along with this library. If not, see <http://www.gnu.org/licenses/>.
++*/
++
++#include "udisksgenericinterface.h"
++
++#include "udisksdevice.h"
++
++using namespace Solid::Backends::UDisks2;
++
++GenericInterface::GenericInterface(Device *device)
++    : DeviceInterface(device)
++{
++    connect(device, SIGNAL(propertyChanged(QMap<QString,int>)),
++            this, SIGNAL(propertyChanged(QMap<QString,int>)));
++}
++
++GenericInterface::~GenericInterface()
++{
++}
++
++QVariant GenericInterface::property(const QString &key) const
++{
++    return m_device->prop(key);
++}
++
++QVariantMap GenericInterface::allProperties() const
++{
++    return m_device->allProperties();
++}
++
++bool GenericInterface::propertyExists(const QString &key) const
++{
++    return m_device->propertyExists(key);
++}
++
+diff --git a/tier1/solid/src/solid/backends/udisks2/udisksgenericinterface.h b/tier1/solid/src/solid/backends/udisks2/udisksgenericinterface.h
+new file mode 100644
+index 0000000..d225f32
+--- /dev/null
++++ b/tier1/solid/src/solid/backends/udisks2/udisksgenericinterface.h
+@@ -0,0 +1,57 @@
++/*
++    Copyright 2009 Pino Toscano <pino at kde.org>
++
++    This library is free software; you can redistribute it and/or
++    modify it under the terms of the GNU Lesser General Public
++    License as published by the Free Software Foundation; either
++    version 2.1 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 6 of version 3 of the license.
++
++    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
++    Lesser General Public License for more details.
++
++    You should have received a copy of the GNU Lesser General Public
++    License along with this library. If not, see <http://www.gnu.org/licenses/>.
++*/
++
++#ifndef SOLID_BACKENDS_UDISKS2_GENERICINTERFACE_H
++#define SOLID_BACKENDS_UDISKS2_GENERICINTERFACE_H
++
++#include <solid/ifaces/genericinterface.h>
++#include <solid/genericinterface.h>
++#include "udisksdeviceinterface.h"
++
++namespace Solid
++{
++namespace Backends
++{
++namespace UDisks2
++{
++class Device;
++
++class GenericInterface : public DeviceInterface, virtual public Solid::Ifaces::GenericInterface
++{
++    Q_OBJECT
++    Q_INTERFACES(Solid::Ifaces::GenericInterface)
++
++public:
++    GenericInterface(Device *device);
++    virtual ~GenericInterface();
++
++    virtual QVariant property(const QString &key) const;
++    virtual QVariantMap allProperties() const;
++    virtual bool propertyExists(const QString &key) const;
++
++Q_SIGNALS:
++    void propertyChanged(const QMap<QString, int> &changes);
++    void conditionRaised(const QString &condition, const QString &reason);
++};
++}
++}
++}
++
++#endif // SOLID_BACKENDS_UDISKS2_GENERICINTERFACE_H
+diff --git a/tier1/solid/src/solid/backends/udisks2/udisksmanager.cpp b/tier1/solid/src/solid/backends/udisks2/udisksmanager.cpp
+new file mode 100644
+index 0000000..2e6f8c6
+--- /dev/null
++++ b/tier1/solid/src/solid/backends/udisks2/udisksmanager.cpp
+@@ -0,0 +1,294 @@
++/*
++    Copyright 2012 Lukáš Tinkl <ltinkl at redhat.com>
++
++    This library is free software; you can redistribute it and/or
++    modify it under the terms of the GNU Lesser General Public
++    License as published by the Free Software Foundation; either
++    version 2.1 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 6 of version 3 of the license.
++
++    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
++    Lesser General Public License for more details.
++
++    You should have received a copy of the GNU Lesser General Public
++    License along with this library. If not, see <http://www.gnu.org/licenses/>.
++*/
++
++#include "udisksmanager.h"
++
++#include <QtCore/QDebug>
++#include <QtDBus>
++
++#include "../shared/rootdevice.h"
++
++using namespace Solid::Backends::UDisks2;
++using namespace Solid::Backends::Shared;
++
++Manager::Manager(QObject *parent)
++    : Solid::Ifaces::DeviceManager(parent),
++      m_manager(UD2_DBUS_SERVICE,
++                UD2_DBUS_PATH,
++                QDBusConnection::systemBus())
++{
++    m_supportedInterfaces
++            << Solid::DeviceInterface::GenericInterface
++            << Solid::DeviceInterface::Block
++            << Solid::DeviceInterface::StorageAccess
++            << Solid::DeviceInterface::StorageDrive
++            << Solid::DeviceInterface::OpticalDrive
++            << Solid::DeviceInterface::OpticalDisc
++            << Solid::DeviceInterface::StorageVolume;
++
++    qDBusRegisterMetaType<QList<QDBusObjectPath> >();
++    qDBusRegisterMetaType<QVariantMap>();
++    qDBusRegisterMetaType<QVariantMapMap>();
++    qDBusRegisterMetaType<QByteArrayList>();
++    qDBusRegisterMetaType<DBUSManagerStruct>();
++
++    bool serviceFound = m_manager.isValid();
++    if (!serviceFound) {
++        // find out whether it will be activated automatically
++        QDBusMessage message = QDBusMessage::createMethodCall("org.freedesktop.DBus",
++                                                              "/org/freedesktop/DBus",
++                                                              "org.freedesktop.DBus",
++                                                              "ListActivatableNames");
++
++        QDBusReply<QStringList> reply = QDBusConnection::systemBus().call(message);
++        if (reply.isValid() && reply.value().contains(UD2_DBUS_SERVICE)) {
++            QDBusConnection::systemBus().interface()->startService(UD2_DBUS_SERVICE);
++            serviceFound = true;
++        }
++    }
++
++    if (serviceFound) {
++        connect(&m_manager, SIGNAL(InterfacesAdded(QDBusObjectPath, QVariantMapMap)),
++                this, SLOT(slotInterfacesAdded(QDBusObjectPath,QVariantMapMap)));
++        connect(&m_manager, SIGNAL(InterfacesRemoved(QDBusObjectPath,QStringList)),
++                this, SLOT(slotInterfacesRemoved(QDBusObjectPath,QStringList)));
++    }
++}
++
++Manager::~Manager()
++{
++}
++
++QObject* Manager::createDevice(const QString& udi)
++{
++    if (udi==udiPrefix()) {
++        RootDevice *root = new RootDevice(udi);
++
++        root->setProduct(tr("Storage"));
++        root->setDescription(tr("Storage devices"));
++        root->setIcon("server-database"); // Obviously wasn't meant for that, but maps nicely in oxygen icon set :-p
++
++        return root;
++    } else if (deviceCache().contains(udi)) {
++        return new Device(udi);
++    } else {
++        return 0;
++    }
++}
++
++QStringList Manager::devicesFromQuery(const QString& parentUdi, Solid::DeviceInterface::Type type)
++{
++    QStringList result;
++
++    if (!parentUdi.isEmpty())
++    {
++        Q_FOREACH (const QString &udi, deviceCache())
++        {
++            Device device(udi);
++            if (device.queryDeviceInterface(type) && device.parentUdi() == parentUdi)
++                result << udi;
++        }
++
++        return result;
++    }
++    else if (type != Solid::DeviceInterface::Unknown)
++    {
++        Q_FOREACH (const QString &udi, deviceCache())
++        {
++            Device device(udi);
++            if (device.queryDeviceInterface(type))
++                result << udi;
++        }
++
++        return result;
++    }
++
++    return deviceCache();
++}
++
++QStringList Manager::allDevices()
++{
++    m_deviceCache.clear();
++
++    QDBusPendingReply<DBUSManagerStruct> reply = m_manager.GetManagedObjects();
++    reply.waitForFinished();
++    if (!reply.isError()) {  // enum devices
++        m_deviceCache << udiPrefix();
++
++        Q_FOREACH(const QDBusObjectPath &path, reply.value().keys()) {
++            const QString udi = path.path();
++            qDebug() << "Adding device" << udi;
++
++            if (udi == UD2_DBUS_PATH_MANAGER || udi == UD2_UDI_DISKS_PREFIX || udi.startsWith(UD2_DBUS_PATH_JOBS))
++                continue;
++
++            Device device(udi);
++            if (device.mightBeOpticalDisc()) {
++                QDBusConnection::systemBus().connect(UD2_DBUS_SERVICE, udi, DBUS_INTERFACE_PROPS, "PropertiesChanged", this,
++                                                     SLOT(slotMediaChanged(QDBusMessage)));
++                if (!device.isOpticalDisc())  // skip empty CD disc
++                    continue;
++            }
++
++            m_deviceCache.append(udi);
++        }
++    }
++    else  // show error
++    {
++        qWarning() << "Failed enumerating UDisks2 objects:" << reply.error().name() << "\n" << reply.error().message();
++    }
++
++    return m_deviceCache;
++}
++
++
++QSet< Solid::DeviceInterface::Type > Manager::supportedInterfaces() const
++{
++    return m_supportedInterfaces;
++}
++
++QString Manager::udiPrefix() const
++{
++    return UD2_UDI_DISKS_PREFIX;
++}
++
++#if 0
++void Manager::slotDeviceAdded(const QDBusObjectPath &opath)
++{
++    const QString udi = opath.path();
++
++    if (!m_deviceCache.contains(udi)) {
++        m_deviceCache.append(udi);
++    }
++
++    Device device(udi);
++    if (device.queryDeviceInterface(Solid::DeviceInterface::StorageDrive)
++            && !device.prop("DeviceIsMediaAvailable").toBool()
++            && !m_dirtyDevices.contains(udi))
++        m_dirtyDevices.append(udi);
++
++    Q_EMIT deviceAdded(udi);
++    slotDeviceChanged(opath);  // case: hotswap event (optical drive with media inside)
++}
++
++void Manager::slotDeviceRemoved(const QDBusObjectPath &opath)
++{
++    const QString udi = opath.path();
++
++    // case: hotswap event (optical drive with media inside)
++    if (m_knownDrivesWithMedia.contains(udi)) {
++        m_knownDrivesWithMedia.removeAll(udi);
++        m_deviceCache.removeAll(udi + ":media");
++        Q_EMIT deviceRemoved(udi + ":media");
++    }
++
++    if (m_dirtyDevices.contains(udi))
++        m_dirtyDevices.removeAll(udi);
++
++    Q_EMIT deviceRemoved(udi);
++    m_deviceCache.removeAll(udi);
++}
++
++void Manager::slotDeviceChanged(const QDBusObjectPath &opath)
++{
++    const QString udi = opath.path();
++    Device device(udi);
++
++    if (device.queryDeviceInterface(Solid::DeviceInterface::OpticalDrive))
++    {
++        if (!m_knownDrivesWithMedia.contains(udi) && device.prop("DeviceIsOpticalDisc").toBool())
++        {
++            m_knownDrivesWithMedia.append(udi);
++            if (!m_deviceCache.isEmpty()) {
++                m_deviceCache.append(udi + ":media");
++            }
++            Q_EMIT deviceAdded(udi + ":media");
++        }
++
++        if (m_knownDrivesWithMedia.contains(udi) && !device.prop("DeviceIsOpticalDisc").toBool())
++        {
++            m_knownDrivesWithMedia.removeAll(udi);
++            m_deviceCache.removeAll(udi + ":media");
++            Q_EMIT deviceRemoved(udi + ":media");
++        }
++    }
++
++    if (device.queryDeviceInterface(Solid::DeviceInterface::StorageDrive) && device.prop("MediaAvailable").toBool() && m_dirtyDevices.contains(udi))
++    {
++        qDebug() << "dirty device added:" << udi;
++        Q_EMIT deviceAdded(udi);
++        m_dirtyDevices.removeAll(udi);
++    }
++}
++#endif
++
++
++void Manager::slotInterfacesAdded(const QDBusObjectPath &object_path, const QVariantMapMap &interfaces_and_properties)
++{
++    const QString udi = object_path.path();
++
++    qDebug() << udi << "has new interfaces:" << interfaces_and_properties.keys();
++
++    // new device, we don't know it yet
++    if (!m_deviceCache.contains(udi)) {
++        m_deviceCache.append(udi);
++        Q_EMIT deviceAdded(udi);
++    }
++}
++
++void Manager::slotInterfacesRemoved(const QDBusObjectPath &object_path, const QStringList &interfaces)
++{
++    const QString udi = object_path.path();
++
++    qDebug() << udi << "lost interfaces:" << interfaces;
++
++    Device device(udi);
++
++    if (!udi.isEmpty() && (interfaces.isEmpty() || device.interfaces().isEmpty() || device.interfaces().contains(UD2_DBUS_INTERFACE_FILESYSTEM))) {
++        Q_EMIT deviceRemoved(udi);
++        m_deviceCache.removeAll(udi);
++    }
++}
++
++void Manager::slotMediaChanged(const QDBusMessage & msg)
++{
++    const QVariantMap properties = qdbus_cast<QVariantMap>(msg.arguments().at(1));
++    const QString udi = msg.path();
++    qulonglong size = properties.value("Size").toULongLong();
++    qDebug() << "MEDIA CHANGED in" << udi << "; size is:" << size;
++
++    if (!m_deviceCache.contains(udi) && size > 0) { // we don't know the optdisc, got inserted
++        m_deviceCache.append(udi);
++        Q_EMIT deviceAdded(udi);
++    }
++
++    if (m_deviceCache.contains(udi) && size == 0) {  // we know the optdisc, got removed
++        Q_EMIT deviceRemoved(udi);
++        m_deviceCache.removeAll(udi);
++    }
++}
++
++const QStringList & Manager::deviceCache()
++{
++    if (m_deviceCache.isEmpty())
++        allDevices();
++
++    return m_deviceCache;
++}
+diff --git a/tier1/solid/src/solid/backends/udisks2/udisksmanager.h b/tier1/solid/src/solid/backends/udisks2/udisksmanager.h
+new file mode 100644
+index 0000000..7cf0a72
+--- /dev/null
++++ b/tier1/solid/src/solid/backends/udisks2/udisksmanager.h
+@@ -0,0 +1,69 @@
++/*
++    Copyright 2010 Michael Zanetti <mzanetti at kde.org>
++    Copyright 2010-2012 Lukáš Tinkl <ltinkl at redhat.com>
++
++    This library is free software; you can redistribute it and/or
++    modify it under the terms of the GNU Lesser General Public
++    License as published by the Free Software Foundation; either
++    version 2.1 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 6 of version 3 of the license.
++
++    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
++    Lesser General Public License for more details.
++
++    You should have received a copy of the GNU Lesser General Public
++    License along with this library. If not, see <http://www.gnu.org/licenses/>.
++*/
++
++#ifndef UDISKS2MANAGER_H
++#define UDISKS2MANAGER_H
++
++#include "udisks2.h"
++#include "udisksdevice.h"
++#include "dbus/manager.h"
++
++#include "solid/ifaces/devicemanager.h"
++
++#include <QtDBus/QDBusInterface>
++#include <QtCore/QSet>
++
++namespace Solid
++{
++namespace Backends
++{
++namespace UDisks2
++{
++
++class Manager: public Solid::Ifaces::DeviceManager
++{
++    Q_OBJECT
++
++public:
++    Manager(QObject *parent);
++    virtual QObject* createDevice(const QString& udi);
++    virtual QStringList devicesFromQuery(const QString& parentUdi, Solid::DeviceInterface::Type type);
++    virtual QStringList allDevices();
++    virtual QSet< Solid::DeviceInterface::Type > supportedInterfaces() const;
++    virtual QString udiPrefix() const;
++    virtual ~Manager();
++
++private Q_SLOTS:
++    void slotInterfacesAdded(const QDBusObjectPath &object_path, const QVariantMapMap &interfaces_and_properties);
++    void slotInterfacesRemoved(const QDBusObjectPath &object_path, const QStringList &interfaces);
++    void slotMediaChanged(const QDBusMessage &msg);
++
++private:
++    const QStringList &deviceCache();
++    QSet<Solid::DeviceInterface::Type> m_supportedInterfaces;
++    org::freedesktop::DBus::ObjectManager m_manager;
++    QStringList m_deviceCache;
++};
++
++}
++}
++}
++#endif // UDISKS2MANAGER_H
+diff --git a/tier1/solid/src/solid/backends/udisks2/udisksopticaldisc.cpp b/tier1/solid/src/solid/backends/udisks2/udisksopticaldisc.cpp
+new file mode 100644
+index 0000000..bceb277
+--- /dev/null
++++ b/tier1/solid/src/solid/backends/udisks2/udisksopticaldisc.cpp
+@@ -0,0 +1,274 @@
++/*
++    Copyright 2010 Michael Zanetti <mzanetti at kde.org>
++    Copyright 2010 - 2012 Lukáš Tinkl <ltinkl at redhat.com>
++
++    This library is free software; you can redistribute it and/or
++    modify it under the terms of the GNU Lesser General Public
++    License as published by the Free Software Foundation; either
++    version 2.1 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 6 of version 3 of the license.
++
++    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
++    Lesser General Public License for more details.
++
++    You should have received a copy of the GNU Lesser General Public
++    License along with this library. If not, see <http://www.gnu.org/licenses/>.
++*/
++
++#include <sys/types.h>
++#include <unistd.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++
++#include <QtCore/QFile>
++#include <QtDBus/QDBusConnection>
++
++#include "../shared/udevqtclient.h"
++
++#include "udisks2.h"
++#include "udisksopticaldisc.h"
++
++// inspired by http://cgit.freedesktop.org/hal/tree/hald/linux/probing/probe-volume.c
++static Solid::OpticalDisc::ContentType advancedDiscDetect(const QByteArray & device_file)
++{
++    /* the discs block size */
++    unsigned short bs;
++    /* the path table size */
++    unsigned short ts;
++    /* the path table location (in blocks) */
++    unsigned int tl;
++    /* length of the directory name in current path table entry */
++    unsigned char len_di = 0;
++    /* the number of the parent directory's path table entry */
++    unsigned int parent = 0;
++    /* filename for the current path table entry */
++    char dirname[256];
++    /* our position into the path table */
++    int pos = 0;
++    /* the path table record we're on */
++    int curr_record = 1;
++
++    Solid::OpticalDisc::ContentType result = Solid::OpticalDisc::NoContent;
++
++    int fd = open(device_file.constData(), O_RDONLY);
++
++    /* read the block size */
++    lseek (fd, 0x8080, SEEK_CUR);
++    if (read (fd, &bs, 2) != 2)
++    {
++        qDebug("Advanced probing on %s failed while reading block size", qPrintable(device_file));
++        goto out;
++    }
++
++    /* read in size of path table */
++    lseek (fd, 2, SEEK_CUR);
++    if (read (fd, &ts, 2) != 2)
++    {
++        qDebug("Advanced probing on %s failed while reading path table size", qPrintable(device_file));
++        goto out;
++    }
++
++    /* read in which block path table is in */
++    lseek (fd, 6, SEEK_CUR);
++    if (read (fd, &tl, 4) != 4)
++    {
++        qDebug("Advanced probing on %s failed while reading path table block", qPrintable(device_file));
++        goto out;
++    }
++
++    /* seek to the path table */
++    lseek (fd, bs * tl, SEEK_SET);
++
++    /* loop through the path table entries */
++    while (pos < ts)
++    {
++        /* get the length of the filename of the current entry */
++        if (read (fd, &len_di, 1) != 1)
++        {
++            qDebug("Advanced probing on %s failed, cannot read more entries", qPrintable(device_file));
++            break;
++        }
++
++        /* get the record number of this entry's parent
++           i'm pretty sure that the 1st entry is always the top directory */
++        lseek (fd, 5, SEEK_CUR);
++        if (read (fd, &parent, 2) != 2)
++        {
++            qDebug("Advanced probing on %s failed, couldn't read parent entry", qPrintable(device_file));
++            break;
++        }
++
++        /* read the name */
++        if (read (fd, dirname, len_di) != len_di)
++        {
++            qDebug("Advanced probing on %s failed, couldn't read the entry name", qPrintable(device_file));
++            break;
++        }
++        dirname[len_di] = 0;
++
++        /* if we found a folder that has the root as a parent, and the directory name matches
++           one of the special directories then set the properties accordingly */
++        if (parent == 1)
++        {
++            if (!strcasecmp (dirname, "VIDEO_TS"))
++            {
++                qDebug("Disc in %s is a Video DVD", qPrintable(device_file));
++                result = Solid::OpticalDisc::VideoDvd;
++                break;
++            }
++            else if (!strcasecmp (dirname, "BDMV"))
++            {
++                qDebug("Disc in %s is a Blu-ray video disc", qPrintable(device_file));
++                result = Solid::OpticalDisc::VideoBluRay;
++                break;
++            }
++            else if (!strcasecmp (dirname, "VCD"))
++            {
++                qDebug("Disc in %s is a Video CD", qPrintable(device_file));
++                result = Solid::OpticalDisc::VideoCd;
++                break;
++            }
++            else if (!strcasecmp (dirname, "SVCD"))
++            {
++                qDebug("Disc in %s is a Super Video CD", qPrintable(device_file));
++                result = Solid::OpticalDisc::SuperVideoCd;
++                break;
++            }
++        }
++
++        /* all path table entries are padded to be even,
++           so if this is an odd-length table, seek a byte to fix it */
++        if (len_di%2 == 1)
++        {
++            lseek (fd, 1, SEEK_CUR);
++            pos++;
++        }
++
++        /* update our position */
++        pos += 8 + len_di;
++        curr_record++;
++    }
++
++    close(fd);
++    return result;
++
++out:
++    /* go back to the start of the file */
++    lseek (fd, 0, SEEK_SET);
++    close(fd);
++    return result;
++}
++
++using namespace Solid::Backends::UDisks2;
++
++OpticalDisc::OpticalDisc(Device *device)
++    : StorageVolume(device), m_needsReprobe(true), m_cachedContent(Solid::OpticalDisc::NoContent)
++{
++    UdevQt::Client client(this);
++    m_udevDevice = client.deviceByDeviceFile(QFile::decodeName(m_device->prop("Device").toByteArray()));
++
++    m_drive = new Device(m_device->prop("Drive").value<QDBusObjectPath>().path());
++    QDBusConnection::systemBus().connect(UD2_DBUS_SERVICE, m_drive->udi(), DBUS_INTERFACE_PROPS, "PropertiesChanged", this,
++                                         SLOT(slotDrivePropertiesChanged(QString,QVariantMap,QStringList)));
++}
++
++OpticalDisc::~OpticalDisc()
++{
++    delete m_drive;
++}
++
++qulonglong OpticalDisc::capacity() const
++{
++    return m_device->prop("Size").toULongLong();
++}
++
++bool OpticalDisc::isRewritable() const
++{
++    // the hard way, udisks has no notion of a disc "rewritability"
++    const QString mediaType = media();
++    return mediaType == "optical_cd_rw" || mediaType == "optical_dvd_rw" || mediaType == "optical_dvd_ram" ||
++            mediaType == "optical_dvd_plus_rw" || mediaType == "optical_dvd_plus_rw_dl" ||
++            mediaType == "optical_bd_re" || mediaType == "optical_hddvd_rw";
++}
++
++bool OpticalDisc::isBlank() const
++{
++    return m_drive->prop("OpticalBlank").toBool();
++}
++
++bool OpticalDisc::isAppendable() const
++{
++    return m_udevDevice.deviceProperty("ID_CDROM_MEDIA_STATE").toString() == QLatin1String("appendable");
++}
++
++Solid::OpticalDisc::DiscType OpticalDisc::discType() const
++{
++    QMap<Solid::OpticalDisc::DiscType, QString> map;
++    map[Solid::OpticalDisc::CdRom] = "optical_cd";
++    map[Solid::OpticalDisc::CdRecordable] = "optical_cd_r";
++    map[Solid::OpticalDisc::CdRewritable] = "optical_cd_rw";
++    map[Solid::OpticalDisc::DvdRom] = "optical_dvd";
++    map[Solid::OpticalDisc::DvdRecordable] = "optical_dvd_r";
++    map[Solid::OpticalDisc::DvdRewritable] ="optical_dvd_rw";
++    map[Solid::OpticalDisc::DvdRam] ="optical_dvd_ram";
++    map[Solid::OpticalDisc::DvdPlusRecordable] ="optical_dvd_plus_r";
++    map[Solid::OpticalDisc::DvdPlusRewritable] ="optical_dvd_plus_rw";
++    map[Solid::OpticalDisc::DvdPlusRecordableDuallayer] ="optical_dvd_plus_r_dl";
++    map[Solid::OpticalDisc::DvdPlusRewritableDuallayer] ="optical_dvd_plus_rw_dl";
++    map[Solid::OpticalDisc::BluRayRom] ="optical_bd";
++    map[Solid::OpticalDisc::BluRayRecordable] ="optical_bd_r";
++    map[Solid::OpticalDisc::BluRayRewritable] ="optical_bd_re";
++    map[Solid::OpticalDisc::HdDvdRom] ="optical_hddvd";
++    map[Solid::OpticalDisc::HdDvdRecordable] ="optical_hddvd_r";
++    map[Solid::OpticalDisc::HdDvdRewritable] ="optical_hddvd_rw";
++    // TODO add these to Solid
++    //map[Solid::OpticalDisc::MagnetoOptical] ="optical_mo";
++    //map[Solid::OpticalDisc::MountRainer] ="optical_mrw";
++    //map[Solid::OpticalDisc::MountRainerWritable] ="optical_mrw_w";
++
++    return map.key(media(), Solid::OpticalDisc::UnknownDiscType);  // FIXME optimize, lookup by value, not key
++}
++
++Solid::OpticalDisc::ContentTypes OpticalDisc::availableContent() const
++{
++    if (isBlank()) {
++        m_needsReprobe = false;
++        return Solid::OpticalDisc::NoContent;
++    }
++
++    if (m_needsReprobe) {
++        m_cachedContent = Solid::OpticalDisc::NoContent;
++        const bool hasData = m_drive->prop("OpticalNumDataTracks").toUInt() > 0;
++        const bool hasAudio = m_drive->prop("OpticalNumAudioTracks").toUInt() > 0;
++
++        if ( hasData ) {
++            m_cachedContent |= Solid::OpticalDisc::Data;
++            m_cachedContent |= advancedDiscDetect(m_device->prop("Device").toByteArray());
++        }
++        if ( hasAudio )
++            m_cachedContent |= Solid::OpticalDisc::Audio;
++
++        m_needsReprobe = false;
++    }
++
++    return m_cachedContent;
++}
++
++void OpticalDisc::slotDrivePropertiesChanged(const QString &ifaceName, const QVariantMap &changedProps, const QStringList &invalidatedProps)
++{
++    Q_UNUSED(ifaceName);
++
++    if (changedProps.keys().contains("Media") || invalidatedProps.contains("Media")) {
++        m_needsReprobe = true;
++        m_cachedContent = Solid::OpticalDisc::NoContent;
++    }
++}
++
++QString OpticalDisc::media() const
++{
++    return m_drive->prop("Media").toString();
++}
+diff --git a/tier1/solid/src/solid/backends/udisks2/udisksopticaldisc.h b/tier1/solid/src/solid/backends/udisks2/udisksopticaldisc.h
+new file mode 100644
+index 0000000..1e2f030
+--- /dev/null
++++ b/tier1/solid/src/solid/backends/udisks2/udisksopticaldisc.h
+@@ -0,0 +1,69 @@
++/*
++    Copyright 2010 Michael Zanetti <mzanetti at kde.org>
++    Copyright 2010 - 2012 Lukáš Tinkl <ltinkl at redhat.com>
++
++    This library is free software; you can redistribute it and/or
++    modify it under the terms of the GNU Lesser General Public
++    License as published by the Free Software Foundation; either
++    version 2.1 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 6 of version 3 of the license.
++
++    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
++    Lesser General Public License for more details.
++
++    You should have received a copy of the GNU Lesser General Public
++    License along with this library. If not, see <http://www.gnu.org/licenses/>.
++*/
++
++#ifndef UDISKS2OPTICALDISC_H
++#define UDISKS2OPTICALDISC_H
++
++#include <solid/ifaces/opticaldisc.h>
++
++#include "../shared/udevqtdevice.h"
++
++#include "udisksstoragevolume.h"
++#include "udisksdevice.h"
++
++namespace Solid
++{
++namespace Backends
++{
++namespace UDisks2
++{
++
++class OpticalDisc: public StorageVolume, virtual public Solid::Ifaces::OpticalDisc
++{
++    Q_OBJECT
++    Q_INTERFACES(Solid::Ifaces::OpticalDisc)
++
++public:
++    OpticalDisc(Device *device);
++    virtual ~OpticalDisc();
++
++    virtual qulonglong capacity() const;
++    virtual bool isRewritable() const;
++    virtual bool isBlank() const;
++    virtual bool isAppendable() const;
++    virtual Solid::OpticalDisc::DiscType discType() const;
++    virtual Solid::OpticalDisc::ContentTypes availableContent() const;
++
++private Q_SLOTS:
++    void slotDrivePropertiesChanged(const QString & ifaceName, const QVariantMap & changedProps, const QStringList & invalidatedProps);
++
++private:
++    QString media() const;
++    mutable bool m_needsReprobe;
++    mutable Solid::OpticalDisc::ContentTypes m_cachedContent;
++    Device * m_drive;
++    UdevQt::Device m_udevDevice;
++};
++
++}
++}
++}
++#endif // UDISKS2OPTICALDISC_H
+diff --git a/tier1/solid/src/solid/backends/udisks2/udisksopticaldrive.cpp b/tier1/solid/src/solid/backends/udisks2/udisksopticaldrive.cpp
+new file mode 100644
+index 0000000..0eb4685
+--- /dev/null
++++ b/tier1/solid/src/solid/backends/udisks2/udisksopticaldrive.cpp
+@@ -0,0 +1,188 @@
++/*
++    Copyright 2010 Michael Zanetti <mzanetti at kde.org>
++    Copyright 2010-2012 Lukáš Tinkl <ltinkl at redhat.com>
++
++    This library is free software; you can redistribute it and/or
++    modify it under the terms of the GNU Lesser General Public
++    License as published by the Free Software Foundation; either
++    version 2.1 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 6 of version 3 of the license.
++
++    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
++    Lesser General Public License for more details.
++
++    You should have received a copy of the GNU Lesser General Public
++    License along with this library. If not, see <http://www.gnu.org/licenses/>.
++*/
++
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++#include <string.h>
++#include <errno.h>
++#include <unistd.h>
++#include <stdlib.h>
++
++#include <QtCore/QFile>
++#include <QtCore/QDebug>
++
++#include "udisksopticaldrive.h"
++#include "udisks2.h"
++#include "udisksdevice.h"
++
++using namespace Solid::Backends::UDisks2;
++
++OpticalDrive::OpticalDrive(Device *device)
++    : StorageDrive(device), m_ejectInProgress(false), m_readSpeed(0), m_writeSpeed(0), m_speedsInit(false)
++{
++    m_device->registerAction("eject", this,
++                             SLOT(slotEjectRequested()),
++                             SLOT(slotEjectDone(int, const QString&)));
++
++    connect(m_device, SIGNAL(changed()), this, SLOT(slotChanged()));
++}
++
++OpticalDrive::~OpticalDrive()
++{
++}
++
++bool OpticalDrive::eject()
++{
++    if (m_ejectInProgress)
++        return false;
++    m_ejectInProgress = true;
++    m_device->broadcastActionRequested("eject");
++
++    QDBusConnection c = QDBusConnection::systemBus();
++
++    QString path = m_device->udi();
++
++    QDBusMessage msg = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, path, UD2_DBUS_INTERFACE_DRIVE, "Eject");
++    msg << QVariantMap();
++    return c.callWithCallback(msg, this, SLOT(slotDBusReply(const QDBusMessage &)), SLOT(slotDBusError(const QDBusError &)));
++}
++
++void OpticalDrive::slotDBusReply(const QDBusMessage &/*reply*/)
++{
++    m_ejectInProgress = false;
++    m_device->broadcastActionDone("eject");
++}
++
++void OpticalDrive::slotDBusError(const QDBusError &error)
++{
++    m_ejectInProgress = false;
++    m_device->broadcastActionDone("eject", m_device->errorToSolidError(error.name()),
++                                  m_device->errorToString(error.name()) + ": " +error.message());
++}
++
++void OpticalDrive::slotEjectRequested()
++{
++    m_ejectInProgress = true;
++    Q_EMIT ejectRequested(m_device->udi());
++}
++
++void OpticalDrive::slotEjectDone(int error, const QString &errorString)
++{
++    m_ejectInProgress = false;
++    Q_EMIT ejectDone(static_cast<Solid::ErrorType>(error), errorString, m_device->udi());
++}
++
++void OpticalDrive::initReadWriteSpeeds() const
++{
++#if 0
++    int read_speed, write_speed;
++    char *write_speeds = 0;
++    QByteArray device_file = QFile::encodeName(m_device->property("Device").toString());
++
++    //qDebug("Doing open (\"%s\", O_RDONLY | O_NONBLOCK)", device_file.constData());
++    int fd = open(device_file, O_RDONLY | O_NONBLOCK);
++    if (fd < 0) {
++        qWarning("Cannot open %s: %s", device_file.constData(), strerror (errno));
++        return;
++    }
++
++    if (get_read_write_speed(fd, &read_speed, &write_speed, &write_speeds) >= 0) {
++        m_readSpeed = read_speed;
++        m_writeSpeed = write_speed;
++
++        QStringList list = QString::fromLatin1(write_speeds).split(',', QString::SkipEmptyParts);
++        Q_FOREACH (const QString & speed, list)
++            m_writeSpeeds.append(speed.toInt());
++
++        free(write_speeds);
++
++        m_speedsInit = true;
++    }
++
++    close(fd);
++#endif
++}
++
++QList<int> OpticalDrive::writeSpeeds() const
++{
++    if (!m_speedsInit)
++        initReadWriteSpeeds();
++    //qDebug() << "solid write speeds:" << m_writeSpeeds;
++    return m_writeSpeeds;
++}
++
++int OpticalDrive::writeSpeed() const
++{
++    if (!m_speedsInit)
++        initReadWriteSpeeds();
++    return m_writeSpeed;
++}
++
++int OpticalDrive::readSpeed() const
++{
++    if (!m_speedsInit)
++        initReadWriteSpeeds();
++    return m_readSpeed;
++}
++
++Solid::OpticalDrive::MediumTypes OpticalDrive::supportedMedia() const
++{
++    const QStringList mediaTypes = m_device->prop("MediaCompatibility").toStringList();
++    Solid::OpticalDrive::MediumTypes supported;
++
++    QMap<Solid::OpticalDrive::MediumType, QString> map;
++    map[Solid::OpticalDrive::Cdr] = "optical_cd_r";
++    map[Solid::OpticalDrive::Cdrw] = "optical_cd_rw";
++    map[Solid::OpticalDrive::Dvd] = "optical_dvd";
++    map[Solid::OpticalDrive::Dvdr] = "optical_dvd_r";
++    map[Solid::OpticalDrive::Dvdrw] ="optical_dvd_rw";
++    map[Solid::OpticalDrive::Dvdram] ="optical_dvd_ram";
++    map[Solid::OpticalDrive::Dvdplusr] ="optical_dvd_plus_r";
++    map[Solid::OpticalDrive::Dvdplusrw] ="optical_dvd_plus_rw";
++    map[Solid::OpticalDrive::Dvdplusdl] ="optical_dvd_plus_r_dl";
++    map[Solid::OpticalDrive::Dvdplusdlrw] ="optical_dvd_plus_rw_dl";
++    map[Solid::OpticalDrive::Bd] ="optical_bd";
++    map[Solid::OpticalDrive::Bdr] ="optical_bd_r";
++    map[Solid::OpticalDrive::Bdre] ="optical_bd_re";
++    map[Solid::OpticalDrive::HdDvd] ="optical_hddvd";
++    map[Solid::OpticalDrive::HdDvdr] ="optical_hddvd_r";
++    map[Solid::OpticalDrive::HdDvdrw] ="optical_hddvd_rw";
++    // TODO add these to Solid
++    //map[Solid::OpticalDrive::Mo] ="optical_mo";
++    //map[Solid::OpticalDrive::Mr] ="optical_mrw";
++    //map[Solid::OpticalDrive::Mrw] ="optical_mrw_w";
++
++    Q_FOREACH ( const Solid::OpticalDrive::MediumType & type, map.keys() )
++    {
++        if ( mediaTypes.contains( map[type] ) )
++        {
++            supported |= type;
++        }
++    }
++
++    return supported;
++}
++
++void OpticalDrive::slotChanged()
++{
++    m_speedsInit = false; // reset the read/write speeds, changes eg. with an inserted media
++}
+diff --git a/tier1/solid/src/solid/backends/udisks2/udisksopticaldrive.h b/tier1/solid/src/solid/backends/udisks2/udisksopticaldrive.h
+new file mode 100644
+index 0000000..4c98ef5
+--- /dev/null
++++ b/tier1/solid/src/solid/backends/udisks2/udisksopticaldrive.h
+@@ -0,0 +1,81 @@
++/*
++    Copyright 2010 Michael Zanetti <mzanetti at kde.org>
++    Copyright 2010-2012 Lukáš Tinkl <ltinkl at redhat.com>
++
++    This library is free software; you can redistribute it and/or
++    modify it under the terms of the GNU Lesser General Public
++    License as published by the Free Software Foundation; either
++    version 2.1 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 6 of version 3 of the license.
++
++    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
++    Lesser General Public License for more details.
++
++    You should have received a copy of the GNU Lesser General Public
++    License along with this library. If not, see <http://www.gnu.org/licenses/>.
++*/
++
++#ifndef UDISKS2OPTICALDRIVE_H
++#define UDISKS2OPTICALDRIVE_H
++
++#include <solid/ifaces/opticaldrive.h>
++#include "udisksstoragedrive.h"
++
++namespace Solid
++{
++namespace Backends
++{
++namespace UDisks2
++{
++
++class OpticalDrive: public StorageDrive, virtual public Solid::Ifaces::OpticalDrive
++{
++    Q_OBJECT
++    Q_INTERFACES(Solid::Ifaces::OpticalDrive)
++
++public:
++    OpticalDrive(Device *device);
++    virtual ~OpticalDrive();
++
++Q_SIGNALS:
++    void ejectPressed(const QString &udi);
++    void ejectDone(Solid::ErrorType error, QVariant errorData, const QString &udi);
++    void ejectRequested(const QString &udi);
++
++public:
++    virtual bool eject();
++    virtual QList<int> writeSpeeds() const;
++    virtual int writeSpeed() const;
++    virtual int readSpeed() const;
++    virtual Solid::OpticalDrive::MediumTypes supportedMedia() const;
++
++private Q_SLOTS:
++    void slotDBusReply(const QDBusMessage &reply);
++    void slotDBusError(const QDBusError &error);
++
++    void slotEjectRequested();
++    void slotEjectDone(int error, const QString &errorString);
++
++    void slotChanged();
++
++private:
++    void initReadWriteSpeeds() const;
++
++    bool m_ejectInProgress;
++
++    // read/write speeds
++    mutable int m_readSpeed;
++    mutable int m_writeSpeed;
++    mutable QList<int> m_writeSpeeds;
++    mutable bool m_speedsInit;
++};
++
++}
++}
++}
++
++#endif // UDISKS2OPTICALDRIVE_H
+diff --git a/tier1/solid/src/solid/backends/udisks2/udisksstorageaccess.cpp b/tier1/solid/src/solid/backends/udisks2/udisksstorageaccess.cpp
+new file mode 100644
+index 0000000..9239bcb
+--- /dev/null
++++ b/tier1/solid/src/solid/backends/udisks2/udisksstorageaccess.cpp
+@@ -0,0 +1,359 @@
++/*
++    Copyright 2009 Pino Toscano <pino at kde.org>
++    Copyright 2009-2012 Lukáš Tinkl <ltinkl at redhat.com>
++
++    This library is free software; you can redistribute it and/or
++    modify it under the terms of the GNU Lesser General Public
++    License as published by the Free Software Foundation; either
++    version 2.1 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 6 of version 3 of the license.
++
++    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
++    Lesser General Public License for more details.
++
++    You should have received a copy of the GNU Lesser General Public
++    License along with this library. If not, see <http://www.gnu.org/licenses/>.
++*/
++
++#include "udisksstorageaccess.h"
++#include "udisks2.h"
++
++#include <QtCore/QProcess>
++#include <QtDBus/QtDBus>
++#include <QtGui/QApplication>
++#include <QtGui/QWidget>
++
++using namespace Solid::Backends::UDisks2;
++
++StorageAccess::StorageAccess(Device *device)
++    : DeviceInterface(device), m_setupInProgress(false), m_teardownInProgress(false), m_passphraseRequested(false)
++{
++    updateCache();
++    QDBusConnection::systemBus().connect(UD2_DBUS_SERVICE, m_device->udi(), DBUS_INTERFACE_PROPS, "PropertiesChanged", this,
++                                         SLOT(slotPropertiesChanged(QString,QVariantMap,QStringList)));
++
++    // Delay connecting to DBus signals to avoid the related time penalty
++    // in hot paths such as predicate matching
++    QTimer::singleShot(0, this, SLOT(connectDBusSignals()));
++}
++
++StorageAccess::~StorageAccess()
++{
++}
++
++void StorageAccess::connectDBusSignals()
++{
++    m_device->registerAction("setup", this,
++                             SLOT(slotSetupRequested()),
++                             SLOT(slotSetupDone(int, const QString&)));
++
++    m_device->registerAction("teardown", this,
++                             SLOT(slotTeardownRequested()),
++                             SLOT(slotTeardownDone(int, const QString&)));
++}
++
++bool StorageAccess::isLuksDevice() const
++{
++    return m_device->isEncryptedContainer(); // encrypted (and unlocked) device
++}
++
++bool StorageAccess::isAccessible() const
++{
++    if (isLuksDevice()) { // check if the cleartext slave is mounted
++        if (m_clearTextPath.isEmpty() || m_clearTextPath == "/")
++            return false;
++        Device holderDevice(m_clearTextPath);
++        return holderDevice.isMounted();
++    }
++
++    return m_device->isMounted();
++}
++
++QString StorageAccess::filePath() const
++{
++    if (!isAccessible())
++        return QString();
++
++    QByteArrayList mntPoints;
++
++    if (isLuksDevice()) {  // encrypted (and unlocked) device
++        if (m_clearTextPath.isEmpty() || m_clearTextPath == "/")
++            return QString();
++        Device holderDevice(m_clearTextPath);
++        mntPoints = qdbus_cast<QByteArrayList>(holderDevice.prop("MountPoints"));
++        if (!mntPoints.isEmpty())
++            return QFile::decodeName(mntPoints.first()); // FIXME Solid doesn't support multiple mount points
++        else
++            return QString();
++    }
++
++    mntPoints = qdbus_cast<QByteArrayList>(m_device->prop("MountPoints"));
++
++    if (!mntPoints.isEmpty())
++        return QFile::decodeName(mntPoints.first()); // FIXME Solid doesn't support multiple mount points
++    else
++        return QString();
++}
++
++bool StorageAccess::isIgnored() const
++{
++    return m_device->prop("HintIgnore").toBool(); // FIXME tune
++}
++
++bool StorageAccess::setup()
++{
++    if ( m_teardownInProgress || m_setupInProgress )
++        return false;
++    m_setupInProgress = true;
++    m_device->broadcastActionRequested("setup");
++
++    if (m_device->isEncryptedContainer())
++        return requestPassphrase();
++    else
++        return mount();
++}
++
++bool StorageAccess::teardown()
++{
++    if ( m_teardownInProgress || m_setupInProgress )
++        return false;
++    m_teardownInProgress = true;
++    m_device->broadcastActionRequested("teardown");
++
++    return unmount();
++}
++
++void StorageAccess::slotPropertiesChanged(const QString &ifaceName, const QVariantMap &changedProps, const QStringList &invalidatedProps)
++{
++    Q_UNUSED(ifaceName);
++
++    if (changedProps.keys().contains("MountPoints") || invalidatedProps.contains("MountPoints")) {
++        Q_EMIT accessibilityChanged(isAccessible(), isLuksDevice() ? m_clearTextPath : m_device->udi());
++    }
++}
++
++void StorageAccess::updateCache()
++{
++    m_isAccessible = isAccessible();
++}
++
++void StorageAccess::checkAccessibility()
++{
++    const bool old_isAccessible = m_isAccessible;
++    updateCache();
++
++    if (old_isAccessible != m_isAccessible) {
++        Q_EMIT accessibilityChanged(m_isAccessible, isLuksDevice() ? m_clearTextPath : m_device->udi());
++    }
++}
++
++void StorageAccess::slotDBusReply( const QDBusMessage & reply )
++{
++    if (m_setupInProgress)
++    {
++        if (isLuksDevice() && !isAccessible()) { // unlocked device, now mount it
++            if (reply.type() == QDBusMessage::ReplyMessage)
++                m_clearTextPath = reply.arguments().value(0).value<QDBusObjectPath>().path();
++            mount();
++        }
++        else // Don't broadcast setupDone unless the setup is really done. (Fix kde#271156)
++        {
++            m_setupInProgress = false;
++            m_device->broadcastActionDone("setup");
++
++            checkAccessibility();
++        }
++    }
++    else if (m_teardownInProgress)  // FIXME
++    {
++        if (isLuksDevice() && !m_clearTextPath.isEmpty() && m_clearTextPath != "/") // unlocked device, lock it
++        {
++            callCryptoTeardown();
++        }
++        else if (!m_clearTextPath.isEmpty() && m_clearTextPath != "/") {
++            callCryptoTeardown(true); // Lock crypted parent
++        }
++        else
++        {
++            if (m_device->prop("Ejectable").toBool() && !m_device->isOpticalDisc()) // optical drives have their Eject method
++            {
++                // try to "eject" (aka safely remove) from the (parent) drive, e.g. SD card from a reader
++                QString drivePath = m_device->prop("Drive").value<QDBusObjectPath>().path();
++                if (!drivePath.isEmpty() || drivePath != "/")
++                {
++                    QDBusConnection c = QDBusConnection::systemBus();
++                    QDBusMessage msg = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, drivePath, UD2_DBUS_INTERFACE_DRIVE, "Eject");
++                    msg << QVariantMap();   // options, unused now
++                    c.call(msg, QDBus::NoBlock);
++                }
++            }
++
++            m_teardownInProgress = false;
++            m_device->broadcastActionDone("teardown");
++
++            checkAccessibility();
++        }
++    }
++}
++
++void StorageAccess::slotDBusError( const QDBusError & error )
++{
++    if (m_setupInProgress)
++    {
++        m_setupInProgress = false;
++        m_device->broadcastActionDone("setup", m_device->errorToSolidError(error.name()),
++                                      m_device->errorToString(error.name()) + ": " +error.message());
++
++        checkAccessibility();
++    }
++    else if (m_teardownInProgress)
++    {
++        m_teardownInProgress = false;
++        m_clearTextPath.clear();
++        m_device->broadcastActionDone("teardown", m_device->errorToSolidError(error.name()),
++                                      m_device->errorToString(error.name()) + ": " + error.message());
++        checkAccessibility();
++    }
++}
++
++void StorageAccess::slotSetupRequested()
++{
++    m_setupInProgress = true;
++    Q_EMIT setupRequested(m_device->udi());
++}
++
++void StorageAccess::slotSetupDone(int error, const QString &errorString)
++{
++    m_setupInProgress = false;
++    Q_EMIT setupDone(static_cast<Solid::ErrorType>(error), errorString, m_device->udi());
++}
++
++void StorageAccess::slotTeardownRequested()
++{
++    m_teardownInProgress = true;
++    Q_EMIT teardownRequested(m_device->udi());
++}
++
++void StorageAccess::slotTeardownDone(int error, const QString &errorString)
++{
++    m_teardownInProgress = false;
++    m_clearTextPath.clear();
++    Q_EMIT teardownDone(static_cast<Solid::ErrorType>(error), errorString, m_device->udi());
++}
++
++bool StorageAccess::mount()
++{
++    QString path = m_device->udi();
++
++    if (isLuksDevice()) { // mount options for the cleartext volume
++        path = m_clearTextPath;
++    }
++
++    QDBusConnection c = QDBusConnection::systemBus();
++    QDBusMessage msg = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, path, UD2_DBUS_INTERFACE_FILESYSTEM, "Mount");
++
++    msg << QVariantMap();   // options, unused now
++
++    return c.callWithCallback(msg, this,
++                              SLOT(slotDBusReply(const QDBusMessage &)),
++                              SLOT(slotDBusError(const QDBusError &)));
++}
++
++bool StorageAccess::unmount()
++{
++    QString path = m_device->udi();
++
++    if (isLuksDevice()) { // unmount options for the cleartext volume
++        path = m_clearTextPath;
++    }
++
++    QDBusConnection c = QDBusConnection::systemBus();
++    QDBusMessage msg = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, path, UD2_DBUS_INTERFACE_FILESYSTEM, "Unmount");
++
++    msg << QVariantMap();   // options, unused now
++
++    return c.callWithCallback(msg, this,
++                              SLOT(slotDBusReply(const QDBusMessage &)),
++                              SLOT(slotDBusError(const QDBusError &)),
++                              s_unmountTimeout);
++}
++
++QString StorageAccess::generateReturnObjectPath()
++{
++    static int number = 1;
++
++    return "/org/kde/solid/UDisks2StorageAccess_"+QString::number(number++);
++}
++
++bool StorageAccess::requestPassphrase()
++{
++    QString udi = m_device->udi();
++    QString returnService = QDBusConnection::sessionBus().baseService();
++    m_lastReturnObject = generateReturnObjectPath();
++
++    QDBusConnection::sessionBus().registerObject(m_lastReturnObject, this, QDBusConnection::ExportScriptableSlots);
++
++    QWidget *activeWindow = QApplication::activeWindow();
++    uint wId = 0;
++    if (activeWindow!=0)
++        wId = (uint)activeWindow->winId();
++
++    QString appId = QCoreApplication::applicationName();
++
++    QDBusInterface soliduiserver("org.kde.kded", "/modules/soliduiserver", "org.kde.SolidUiServer");
++    QDBusReply<void> reply = soliduiserver.call("showPassphraseDialog", udi, returnService,
++                                                m_lastReturnObject, wId, appId);
++    m_passphraseRequested = reply.isValid();
++    if (!m_passphraseRequested)
++        qWarning() << "Failed to call the SolidUiServer, D-Bus said:" << reply.error();
++
++    return m_passphraseRequested;
++}
++
++void StorageAccess::passphraseReply(const QString & passphrase)
++{
++    if (m_passphraseRequested)
++    {
++        QDBusConnection::sessionBus().unregisterObject(m_lastReturnObject);
++        m_passphraseRequested = false;
++        if (!passphrase.isEmpty())
++            callCryptoSetup(passphrase);
++        else
++        {
++            m_setupInProgress = false;
++            m_device->broadcastActionDone("setup");
++        }
++    }
++}
++
++void StorageAccess::callCryptoSetup(const QString & passphrase)
++{
++    QDBusConnection c = QDBusConnection::systemBus();
++    QDBusMessage msg = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, m_device->udi(), UD2_DBUS_INTERFACE_ENCRYPTED, "Unlock");
++
++    msg << passphrase.toUtf8();  // QByteArray
++    msg << QVariantMap();   // options, unused now
++
++    c.callWithCallback(msg, this,
++                       SLOT(slotDBusReply(const QDBusMessage &)),
++                       SLOT(slotDBusError(const QDBusError &)));
++}
++
++bool StorageAccess::callCryptoTeardown(bool actOnParent)
++{
++    QDBusConnection c = QDBusConnection::systemBus();
++    QDBusMessage msg = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE,
++                                                      actOnParent ? (m_device->prop("CryptoBackingDevice").value<QDBusObjectPath>().path()) : m_device->udi(),
++                                                      UD2_DBUS_INTERFACE_ENCRYPTED, "Lock");
++    msg << QVariantMap();   // options, unused now
++
++    m_clearTextPath.clear();
++
++    return c.callWithCallback(msg, this,
++                              SLOT(slotDBusReply(const QDBusMessage &)),
++                              SLOT(slotDBusError(const QDBusError &)));
++}
+diff --git a/tier1/solid/src/solid/backends/udisks2/udisksstorageaccess.h b/tier1/solid/src/solid/backends/udisks2/udisksstorageaccess.h
+new file mode 100644
+index 0000000..36f2102
+--- /dev/null
++++ b/tier1/solid/src/solid/backends/udisks2/udisksstorageaccess.h
+@@ -0,0 +1,104 @@
++/*
++    Copyright 2009 Pino Toscano <pino at kde.org>
++    Copyright 2009-2012 Lukáš Tinkl <ltinkl at redhat.com>
++
++    This library is free software; you can redistribute it and/or
++    modify it under the terms of the GNU Lesser General Public
++    License as published by the Free Software Foundation; either
++    version 2.1 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 6 of version 3 of the license.
++
++    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
++    Lesser General Public License for more details.
++
++    You should have received a copy of the GNU Lesser General Public
++    License along with this library. If not, see <http://www.gnu.org/licenses/>.
++*/
++
++#ifndef UDISKS2STORAGEACCESS_H
++#define UDISKS2STORAGEACCESS_H
++
++#include <solid/ifaces/storageaccess.h>
++#include "udisksdeviceinterface.h"
++
++#include <QtDBus/QDBusMessage>
++#include <QtDBus/QDBusError>
++
++namespace Solid
++{
++namespace Backends
++{
++namespace UDisks2
++{
++class StorageAccess : public DeviceInterface, virtual public Solid::Ifaces::StorageAccess
++{
++    Q_OBJECT
++    Q_INTERFACES(Solid::Ifaces::StorageAccess)
++
++public:
++    StorageAccess(Device *device);
++    virtual ~StorageAccess();
++
++    virtual bool isAccessible() const;
++    virtual QString filePath() const;
++    virtual bool isIgnored() const;
++    virtual bool setup();
++    virtual bool teardown();
++
++Q_SIGNALS:
++    void accessibilityChanged(bool accessible, const QString &udi);
++    void setupDone(Solid::ErrorType error, QVariant errorData, const QString &udi);
++    void teardownDone(Solid::ErrorType error, QVariant errorData, const QString &udi);
++    void setupRequested(const QString &udi);
++    void teardownRequested(const QString &udi);
++
++public Q_SLOTS:
++    Q_SCRIPTABLE Q_NOREPLY void passphraseReply(const QString & passphrase);
++
++private Q_SLOTS:
++    void slotPropertiesChanged(const QString & ifaceName, const QVariantMap & changedProps, const QStringList & invalidatedProps);
++    void slotDBusReply(const QDBusMessage & reply);
++    void slotDBusError(const QDBusError & error);
++
++    void connectDBusSignals();
++
++    void slotSetupRequested();
++    void slotSetupDone(int error, const QString &errorString);
++    void slotTeardownRequested();
++    void slotTeardownDone(int error, const QString &errorString);
++
++private:
++    /// @return true if this device is luks and unlocked
++    bool isLuksDevice() const;
++
++    void updateCache();
++    void checkAccessibility();
++
++    bool mount();
++    bool unmount();
++
++    bool requestPassphrase();
++    void callCryptoSetup( const QString & passphrase );
++    bool callCryptoTeardown( bool actOnParent=false );
++
++    QString generateReturnObjectPath();
++
++private:
++    bool m_isAccessible;
++    bool m_setupInProgress;
++    bool m_teardownInProgress;
++    bool m_passphraseRequested;
++    QString m_lastReturnObject;
++    QString m_clearTextPath;  // path to the unlocked cleartext device
++
++    static const int s_unmountTimeout = 0x7fffffff;
++};
++}
++}
++}
++
++#endif // UDISKS2STORAGEACCESS_H
+diff --git a/tier1/solid/src/solid/backends/udisks2/udisksstoragedrive.cpp b/tier1/solid/src/solid/backends/udisks2/udisksstoragedrive.cpp
+new file mode 100644
+index 0000000..3a62857
+--- /dev/null
++++ b/tier1/solid/src/solid/backends/udisks2/udisksstoragedrive.cpp
+@@ -0,0 +1,144 @@
++/*
++    Copyright 2010 Michael Zanetti <mzanetti at kde.org>
++    Copyright 2010-2012 Lukáš Tinkl <ltinkl at redhat.com>
++
++    This library is free software; you can redistribute it and/or
++    modify it under the terms of the GNU Lesser General Public
++    License as published by the Free Software Foundation; either
++    version 2.1 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 6 of version 3 of the license.
++
++    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
++    Lesser General Public License for more details.
++
++    You should have received a copy of the GNU Lesser General Public
++    License along with this library. If not, see <http://www.gnu.org/licenses/>.
++*/
++
++#include "udisksstoragedrive.h"
++
++#include "../shared/udevqtclient.h"
++
++#include <QtCore/QDebug>
++#include <QtCore/QFile>
++
++using namespace Solid::Backends::UDisks2;
++
++StorageDrive::StorageDrive(Device *device)
++    : Block(device)
++{
++    UdevQt::Client client(this);
++    m_udevDevice = client.deviceByDeviceFile(QFile::decodeName(m_device->prop("Device").toByteArray()));
++}
++
++StorageDrive::~StorageDrive()
++{
++}
++
++qulonglong StorageDrive::size() const
++{
++    return m_device->prop("Size").toULongLong();
++}
++
++bool StorageDrive::isHotpluggable() const
++{
++    const Solid::StorageDrive::Bus _bus = bus();
++    return _bus == Solid::StorageDrive::Usb || _bus == Solid::StorageDrive::Ieee1394;
++}
++
++bool StorageDrive::isRemovable() const
++{
++    return m_device->prop("MediaRemovable").toBool() || m_device->prop("Removable").toBool();
++}
++
++Solid::StorageDrive::DriveType StorageDrive::driveType() const
++{
++    const QStringList mediaTypes = m_device->prop("MediaCompatibility").toStringList();
++
++    if ( m_device->isOpticalDrive() ) // optical disks
++    {
++        return Solid::StorageDrive::CdromDrive;
++    }
++    else if ( mediaTypes.contains( "floppy" ) )
++    {
++        return Solid::StorageDrive::Floppy;
++    }
++#if 0 // TODO add to Solid
++    else if ( mediaTypes.contains( "floppy_jaz" ) )
++    {
++        return Solid::StorageDrive::Jaz;
++    }
++    else if ( mediaTypes.contains( "floppy_zip" ) )
++    {
++        return Solid::StorageDrive::Zip;
++    }
++    else if ( mediaTypes.contains( "flash" ) )
++    {
++        return Solid::StorageDrive::Flash;
++    }
++#endif
++    else if ( mediaTypes.contains( "flash_cf" ) )
++    {
++        return Solid::StorageDrive::CompactFlash;
++    }
++    else if ( mediaTypes.contains( "flash_ms" ) )
++    {
++        return Solid::StorageDrive::MemoryStick;
++    }
++    else if ( mediaTypes.contains( "flash_sm" ) )
++    {
++        return Solid::StorageDrive::SmartMedia;
++    }
++    else if ( mediaTypes.contains( "flash_sd" ) || mediaTypes.contains( "flash_sdhc" )
++              || mediaTypes.contains( "flash_mmc" ) || mediaTypes.contains("flash_sdxc") )
++    {
++        return Solid::StorageDrive::SdMmc;
++    }
++    // FIXME: udisks2 doesn't know about xD cards
++    else
++    {
++        return Solid::StorageDrive::HardDisk;
++    }
++}
++
++Solid::StorageDrive::Bus StorageDrive::bus() const
++{
++    const QString bus = m_device->prop("ConnectionBus").toString();
++    const QString udevBus = m_udevDevice.deviceProperty("ID_BUS").toString();
++
++    if (udevBus == "ata")
++    {
++        if (m_udevDevice.deviceProperty("ID_ATA_SATA").toInt() == 1) // serial ATA
++            return Solid::StorageDrive::Sata;
++        else  // parallel (classical) ATA
++            return Solid::StorageDrive::Ide;
++    }
++    else if (bus == "usb")
++    {
++        return Solid::StorageDrive::Usb;
++    }
++    else if (bus == "ieee1394")
++    {
++        return Solid::StorageDrive::Ieee1394;
++    }
++    else if (udevBus == "scsi")
++    {
++        return Solid::StorageDrive::Scsi;
++    }
++#if 0  // TODO add these to Solid
++    else if ( bus == "sdio" )
++    {
++        return Solid::StorageDrive::SDIO;
++    }
++    else if ( bus == "virtual" )
++    {
++        return Solid::StorageDrive::Virtual;
++    }
++#endif
++    else
++        return Solid::StorageDrive::Platform;
++}
+diff --git a/tier1/solid/src/solid/backends/udisks2/udisksstoragedrive.h b/tier1/solid/src/solid/backends/udisks2/udisksstoragedrive.h
+new file mode 100644
+index 0000000..97007b3
+--- /dev/null
++++ b/tier1/solid/src/solid/backends/udisks2/udisksstoragedrive.h
+@@ -0,0 +1,61 @@
++/*
++    Copyright 2010 Michael Zanetti <mzanetti at kde.org>
++    Copyright 2010-2012 Lukáš Tinkl <ltinkl at redhat.com>
++
++    This library is free software; you can redistribute it and/or
++    modify it under the terms of the GNU Lesser General Public
++    License as published by the Free Software Foundation; either
++    version 2.1 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 6 of version 3 of the license.
++
++    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
++    Lesser General Public License for more details.
++
++    You should have received a copy of the GNU Lesser General Public
++    License along with this library. If not, see <http://www.gnu.org/licenses/>.
++*/
++
++#ifndef UDISKS2STORAGEDRIVE_H
++#define UDISKS2STORAGEDRIVE_H
++
++#include <ifaces/storagedrive.h>
++
++#include "../shared/udevqtdevice.h"
++
++#include "udisksblock.h"
++
++namespace Solid
++{
++namespace Backends
++{
++namespace UDisks2
++{
++
++class StorageDrive: public Block, virtual public Solid::Ifaces::StorageDrive
++{
++    Q_OBJECT
++    Q_INTERFACES(Solid::Ifaces::StorageDrive)
++
++public:
++    StorageDrive(Device *device);
++    virtual ~StorageDrive();
++
++    virtual qulonglong size() const;
++    virtual bool isHotpluggable() const;
++    virtual bool isRemovable() const;
++    virtual Solid::StorageDrive::DriveType driveType() const;
++    virtual Solid::StorageDrive::Bus bus() const;
++
++private:
++    UdevQt::Device m_udevDevice;
++};
++
++}
++}
++}
++
++#endif // UDISK2SSTORAGEDRIVE_H
+diff --git a/tier1/solid/src/solid/backends/udisks2/udisksstoragevolume.cpp b/tier1/solid/src/solid/backends/udisks2/udisksstoragevolume.cpp
+new file mode 100644
+index 0000000..a7d8fad
+--- /dev/null
++++ b/tier1/solid/src/solid/backends/udisks2/udisksstoragevolume.cpp
+@@ -0,0 +1,105 @@
++/*
++    Copyright 2010 Michael Zanetti <mzanetti at kde.org>
++    Copyright 2010-2012 Lukáš Tinkl <ltinkl at redhat.com>
++
++    This library is free software; you can redistribute it and/or
++    modify it under the terms of the GNU Lesser General Public
++    License as published by the Free Software Foundation; either
++    version 2.1 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 6 of version 3 of the license.
++
++    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
++    Lesser General Public License for more details.
++
++    You should have received a copy of the GNU Lesser General Public
++    License along with this library. If not, see <http://www.gnu.org/licenses/>.
++*/
++
++#include "udisksstoragevolume.h"
++#include "udisks2.h"
++
++using namespace Solid::Backends::UDisks2;
++
++StorageVolume::StorageVolume(Device *device)
++    : Block(device)
++{
++}
++
++StorageVolume::~StorageVolume()
++{
++}
++
++QString StorageVolume::encryptedContainerUdi() const
++{
++    const QString path = m_device->prop("CryptoBackingDevice").value<QDBusObjectPath>().path();
++    if ( path.isEmpty() || path == "/")
++        return QString();
++    else
++        return path;
++}
++
++qulonglong StorageVolume::size() const
++{
++    return m_device->prop("Size").toULongLong();
++}
++
++QString StorageVolume::uuid() const
++{
++    return m_device->prop("IdUUID").toString();
++}
++
++QString StorageVolume::label() const
++{
++    QString label = m_device->prop("HintName").toString();
++    if (label.isEmpty())
++        label = m_device->prop("IdLabel").toString();
++    if (label.isEmpty())
++        label = m_device->prop("Name").toString();
++    return label;
++}
++
++QString StorageVolume::fsType() const
++{
++    return m_device->prop("IdType").toString();
++}
++
++Solid::StorageVolume::UsageType StorageVolume::usage() const
++{
++    const QString usage = m_device->prop("IdUsage").toString();
++
++    if (m_device->hasInterface(UD2_DBUS_INTERFACE_FILESYSTEM))
++    {
++        return Solid::StorageVolume::FileSystem;
++    }
++    else if (m_device->isPartitionTable())
++    {
++        return Solid::StorageVolume::PartitionTable;
++    }
++    else if (usage == "raid")
++    {
++        return Solid::StorageVolume::Raid;
++    }
++    else if (m_device->isEncryptedContainer())
++    {
++        return Solid::StorageVolume::Encrypted;
++    }
++    else if (usage == "unused" || usage.isEmpty())
++    {
++        return Solid::StorageVolume::Unused;
++    }
++    else
++    {
++        return Solid::StorageVolume::Other;
++    }
++}
++
++bool StorageVolume::isIgnored() const
++{
++    const Solid::StorageVolume::UsageType usg = usage();
++    return m_device->prop("HintIgnore").toBool() || m_device->isSwap() ||
++            ((usg == Solid::StorageVolume::Unused || usg == Solid::StorageVolume::Other || usg == Solid::StorageVolume::PartitionTable) && !m_device->isOpticalDisc());
++}
+diff --git a/tier1/solid/src/solid/backends/udisks2/udisksstoragevolume.h b/tier1/solid/src/solid/backends/udisks2/udisksstoragevolume.h
+new file mode 100644
+index 0000000..2ca04d2
+--- /dev/null
++++ b/tier1/solid/src/solid/backends/udisks2/udisksstoragevolume.h
+@@ -0,0 +1,57 @@
++/*
++    Copyright 2010 Michael Zanetti <mzanetti at kde.org>
++
++    This library is free software; you can redistribute it and/or
++    modify it under the terms of the GNU Lesser General Public
++    License as published by the Free Software Foundation; either
++    version 2.1 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 6 of version 3 of the license.
++
++    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
++    Lesser General Public License for more details.
++
++    You should have received a copy of the GNU Lesser General Public
++    License along with this library. If not, see <http://www.gnu.org/licenses/>.
++*/
++
++#ifndef UDISKS2STORAGEVOLUME_H
++#define UDISKS2STORAGEVOLUME_H
++
++#include <ifaces/storagevolume.h>
++#include "udisksblock.h"
++
++
++namespace Solid
++{
++namespace Backends
++{
++namespace UDisks2
++{
++
++class StorageVolume: public Block, virtual public Solid::Ifaces::StorageVolume
++{
++    Q_OBJECT
++    Q_INTERFACES(Solid::Ifaces::StorageVolume)
++
++public:
++    StorageVolume(Device *device);
++    virtual ~StorageVolume();
++
++    virtual QString encryptedContainerUdi() const;
++    virtual qulonglong size() const;
++    virtual QString uuid() const;
++    virtual QString label() const;
++    virtual QString fsType() const;
++    virtual Solid::StorageVolume::UsageType usage() const;
++    virtual bool isIgnored() const;
++};
++
++}
++}
++}
++
++#endif // UDISKS2STORAGEVOLUME_H
diff --git a/kdelibs.spec b/kdelibs.spec
index b8afa32..40d057c 100644
--- a/kdelibs.spec
+++ b/kdelibs.spec
@@ -20,7 +20,7 @@
 
 Summary: KDE Libraries
 Version: 4.8.2
-Release: 2%{?dist}
+Release: 3%{?dist}
 
 Name: kdelibs
 Epoch: 6
@@ -142,6 +142,8 @@ Patch200: kdelibs-4.3.1-CVE-2009-2702.patch
 ## Fedora specific patches
 # make forcefully hal-free build
 Patch300: kdelibs-4.7.3-halectomy.patch
+# udisks2 Solid backend, halectomy
+Patch301: kdelibs-udisks2-backend.patch
 
 # force upgrade of apps using the discontinued KatePart Smart* interfaces to
 # versions using the new Moving* interfaces instead
@@ -330,7 +332,14 @@ sed -i -e "s|@@VERSION_RELEASE@@|%{version}-%{release}|" kio/kio/kprotocolmanage
 %patch200 -p1 -b .CVE-2009-2702
 
 # Fedora patches
+%if 0%{?fedora}
 %patch300 -p1 -b .halectomy
+%endif
+%if 0%{?rhel}
+pushd solid
+%patch301 -p4 -b .udisks2backend
+popd
+%endif
 
 
 %build
@@ -578,6 +587,9 @@ rm -rf %{buildroot}
 
 
 %changelog
+* Mon Apr 16 2012 Lukas Tinkl <ltinkl at redhat.com> - 6:4.8.2-3
+- add udisks2 Solid backend plus RHEL conditional
+
 * Thu Apr 12 2012 Than Ngo <than at redhat.com> - 6:4.8.2-2
 - Load/Update filter lists only when AdBlock is enabled
 


More information about the scm-commits mailing list