kdelibs/kdelibs-udisks2-backend.patch
2012-10-29 18:58:24 +01:00

3799 lines
130 KiB
Diff

diff --git a/solid/solid/CMakeLists.txt b/solid/solid/CMakeLists.txt
index 0aa7a43..21e774c 100644
--- a/solid/solid/CMakeLists.txt
+++ b/solid/solid/CMakeLists.txt
@@ -1,6 +1,7 @@
set( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR} )
add_subdirectory( ifaces )
include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} )
+include_directories( ${QT_QTDBUS_INCLUDE_DIR} )
if(WIN32)
include_directories( ${KDEWIN_INCLUDES} )
@@ -39,7 +40,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
)
@@ -225,33 +225,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
@@ -264,19 +237,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." )
- 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
- )
+ message(STATUS "Building Solid UDisks2 backend." )
+ set(solid_LIB_SRCS ${solid_LIB_SRCS}
+ 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)
message(STATUS "Building Solid fstab backend." )
diff --git a/solid/solid/backends/udisks2/dbus/manager.cpp b/solid/solid/backends/udisks2/dbus/manager.cpp
new file mode 100644
index 0000000..7ea4aa8
--- /dev/null
+++ b/solid/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/solid/solid/backends/udisks2/dbus/manager.h b/solid/solid/backends/udisks2/dbus/manager.h
new file mode 100644
index 0000000..11f0be8
--- /dev/null
+++ b/solid/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/solid/solid/backends/udisks2/dbus/manager.xml b/solid/solid/backends/udisks2/dbus/manager.xml
new file mode 100644
index 0000000..8f25cb6
--- /dev/null
+++ b/solid/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/solid/solid/backends/udisks2/udisks2.h b/solid/solid/backends/udisks2/udisks2.h
new file mode 100644
index 0000000..8dda86a
--- /dev/null
+++ b/solid/solid/backends/udisks2/udisks2.h
@@ -0,0 +1,78 @@
+/*
+ Copyright 2012 Lukáš Tinkl <ltinkl@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"
+#define UD2_DBUS_INTERFACE_LOOP "org.freedesktop.UDisks2.Loop"
+
+/* 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/solid/solid/backends/udisks2/udisksblock.cpp b/solid/solid/backends/udisks2/udisksblock.cpp
new file mode 100644
index 0000000..f3cd1e8
--- /dev/null
+++ b/solid/solid/backends/udisks2/udisksblock.cpp
@@ -0,0 +1,88 @@
+/*
+ Copyright 2012 Lukáš Tinkl <ltinkl@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 <QtDBus/QDBusConnection>
+#include <QtDBus/QDBusPendingReply>
+#include <QtXml/QDomDocument>
+
+#include "udisksblock.h"
+
+using namespace Solid::Backends::UDisks2;
+
+Block::Block(Device *dev)
+ : DeviceInterface(dev)
+{
+ m_devNum = m_device->prop("DeviceNumber").toULongLong();
+ m_devFile = QFile::decodeName(m_device->prop("Device").toByteArray());
+
+ // we have a drive (non-block device for udisks), so let's find the corresponding (real) block device
+ if (m_devNum == 0 || m_devFile.isEmpty()) {
+ const QString path = "/org/freedesktop/UDisks2/block_devices";
+ QDBusMessage call = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, path,
+ DBUS_INTERFACE_INTROSPECT, "Introspect");
+ QDBusPendingReply<QString> reply = QDBusConnection::systemBus().asyncCall(call);
+ reply.waitForFinished();
+
+ if (reply.isValid()) {
+ QDomDocument dom;
+ dom.setContent(reply.value());
+ QDomNodeList nodeList = dom.documentElement().elementsByTagName("node");
+ for (int i = 0; i < nodeList.count(); i++) {
+ QDomElement nodeElem = nodeList.item(i).toElement();
+ if (!nodeElem.isNull() && nodeElem.hasAttribute("name")) {
+ const QString udi = path + "/" + nodeElem.attribute("name");
+
+ Device device(udi);
+ if (device.drivePath() == dev->udi()) {
+ m_devNum = device.prop("DeviceNumber").toULongLong();
+ m_devFile = QFile::decodeName(device.prop("Device").toByteArray());
+ break;
+ }
+ }
+ }
+ }
+ else
+ qWarning() << "Failed enumerating UDisks2 objects:" << reply.error().name() << "\n" << reply.error().message();
+ }
+
+ //qDebug() << "devnum:" << m_devNum << "dev file:" << m_devFile;
+}
+
+Block::~Block()
+{
+}
+
+QString Block::device() const
+{
+ return m_devFile;
+}
+
+int Block::deviceMinor() const
+{
+ return MINOR(m_devNum);
+}
+
+int Block::deviceMajor() const
+{
+ return MAJOR(m_devNum);
+}
diff --git a/solid/solid/backends/udisks2/udisksblock.h b/solid/solid/backends/udisks2/udisksblock.h
new file mode 100644
index 0000000..19cb70a
--- /dev/null
+++ b/solid/solid/backends/udisks2/udisksblock.h
@@ -0,0 +1,56 @@
+/*
+ Copyright 2012 Lukáš Tinkl <ltinkl@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 *dev);
+ virtual ~Block();
+
+ virtual QString device() const;
+ virtual int deviceMinor() const;
+ virtual int deviceMajor() const;
+private:
+ dev_t m_devNum;
+ QString m_devFile;
+};
+
+}
+}
+}
+
+#endif // UDISKS2BLOCK_H
diff --git a/solid/solid/backends/udisks2/udisksdevice.cpp b/solid/solid/backends/udisks2/udisksdevice.cpp
new file mode 100644
index 0000000..a3f780f
--- /dev/null
+++ b/solid/solid/backends/udisks2/udisksdevice.cpp
@@ -0,0 +1,927 @@
+/*
+ Copyright 2010 Michael Zanetti <mzanetti@kde.org>
+ Copyright 2010-2012 Lukáš Tinkl <ltinkl@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 = QCoreApplication::translate("", "%1 TiB").arg(QLocale().toString(size / 1024.0, 'f', 1));
+ else
+ s = QCoreApplication::translate("", "%1 GiB").arg(QLocale().toString(size, 'f', 1));
+ }
+ // Mebi-byte
+ else if ( size >= 1048576.0 )
+ {
+ size /= 1048576.0;
+ s = QCoreApplication::translate("", "%1 MiB").arg(QLocale().toString(size, 'f', 1));
+ }
+ // Kibi-byte
+ else if ( size >= 1024.0 )
+ {
+ size /= 1024.0;
+ s = QCoreApplication::translate("", "%1 KiB").arg(QLocale().toString(size, 'f', 1));
+ }
+ // Just byte
+ else if ( size > 0 )
+ {
+ s = QCoreApplication::translate("", "%1 B").arg(QLocale().toString(size, 'f', 1));
+ }
+ // Nothing
+ else
+ {
+ s = QCoreApplication::translate("", "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() || isDrive();
+ 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 = property("HintName").toString(); // non-cached
+ if (!hintName.isEmpty())
+ return hintName;
+
+ if (isLoop())
+ return QObject::tr("Loop Device");
+ else if (isSwap())
+ return QObject::tr("Swap Space");
+ else 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();
+ const 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 = QCoreApplication::translate("", "CD-ROM", "First item of %1%2 Drive sentence");
+ if (mediumTypes & Solid::OpticalDrive::Cdr)
+ first = QCoreApplication::translate("", "CD-R", "First item of %1%2 Drive sentence");
+ if (mediumTypes & Solid::OpticalDrive::Cdrw)
+ first = QCoreApplication::translate("", "CD-RW", "First item of %1%2 Drive sentence");
+
+ if (mediumTypes & Solid::OpticalDrive::Dvd)
+ second = QCoreApplication::translate("", "/DVD-ROM", "Second item of %1%2 Drive sentence");
+ if (mediumTypes & Solid::OpticalDrive::Dvdplusr)
+ second = QCoreApplication::translate("", "/DVD+R", "Second item of %1%2 Drive sentence");
+ if (mediumTypes & Solid::OpticalDrive::Dvdplusrw)
+ second = QCoreApplication::translate("", "/DVD+RW", "Second item of %1%2 Drive sentence");
+ if (mediumTypes & Solid::OpticalDrive::Dvdr)
+ second = QCoreApplication::translate("", "/DVD-R", "Second item of %1%2 Drive sentence");
+ if (mediumTypes & Solid::OpticalDrive::Dvdrw)
+ second = QCoreApplication::translate("", "/DVD-RW", "Second item of %1%2 Drive sentence");
+ if (mediumTypes & Solid::OpticalDrive::Dvdram)
+ second = QCoreApplication::translate("", "/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 = QCoreApplication::translate("", "/BD-ROM", "Second item of %1%2 Drive sentence");
+ if (mediumTypes & Solid::OpticalDrive::Bdr)
+ second = QCoreApplication::translate("", "/BD-R", "Second item of %1%2 Drive sentence");
+ if (mediumTypes & Solid::OpticalDrive::Bdre)
+ second = QCoreApplication::translate("", "/BD-RE", "Second item of %1%2 Drive sentence");
+ if (mediumTypes & Solid::OpticalDrive::HdDvd)
+ second = QCoreApplication::translate("", "/HD DVD-ROM", "Second item of %1%2 Drive sentence");
+ if (mediumTypes & Solid::OpticalDrive::HdDvdr)
+ second = QCoreApplication::translate("", "/HD DVD-R", "Second item of %1%2 Drive sentence");
+ if (mediumTypes & Solid::OpticalDrive::HdDvdrw)
+ second = QCoreApplication::translate("", "/HD DVD-RW", "Second item of %1%2 Drive sentence");
+
+ if (drive_is_hotpluggable)
+ description = QCoreApplication::translate("", "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 = QCoreApplication::translate("", "%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 = QCoreApplication::translate("", "External Floppy Drive");
+ else
+ description = QCoreApplication::translate("", "Floppy Drive");
+
+ return description;
+ }
+
+ const 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 = QCoreApplication::translate("", "%1 External Hard Drive", "%1 is the size").arg(size_str);
+ else
+ description = QCoreApplication::translate("", "%1 Hard Drive", "%1 is the size").arg(size_str);
+ } else {
+ if (drive_is_hotpluggable)
+ description = QCoreApplication::translate("", "External Hard Drive");
+ else
+ description = QCoreApplication::translate("", "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 = QCoreApplication::translate("", "%1 %2", "%1 is the vendor, %2 is the model of the device").arg(vendor_str).arg(model);
+ }
+ }
+ }
+
+ if (vendormodel_str.isEmpty())
+ description = QCoreApplication::translate("", "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;
+
+ 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 = QCoreApplication::translate("", "CD-ROM");
+ break;
+
+ case Solid::OpticalDisc::CdRecordable:
+ if (disc.isBlank())
+ description = QCoreApplication::translate("", "Blank CD-R");
+ else
+ description = QCoreApplication::translate("", "CD-R");
+ break;
+
+ case Solid::OpticalDisc::CdRewritable:
+ if (disc.isBlank())
+ description = QCoreApplication::translate("", "Blank CD-RW");
+ else
+ description = QCoreApplication::translate("", "CD-RW");
+ break;
+
+ case Solid::OpticalDisc::DvdRom:
+ description = QCoreApplication::translate("", "DVD-ROM");
+ break;
+
+ case Solid::OpticalDisc::DvdRam:
+ if (disc.isBlank())
+ description = QCoreApplication::translate("", "Blank DVD-RAM");
+ else
+ description = QCoreApplication::translate("", "DVD-RAM");
+ break;
+
+ case Solid::OpticalDisc::DvdRecordable:
+ if (disc.isBlank())
+ description = QCoreApplication::translate("", "Blank DVD-R");
+ else
+ description = QCoreApplication::translate("", "DVD-R");
+ break;
+
+ case Solid::OpticalDisc::DvdPlusRecordableDuallayer:
+ if (disc.isBlank())
+ description = QCoreApplication::translate("", "Blank DVD+R Dual-Layer");
+ else
+ description = QCoreApplication::translate("", "DVD+R Dual-Layer");
+ break;
+
+ case Solid::OpticalDisc::DvdRewritable:
+ if (disc.isBlank())
+ description = QCoreApplication::translate("", "Blank DVD-RW");
+ else
+ description = QCoreApplication::translate("", "DVD-RW");
+ break;
+
+ case Solid::OpticalDisc::DvdPlusRecordable:
+ if (disc.isBlank())
+ description = QCoreApplication::translate("", "Blank DVD+R");
+ else
+ description = QCoreApplication::translate("", "DVD+R");
+ break;
+
+ case Solid::OpticalDisc::DvdPlusRewritable:
+ if (disc.isBlank())
+ description = QCoreApplication::translate("", "Blank DVD+RW");
+ else
+ description = QCoreApplication::translate("", "DVD+RW");
+ break;
+
+ case Solid::OpticalDisc::DvdPlusRewritableDuallayer:
+ if (disc.isBlank())
+ description = QCoreApplication::translate("", "Blank DVD+RW Dual-Layer");
+ else
+ description = QCoreApplication::translate("", "DVD+RW Dual-Layer");
+ break;
+
+ case Solid::OpticalDisc::BluRayRom:
+ description = QCoreApplication::translate("", "BD-ROM");
+ break;
+
+ case Solid::OpticalDisc::BluRayRecordable:
+ if (disc.isBlank())
+ description = QCoreApplication::translate("", "Blank BD-R");
+ else
+ description = QCoreApplication::translate("", "BD-R");
+ break;
+
+ case Solid::OpticalDisc::BluRayRewritable:
+ if (disc.isBlank())
+ description = QCoreApplication::translate("", "Blank BD-RE");
+ else
+ description = QCoreApplication::translate("", "BD-RE");
+ break;
+
+ case Solid::OpticalDisc::HdDvdRom:
+ description = QCoreApplication::translate("", "HD DVD-ROM");
+ break;
+
+ case Solid::OpticalDisc::HdDvdRecordable:
+ if (disc.isBlank())
+ description = QCoreApplication::translate("", "Blank HD DVD-R");
+ else
+ description = QCoreApplication::translate("", "HD DVD-R");
+ break;
+
+ case Solid::OpticalDisc::HdDvdRewritable:
+ if (disc.isBlank())
+ description = QCoreApplication::translate("", "Blank HD DVD-RW");
+ else
+ description = QCoreApplication::translate("", "HD DVD-RW");
+ break;
+ }
+
+ // Special case for pure audio disc
+ if (disc.availableContent() == Solid::OpticalDisc::Audio)
+ description = QCoreApplication::translate("", "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 = QCoreApplication::translate("", "%1 Encrypted Container", "%1 is the size").arg(size_str);
+ else
+ description = QCoreApplication::translate("", "Encrypted Container");
+ }
+ else if (drive_type == Solid::StorageDrive::HardDisk && !drive_is_removable)
+ {
+ if (!size_str.isEmpty())
+ {
+ if (drive_is_hotpluggable)
+ description = QCoreApplication::translate("", "%1 External Hard Drive", "%1 is the size").arg(size_str);
+ else
+ description = QCoreApplication::translate("", "%1 Hard Drive", "%1 is the size").arg(size_str);
+ }
+ else
+ {
+ if (drive_is_hotpluggable)
+ description = QCoreApplication::translate("", "External Hard Drive");
+ else
+ description = QCoreApplication::translate("", "Hard Drive");
+ }
+ }
+ else
+ {
+ if (drive_is_removable)
+ description = QCoreApplication::translate("", "%1 Removable Media", "%1 is the size").arg(size_str);
+ else
+ description = QCoreApplication::translate("", "%1 Media", "%1 is the size").arg(size_str);
+ }
+
+ return description;
+}
+
+QString Device::icon() const
+{
+ QString iconName = property( "HintIconName" ).toString(); // non-cached
+
+ if ( !iconName.isEmpty() )
+ {
+ return iconName;
+ }
+ else if (isLoop() || isSwap())
+ {
+ return "drive-harddisk";
+ }
+ else if (isDrive()) {
+ const bool isRemovable = prop("Removable").toBool();
+ const QString conn = prop("ConnectionBus").toString();
+
+ if (isOpticalDrive())
+ return "drive-optical";
+ else if (isRemovable && !prop("Optical").toBool()) {
+ if (conn == "usb")
+ return "drive-removable-media-usb";
+ else
+ return "drive-removable-media";
+ }
+ }
+ else if (isBlock()) {
+ const QString drv = drivePath();
+ if (drv.isEmpty() || drv == "/")
+ return "drive-harddisk"; // stuff like loop devices or swap which don't have the Drive prop set
+
+ Device drive(drv);
+
+ // handle media
+ const QString media = drive.prop("Media").toString();
+
+ if ( !media.isEmpty() )
+ {
+ if ( drive.prop("Optical").toBool() ) // 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 {
+ qWarning() << "got invalid reply for cache:" << key;
+ }
+}
+
+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
+{
+ QDBusMessage call = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, m_udi, DBUS_INTERFACE_PROPS, "GetAll");
+
+ Q_FOREACH (const QString & iface, m_interfaces) {
+ if (iface.startsWith("org.freedesktop.DBus"))
+ continue;
+ call.setArguments(QVariantList() << 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();
+ const QString key = i.key();
+ m_cache.insert(key, i.value()); // replace the value
+ changeMap.insert(key, Solid::GenericInterface::PropertyModified);
+ qDebug() << "\t modified:" << key << ":" << m_cache.value(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 QCoreApplication::translate("", "You are not authorized to perform this operation");
+ else if (error == UD2_ERROR_BUSY)
+ return QCoreApplication::translate("", "The device is currently busy");
+ else if (error == UD2_ERROR_FAILED)
+ return QCoreApplication::translate("", "The requested operation has failed");
+ else if (error == UD2_ERROR_CANCELED)
+ return QCoreApplication::translate("", "The requested operation has been canceled");
+ else if (error == UD2_ERROR_INVALID_OPTION)
+ return QCoreApplication::translate("", "An invalid or malformed option has been given");
+ else if (error == UD2_ERROR_MISSING_DRIVER)
+ return QCoreApplication::translate("", "The kernel driver for this filesystem type is not available");
+ else if (error == UD2_ERROR_ALREADY_MOUNTED)
+ return QCoreApplication::translate("", "The device is already mounted");
+ else if (error == UD2_ERROR_NOT_MOUNTED)
+ return QCoreApplication::translate("", "The device is not mounted");
+ else if (error == UD2_ERROR_MOUNTED_BY_OTHER_USER)
+ return QCoreApplication::translate("", "The device is mounted by another user");
+ else if (error == UD2_ERROR_ALREADY_UNMOUNTING)
+ return QCoreApplication::translate("", "The device is already unmounting");
+ else if (error == UD2_ERROR_TIMED_OUT)
+ return QCoreApplication::translate("", "The operation timed out");
+ else if (error == UD2_ERROR_WOULD_WAKEUP)
+ return QCoreApplication::translate("", "The operation would wake up a disk that is in a deep-sleep state");
+ else if (error == UD2_ERROR_ALREADY_CANCELLED)
+ return QCoreApplication::translate("", "The operation has already been canceled");
+ else
+ return QCoreApplication::translate("", "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
+{
+ const QString drv = drivePath();
+ if (drv.isEmpty() || drv == "/")
+ return false;
+
+ Device drive(drv);
+ return drive.prop("Optical").toBool();
+}
+
+bool Device::mightBeOpticalDisc() const
+{
+ const QString drv = drivePath();
+ if (drv.isEmpty() || drv == "/")
+ return false;
+
+ Device drive(drv);
+ 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);
+}
+
+bool Device::isLoop() const
+{
+ return hasInterface(UD2_DBUS_INTERFACE_LOOP);
+}
+
+QString Device::drivePath() const
+{
+ return prop("Drive").value<QDBusObjectPath>().path();
+}
diff --git a/solid/solid/backends/udisks2/udisksdevice.h b/solid/solid/backends/udisks2/udisksdevice.h
new file mode 100644
index 0000000..7e27634
--- /dev/null
+++ b/solid/solid/backends/udisks2/udisksdevice.h
@@ -0,0 +1,113 @@
+/*
+ Copyright 2010 Michael Zanetti <mzanetti@kde.org>
+ Copyright 2010-2012 Lukáš Tinkl <ltinkl@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;
+ bool isLoop() const;
+
+ QString drivePath() 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/solid/solid/backends/udisks2/udisksdeviceinterface.cpp b/solid/solid/backends/udisks2/udisksdeviceinterface.cpp
new file mode 100644
index 0000000..9fa60e5
--- /dev/null
+++ b/solid/solid/backends/udisks2/udisksdeviceinterface.cpp
@@ -0,0 +1,33 @@
+/*
+ Copyright 2010 Michael Zanetti <mzanetti@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/solid/solid/backends/udisks2/udisksdeviceinterface.h b/solid/solid/backends/udisks2/udisksdeviceinterface.h
new file mode 100644
index 0000000..43a1b6f
--- /dev/null
+++ b/solid/solid/backends/udisks2/udisksdeviceinterface.h
@@ -0,0 +1,148 @@
+/*
+ Copyright 2010 Michael Zanetti <mzanetti@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/solid/solid/backends/udisks2/udisksgenericinterface.cpp b/solid/solid/backends/udisks2/udisksgenericinterface.cpp
new file mode 100644
index 0000000..2d8cea2
--- /dev/null
+++ b/solid/solid/backends/udisks2/udisksgenericinterface.cpp
@@ -0,0 +1,53 @@
+/*
+ Copyright 2009 Pino Toscano <pino@kde.org>
+ Copyright 2012 Lukáš Tinkl <ltinkl@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/solid/solid/backends/udisks2/udisksgenericinterface.h b/solid/solid/backends/udisks2/udisksgenericinterface.h
new file mode 100644
index 0000000..d225f32
--- /dev/null
+++ b/solid/solid/backends/udisks2/udisksgenericinterface.h
@@ -0,0 +1,57 @@
+/*
+ Copyright 2009 Pino Toscano <pino@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/solid/solid/backends/udisks2/udisksmanager.cpp b/solid/solid/backends/udisks2/udisksmanager.cpp
new file mode 100644
index 0000000..fab5208
--- /dev/null
+++ b/solid/solid/backends/udisks2/udisksmanager.cpp
@@ -0,0 +1,269 @@
+/*
+ Copyright 2012 Lukáš Tinkl <ltinkl@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/QCoreApplication>
+#include <QtCore/QDebug>
+#include <QtDBus>
+#include <QtXml/QDomDocument>
+
+#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(QCoreApplication::translate("", "Storage"));
+ root->setDescription(QCoreApplication::translate("", "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();
+
+#if 0
+ 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();
+ }
+
+#endif
+
+ introspect("/org/freedesktop/UDisks2/block_devices", true /*checkOptical*/);
+ introspect("/org/freedesktop/UDisks2/drives");
+
+ return m_deviceCache;
+}
+
+void Manager::introspect(const QString & path, bool checkOptical)
+{
+ QDBusMessage call = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, path,
+ DBUS_INTERFACE_INTROSPECT, "Introspect");
+ QDBusPendingReply<QString> reply = QDBusConnection::systemBus().asyncCall(call);
+ reply.waitForFinished();
+
+ if (reply.isValid()) {
+ QDomDocument dom;
+ dom.setContent(reply.value());
+ QDomNodeList nodeList = dom.documentElement().elementsByTagName("node");
+ for (int i = 0; i < nodeList.count(); i++) {
+ QDomElement nodeElem = nodeList.item(i).toElement();
+ if (!nodeElem.isNull() && nodeElem.hasAttribute("name")) {
+ const QString udi = path + "/" + nodeElem.attribute("name");
+
+ if (checkOptical) {
+ 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
+ qWarning() << "Failed enumerating UDisks2 objects:" << reply.error().name() << "\n" << reply.error().message();
+}
+
+QSet< Solid::DeviceInterface::Type > Manager::supportedInterfaces() const
+{
+ return m_supportedInterfaces;
+}
+
+QString Manager::udiPrefix() const
+{
+ return UD2_UDI_DISKS_PREFIX;
+}
+
+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));
+
+ if (!properties.contains("Size")) // react only on Size changes
+ return;
+
+ 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/solid/solid/backends/udisks2/udisksmanager.h b/solid/solid/backends/udisks2/udisksmanager.h
new file mode 100644
index 0000000..fb929ce
--- /dev/null
+++ b/solid/solid/backends/udisks2/udisksmanager.h
@@ -0,0 +1,70 @@
+/*
+ Copyright 2010 Michael Zanetti <mzanetti@kde.org>
+ Copyright 2010-2012 Lukáš Tinkl <ltinkl@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();
+ void introspect(const QString & path, bool checkOptical = false);
+ QSet<Solid::DeviceInterface::Type> m_supportedInterfaces;
+ org::freedesktop::DBus::ObjectManager m_manager;
+ QStringList m_deviceCache;
+};
+
+}
+}
+}
+#endif // UDISKS2MANAGER_H
diff --git a/solid/solid/backends/udisks2/udisksopticaldisc.cpp b/solid/solid/backends/udisks2/udisksopticaldisc.cpp
new file mode 100644
index 0000000..dc5256d
--- /dev/null
+++ b/solid/solid/backends/udisks2/udisksopticaldisc.cpp
@@ -0,0 +1,297 @@
+/*
+ Copyright 2010 Michael Zanetti <mzanetti@kde.org>
+ Copyright 2010 - 2012 Lukáš Tinkl <ltinkl@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 <QtCore/QMap>
+#include <QtCore/QMutexLocker>
+#include <QtDBus/QDBusConnection>
+
+#include "../shared/udevqt.h"
+
+#include "udisks2.h"
+#include "udisksopticaldisc.h"
+#include "soliddefs_p.h"
+
+typedef QMap<QByteArray, Solid::OpticalDisc::ContentTypes> ContentTypesCache;
+SOLID_GLOBAL_STATIC(ContentTypesCache, cache)
+SOLID_GLOBAL_STATIC(QMutex, cacheLock)
+
+// 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 *dev)
+ : StorageVolume(dev), m_needsReprobe(true), m_cachedContent(Solid::OpticalDisc::NoContent)
+{
+ UdevQt::Client client(this);
+ m_udevDevice = client.deviceByDeviceFile(device());
+ //qDebug() << "udev device:" << m_udevDevice.name() << "valid:" << m_udevDevice.isValid();
+ /*qDebug() << "\tProperties:" << */ m_udevDevice.deviceProperties(); // initialize the properties DB so that it doesn't crash further down, #298416
+
+ 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
+{
+ //qDebug() << "appendable prop" << m_udevDevice.deviceProperty("ID_CDROM_MEDIA_STATE");
+ 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) {
+ QMutexLocker lock(cacheLock);
+
+ const QByteArray deviceFile = m_device->prop("Device").toByteArray();
+
+ if (cache->contains(deviceFile)) {
+ m_cachedContent = cache->value(deviceFile);
+ m_needsReprobe = false;
+ return m_cachedContent;
+ }
+
+ 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(deviceFile);
+ }
+ if ( hasAudio )
+ m_cachedContent |= Solid::OpticalDisc::Audio;
+
+ m_needsReprobe = false;
+ cache->insert(deviceFile, m_cachedContent);
+ }
+
+ 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")) {
+ QMutexLocker lock(cacheLock);
+ m_needsReprobe = true;
+ m_cachedContent = Solid::OpticalDisc::NoContent;
+ cache->remove(m_device->prop("Device").toByteArray());
+ }
+}
+
+QString OpticalDisc::media() const
+{
+ return m_drive->prop("Media").toString();
+}
diff --git a/solid/solid/backends/udisks2/udisksopticaldisc.h b/solid/solid/backends/udisks2/udisksopticaldisc.h
new file mode 100644
index 0000000..0cdcc66
--- /dev/null
+++ b/solid/solid/backends/udisks2/udisksopticaldisc.h
@@ -0,0 +1,69 @@
+/*
+ Copyright 2010 Michael Zanetti <mzanetti@kde.org>
+ Copyright 2010 - 2012 Lukáš Tinkl <ltinkl@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/udevqt.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 *dev);
+ 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/solid/solid/backends/udisks2/udisksopticaldrive.cpp b/solid/solid/backends/udisks2/udisksopticaldrive.cpp
new file mode 100644
index 0000000..f4351a7
--- /dev/null
+++ b/solid/solid/backends/udisks2/udisksopticaldrive.cpp
@@ -0,0 +1,222 @@
+/*
+ Copyright 2010 Michael Zanetti <mzanetti@kde.org>
+ Copyright 2010-2012 Lukáš Tinkl <ltinkl@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"
+#include "dbus/manager.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");
+
+ const QString path = m_device->udi();
+ QDBusConnection c = QDBusConnection::systemBus();
+
+ // if the device is mounted, unmount first
+ QString blockPath;
+ org::freedesktop::DBus::ObjectManager manager(UD2_DBUS_SERVICE, UD2_DBUS_PATH, c);
+ QDBusPendingReply<DBUSManagerStruct> reply = manager.GetManagedObjects();
+ reply.waitForFinished();
+ if (!reply.isError()) { // enum devices
+ Q_FOREACH(const QDBusObjectPath &objPath, reply.value().keys()) {
+ const QString udi = objPath.path();
+
+ //qDebug() << "Inspecting" << udi;
+
+ if (udi == UD2_DBUS_PATH_MANAGER || udi == UD2_UDI_DISKS_PREFIX || udi.startsWith(UD2_DBUS_PATH_JOBS))
+ continue;
+
+ Device device(udi);
+ if (device.drivePath() == path && device.isMounted()) {
+ //qDebug() << "Got mounted block device:" << udi;
+ blockPath = udi;
+ break;
+ }
+ }
+ }
+ else // show error
+ {
+ qWarning() << "Failed enumerating UDisks2 objects:" << reply.error().name() << "\n" << reply.error().message();
+ }
+
+ if (!blockPath.isEmpty()) {
+ //qDebug() << "Calling unmount on" << blockPath;
+ QDBusMessage msg = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, blockPath, UD2_DBUS_INTERFACE_FILESYSTEM, "Unmount");
+ msg << QVariantMap(); // options, unused now
+ c.call(msg, QDBus::BlockWithGui);
+ }
+
+ 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/solid/solid/backends/udisks2/udisksopticaldrive.h b/solid/solid/backends/udisks2/udisksopticaldrive.h
new file mode 100644
index 0000000..4c98ef5
--- /dev/null
+++ b/solid/solid/backends/udisks2/udisksopticaldrive.h
@@ -0,0 +1,81 @@
+/*
+ Copyright 2010 Michael Zanetti <mzanetti@kde.org>
+ Copyright 2010-2012 Lukáš Tinkl <ltinkl@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/solid/solid/backends/udisks2/udisksstorageaccess.cpp b/solid/solid/backends/udisks2/udisksstorageaccess.cpp
new file mode 100644
index 0000000..f28540b
--- /dev/null
+++ b/solid/solid/backends/udisks2/udisksstorageaccess.cpp
@@ -0,0 +1,362 @@
+/*
+ Copyright 2009 Pino Toscano <pino@kde.org>
+ Copyright 2009-2012 Lukáš Tinkl <ltinkl@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)
+{
+ connect(device, SIGNAL(changed()), this, SLOT(checkAccessibility()));
+ updateCache();
+
+ // 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 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::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) // we've got a response from Unlock
+ 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
+ {
+ // 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 != "/")
+ {
+ Device drive(drivePath);
+ if (drive.prop("Ejectable").toBool() &&
+ drive.prop("MediaAvailable").toBool() &&
+ !m_device->isOpticalDisc()) // optical drives have their Eject method
+ {
+ 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;
+ //qDebug() << "SETUP REQUESTED:" << m_device->udi();
+ Q_EMIT setupRequested(m_device->udi());
+}
+
+void StorageAccess::slotSetupDone(int error, const QString &errorString)
+{
+ m_setupInProgress = false;
+ //qDebug() << "SETUP DONE:" << m_device->udi();
+ Q_EMIT setupDone(static_cast<Solid::ErrorType>(error), errorString, m_device->udi());
+
+ checkAccessibility();
+}
+
+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());
+
+ checkAccessibility();
+}
+
+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");
+ QVariantMap options;
+
+ if (m_device->prop("IdType").toString() == "vfat")
+ options.insert("options", "flush");
+
+ msg << options;
+
+ 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;
+ 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/solid/solid/backends/udisks2/udisksstorageaccess.h b/solid/solid/backends/udisks2/udisksstorageaccess.h
new file mode 100644
index 0000000..2901067
--- /dev/null
+++ b/solid/solid/backends/udisks2/udisksstorageaccess.h
@@ -0,0 +1,104 @@
+/*
+ Copyright 2009 Pino Toscano <pino@kde.org>
+ Copyright 2009-2012 Lukáš Tinkl <ltinkl@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 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);
+
+ void checkAccessibility();
+
+private:
+ /// @return true if this device is luks and unlocked
+ bool isLuksDevice() const;
+
+ void updateCache();
+
+ 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/solid/solid/backends/udisks2/udisksstoragedrive.cpp b/solid/solid/backends/udisks2/udisksstoragedrive.cpp
new file mode 100644
index 0000000..e382154
--- /dev/null
+++ b/solid/solid/backends/udisks2/udisksstoragedrive.cpp
@@ -0,0 +1,147 @@
+/*
+ Copyright 2010 Michael Zanetti <mzanetti@kde.org>
+ Copyright 2010-2012 Lukáš Tinkl <ltinkl@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/udevqt.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QFile>
+
+using namespace Solid::Backends::UDisks2;
+
+StorageDrive::StorageDrive(Device *dev)
+ : Block(dev)
+{
+ UdevQt::Client client(this);
+ m_udevDevice = client.deviceByDeviceFile(device());
+ m_udevDevice.deviceProperties();
+}
+
+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();
+
+ //qDebug() << "bus:" << bus << "udev bus:" << udevBus;
+
+ 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/solid/solid/backends/udisks2/udisksstoragedrive.h b/solid/solid/backends/udisks2/udisksstoragedrive.h
new file mode 100644
index 0000000..d8c1046
--- /dev/null
+++ b/solid/solid/backends/udisks2/udisksstoragedrive.h
@@ -0,0 +1,61 @@
+/*
+ Copyright 2010 Michael Zanetti <mzanetti@kde.org>
+ Copyright 2010-2012 Lukáš Tinkl <ltinkl@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/udevqt.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 *dev);
+ 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/solid/solid/backends/udisks2/udisksstoragevolume.cpp b/solid/solid/backends/udisks2/udisksstoragevolume.cpp
new file mode 100644
index 0000000..a7d8fad
--- /dev/null
+++ b/solid/solid/backends/udisks2/udisksstoragevolume.cpp
@@ -0,0 +1,105 @@
+/*
+ Copyright 2010 Michael Zanetti <mzanetti@kde.org>
+ Copyright 2010-2012 Lukáš Tinkl <ltinkl@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/solid/solid/backends/udisks2/udisksstoragevolume.h b/solid/solid/backends/udisks2/udisksstoragevolume.h
new file mode 100644
index 0000000..2ca04d2
--- /dev/null
+++ b/solid/solid/backends/udisks2/udisksstoragevolume.h
@@ -0,0 +1,57 @@
+/*
+ Copyright 2010 Michael Zanetti <mzanetti@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/solid/solid/managerbase.cpp b/solid/solid/managerbase.cpp
index fb5a67c..d58736e 100644
--- a/solid/solid/managerbase.cpp
+++ b/solid/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_WS_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/solid/tests/CMakeLists.txt b/solid/tests/CMakeLists.txt
index ef507d1..b9f3720 100644
--- a/solid/tests/CMakeLists.txt
+++ b/solid/tests/CMakeLists.txt
@@ -15,21 +15,6 @@ endif(WIN32)
target_link_libraries(fakehardwaretest solid_static ${QT_QTCORE_LIBRARY} ${QT_QTDBUS_LIBRARY} ${QT_QTXML_LIBRARY} ${QT_QTTEST_LIBRARY} )
add_definitions(-DTEST_DATA="\\"${CMAKE_CURRENT_SOURCE_DIR}/../solid/backends/fakehw/fakecomputer.xml\\"")
-
-########### halbasictest ###############
-
-if(NOT WIN32 AND NOT APPLE)
-set(halbasictest_SRCS halbasictest.cpp )
-
-kde4_add_executable(halbasictest ${halbasictest_SRCS})
-
-if(WIN32)
- set_target_properties(halbasictest PROPERTIES COMPILE_FLAGS -DSOLID_EXPORT=)
-endif(WIN32)
-
-target_link_libraries(halbasictest solid_static ${KDEWIN_LIBRARIES} ${QT_QTCORE_LIBRARY} ${QT_QTDBUS_LIBRARY} ${QT_QTXML_LIBRARY} ${QT_QTTEST_LIBRARY} )
-endif(NOT WIN32 AND NOT APPLE)
-
########### solidhwtest ###############
set(solidhwtest_SRCS