diff --git a/solid/solid/CMakeLists.txt b/solid/solid/CMakeLists.txt index 0aa7a43..b00e50a 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,39 @@ 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 - ) + + if ( WITH_SOLID_UDISKS2 ) + message(STATUS "Building Solid UDisks2 backend." ) + add_definitions(-DWITH_SOLID_UDISKS2) + set(solid_LIB_SRCS ${solid_LIB_SRCS} + backends/udisks2/udisksmanager.cpp + backends/udisks2/udisksdevice.cpp + backends/udisks2/udisksdevicebackend.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 + ) + else ( WITH_SOLID_UDISKS2 ) + 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 + ) + endif ( WITH_SOLID_UDISKS2 ) 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 +#include +#include +#include +#include +#include +#include +#include + +#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 GetManagedObjects() + { + QList 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 @@ + + + + + + + + + + + + + + + + + + + + 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 + + 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 . +*/ + +#ifndef SOLID_BACKENDS_UDISKS2_H +#define SOLID_BACKENDS_UDISKS2_H + +#include +#include +#include +#include +#include + +typedef QList QByteArrayList; +Q_DECLARE_METATYPE(QByteArrayList) + +typedef QMap QVariantMapMap; +Q_DECLARE_METATYPE(QVariantMapMap) + +typedef QMap 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 + + 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 . +*/ + +#include + +#include +#include +#include +#include + +#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 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 + + 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 . +*/ + +#ifndef UDISKS2BLOCK_H +#define UDISKS2BLOCK_H + +#include +#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..b888360 --- /dev/null +++ b/solid/solid/backends/udisks2/udisksdevice.cpp @@ -0,0 +1,834 @@ +/* + Copyright 2010 Michael Zanetti + Copyright 2010-2012 Lukáš Tinkl + + 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 . +*/ + +#include "udisksdevice.h" +#include "udisksdevicebackend.h" +#include "udisksblock.h" +#include "udisksdeviceinterface.h" +#include "udisksstoragevolume.h" +#include "udisksopticaldisc.h" +#include "udisksopticaldrive.h" +#include "udisksstorageaccess.h" +#include "udisksgenericinterface.h" + +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + +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_backend(DeviceBackend::backendForUDI(udi)) +{ + if (m_backend) { + connect(m_backend, SIGNAL(changed()), this, SIGNAL(changed())); + connect(m_backend, SIGNAL(propertyChanged(QMap)), this, SIGNAL(propertyChanged(QMap))); + } else { + qDebug() << "Created invalid Device for udi" << udi; + } +} + +Device::~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(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(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(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(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(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 Drive", "%1 is the size").arg(size_str); + else + description = QCoreApplication::translate("", "Encrypted Drive"); + } + 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(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 +{ + if (!isDrive()) { + Device drive(drivePath()); + return drive.prop("Model").toString(); + } + + return prop("Model").toString(); +} + +QString Device::vendor() const +{ + if (!isDrive()) { + Device drive(drivePath()); + return drive.prop("Vendor").toString(); + } + + return prop("Vendor").toString(); +} + +QString Device::udi() const +{ + if (m_backend) { + return m_backend->udi; + } + + return QString(); +} + +QString Device::parentUdi() const +{ + QString parent; + + if (propertyExists("Drive")) // block + parent = prop("Drive").value().path(); + else if (propertyExists("Table")) // partition + parent = prop("Table").value().path(); + else if (parent.isEmpty() || parent=="/") { + parent = UD2_UDI_DISKS_PREFIX; + } + return parent; +} + +QVariant Device::prop(const QString &key) const +{ + if (m_backend) { + return m_backend->prop(key); + } + + return QVariant(); +} + +bool Device::propertyExists(const QString &key) const +{ + if (m_backend) { + return m_backend->propertyExists(key); + } + + return false; +} + +QVariantMap Device::allProperties() const +{ + if (m_backend) { + return m_backend->allProperties(); + } + + return QVariantMap(); +} + +bool Device::hasInterface(const QString &name) const +{ + if (m_backend) { + return m_backend->interfaces().contains(name); + } + + return false; +} + +QStringList Device::interfaces() const +{ + if (m_backend) { + return m_backend->interfaces(); + } + + return QStringList(); +} + +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(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().path(); +} diff --git a/solid/solid/backends/udisks2/udisksdevice.h b/solid/solid/backends/udisks2/udisksdevice.h new file mode 100644 index 0000000..90bb042 --- /dev/null +++ b/solid/solid/backends/udisks2/udisksdevice.h @@ -0,0 +1,103 @@ +/* + Copyright 2010 Michael Zanetti + Copyright 2010-2012 Lukáš Tinkl + + 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 . +*/ + +#ifndef UDISKS2DEVICE_H +#define UDISKS2DEVICE_H + +#include "udisks2.h" + +#include +#include +#include + +#include +#include +#include + +namespace Solid +{ +namespace Backends +{ +namespace UDisks2 +{ + +class DeviceBackend; + +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 &changes); + +private: + QString storageDescription() const; + QString volumeDescription() const; + + DeviceBackend *m_backend; +}; + +} +} +} + +#endif // UDISKS2DEVICE_H diff --git a/solid/solid/backends/udisks2/udisksdevicebackend.cpp b/solid/solid/backends/udisks2/udisksdevicebackend.cpp new file mode 100644 index 0000000..ffa98db --- /dev/null +++ b/solid/solid/backends/udisks2/udisksdevicebackend.cpp @@ -0,0 +1,205 @@ +/* + Copyright 2010 Michael Zanetti + Copyright 2010-2012 Lukáš Tinkl + Copyright 2012 Dan Vrátil + + 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 . +*/ + +#include "udisksdevicebackend.h" + +#include +#include +#include + +#include "solid/deviceinterface.h" +#include "solid/genericinterface.h" + +using namespace Solid::Backends::UDisks2; + +/* Static cache for DeviceBackends for all UDIs */ +QMap DeviceBackend::s_backends; + +DeviceBackend* DeviceBackend::backendForUDI(const QString& udi) +{ + DeviceBackend *backend = 0; + if (udi.isEmpty()) { + return backend; + } + + if (s_backends.contains(udi)) { + backend = s_backends.value(udi); + } else { + backend = new DeviceBackend(udi); + s_backends.insert(udi, backend); + } + + return backend; +} + +DeviceBackend::DeviceBackend(const QString& udi) + : udi(udi) +{ + qDebug() << "Creating backend for device" << udi; + m_device = new QDBusInterface(UD2_DBUS_SERVICE, udi, + QString(), // no interface, we aggregate them + QDBusConnection::systemBus(), this); + + if (m_device->isValid()) { + QDBusConnection::systemBus().connect(UD2_DBUS_SERVICE, 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(); + } +} + +DeviceBackend::~DeviceBackend() +{ +} + +void DeviceBackend::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")); + } +} + +QStringList DeviceBackend::interfaces() const +{ + return m_interfaces; +} + + +QString DeviceBackend::introspect() const +{ + QDBusMessage call = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, udi, + DBUS_INTERFACE_INTROSPECT, "Introspect"); + QDBusPendingReply reply = QDBusConnection::systemBus().call(call); + + if (reply.isValid()) + return reply.value(); + else { + return QString(); + } +} + +QVariant DeviceBackend::prop(const QString& key) +{ + checkCache(key); + return m_propertyCache.value(key); +} + +bool DeviceBackend::propertyExists(const QString& key) +{ + checkCache(key); + return m_propertyCache.contains(key); +} + + +QVariantMap DeviceBackend::allProperties() const +{ + QDBusMessage call = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, udi, DBUS_INTERFACE_PROPS, "GetAll"); + + Q_FOREACH (const QString & iface, m_interfaces) { + if (iface.startsWith("org.freedesktop.DBus")) { + continue; + } + + call.setArguments(QVariantList() << iface); + QDBusPendingReply reply = QDBusConnection::systemBus().call(call); + + if (reply.isValid()) { + m_propertyCache.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_propertyCache; +} + +void DeviceBackend::checkCache(const QString& key) const +{ + if (m_propertyCache.isEmpty()) { // recreate the cache + allProperties(); + } + + if (m_propertyCache.contains(key)) { + return; + } + + QVariant reply = m_device->property(key.toUtf8()); + + if (reply.isValid()) { + m_propertyCache.insert(key, reply); + } else { + qWarning() << "got invalid reply for cache:" << key; + } +} + +void DeviceBackend::slotPropertiesChanged(const QString& ifaceName, const QVariantMap& changedProps, const QStringList& invalidatedProps) +{ + qDebug() << udi << "'s interface" << ifaceName << "changed props:"; + + QMap changeMap; + + Q_FOREACH(const QString & key, invalidatedProps) { + m_propertyCache.remove(key); + changeMap.insert(key, Solid::GenericInterface::PropertyRemoved); + qDebug() << "\t invalidated:" << key; + } + + QMapIterator i(changedProps); + while (i.hasNext()) { + i.next(); + const QString key = i.key(); + m_propertyCache.insert(key, i.value()); // replace the value + changeMap.insert(key, Solid::GenericInterface::PropertyModified); + qDebug() << "\t modified:" << key << ":" << m_propertyCache.value(key); + } + + Q_EMIT propertyChanged(changeMap); + Q_EMIT changed(); +} + +void DeviceBackend::slotInterfacesAdded(const QDBusObjectPath& object_path, const QVariantMapMap& interfaces_and_properties) +{ + if (object_path.path() == udi) { + m_interfaces.append(interfaces_and_properties.keys()); + } +} + +void DeviceBackend::slotInterfacesRemoved(const QDBusObjectPath& object_path, const QStringList& interfaces) +{ + if (object_path.path() == udi) { + Q_FOREACH(const QString & iface, interfaces) { + m_interfaces.removeAll(iface); + } + } +} diff --git a/solid/solid/backends/udisks2/udisksdevicebackend.h b/solid/solid/backends/udisks2/udisksdevicebackend.h new file mode 100644 index 0000000..4953ad5 --- /dev/null +++ b/solid/solid/backends/udisks2/udisksdevicebackend.h @@ -0,0 +1,83 @@ +/* + Copyright 2010 Michael Zanetti + Copyright 2010-2012 Lukáš Tinkl + Copyright 2012 Dan Vrátil + + 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 . +*/ + +#ifndef UDISKSDEVICEBACKEND_H +#define UDISKSDEVICEBACKEND_H + +#include +#include +#include +#include +#include + +#include "udisks2.h" + +namespace Solid { +namespace Backends { +namespace UDisks2 { + +class DeviceBackend: public QObject { + + Q_OBJECT + + public: + static DeviceBackend* backendForUDI(const QString &udi); + + DeviceBackend(const QString &udi); + ~DeviceBackend(); + + void initInterfaces(); + QString introspect() const; + + QVariant prop(const QString &key); + bool propertyExists(const QString &key); + QVariantMap allProperties() const; + void checkCache(const QString &key) const; + + QStringList interfaces() const; + + QString udi; + + Q_SIGNALS: + void propertyChanged(const QMap &changeMap); + void changed(); + + private Q_SLOTS: + void slotInterfacesAdded(const QDBusObjectPath &object_path, const QVariantMapMap &interfaces_and_properties); + void slotInterfacesRemoved(const QDBusObjectPath &object_path, const QStringList &interfaces); + void slotPropertiesChanged(const QString &ifaceName, const QVariantMap &changedProps, const QStringList &invalidatedProps); + + private: + QDBusInterface *m_device; + + mutable QVariantMap m_propertyCache; + QStringList m_interfaces; + + static QMap s_backends; + +}; + +} /* namespace UDisks2 */ +} /* namespace Backends */ +} /* namespace Solid */ + +#endif /* UDISKSDEVICEBACKEND_H */ \ No newline at end of file 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 + + 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 . +*/ + +#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 + + 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 . +*/ + +#ifndef UDISKS2DEVICEINTERFACE_H +#define UDISKS2DEVICEINTERFACE_H + +#include +#include "udisksdevice.h" + +#include +#include + +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 + Copyright 2012 Lukáš Tinkl + + 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 . +*/ + +#include "udisksgenericinterface.h" + +#include "udisksdevice.h" + +using namespace Solid::Backends::UDisks2; + +GenericInterface::GenericInterface(Device *device) + : DeviceInterface(device) +{ + connect(device, SIGNAL(propertyChanged(QMap)), + this, SIGNAL(propertyChanged(QMap))); +} + +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 + + 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 . +*/ + +#ifndef SOLID_BACKENDS_UDISKS2_GENERICINTERFACE_H +#define SOLID_BACKENDS_UDISKS2_GENERICINTERFACE_H + +#include +#include +#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 &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..69e053f --- /dev/null +++ b/solid/solid/backends/udisks2/udisksmanager.cpp @@ -0,0 +1,238 @@ +/* + Copyright 2012 Lukáš Tinkl + + 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 . +*/ + +#include "udisksmanager.h" + +#include +#include +#include +#include + +#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 >(); + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); + + 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 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() +{ + QDBusConnection::systemBus().disconnectFromBus("Solid::UDisks2"); +} + +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(); + + 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 reply = QDBusConnection::systemBus().call(call); + + 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(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 + Copyright 2010-2012 Lukáš Tinkl + + 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 . +*/ + +#ifndef UDISKS2MANAGER_H +#define UDISKS2MANAGER_H + +#include "udisks2.h" +#include "udisksdevice.h" +#include "dbus/manager.h" + +#include "solid/ifaces/devicemanager.h" + +#include +#include + +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 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 + Copyright 2010 - 2012 Lukáš Tinkl + + 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 . +*/ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "../shared/udevqt.h" + +#include "udisks2.h" +#include "udisksopticaldisc.h" +#include "soliddefs_p.h" + +typedef QMap 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().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 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 + Copyright 2010 - 2012 Lukáš Tinkl + + 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 . +*/ + +#ifndef UDISKS2OPTICALDISC_H +#define UDISKS2OPTICALDISC_H + +#include + +#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..74a901e --- /dev/null +++ b/solid/solid/backends/udisks2/udisksopticaldrive.cpp @@ -0,0 +1,226 @@ +/* + Copyright 2010 Michael Zanetti + Copyright 2010-2012 Lukáš Tinkl + + 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 . +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#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 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(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 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 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 + Copyright 2010-2012 Lukáš Tinkl + + 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 . +*/ + +#ifndef UDISKS2OPTICALDRIVE_H +#define UDISKS2OPTICALDRIVE_H + +#include +#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 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 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..6958459 --- /dev/null +++ b/solid/solid/backends/udisks2/udisksstorageaccess.cpp @@ -0,0 +1,390 @@ +/* + Copyright 2009 Pino Toscano + Copyright 2009-2012 Lukáš Tinkl + + 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 . +*/ + +#include "udisksstorageaccess.h" +#include "udisks2.h" + +#include +#include +#include +#include + +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 + const QString path = clearTextPath(); + //qDebug() << Q_FUNC_INFO << "CLEARTEXT device path: " << path; + if (path.isEmpty() || path == "/") + return false; + Device holderDevice(path); + return holderDevice.isMounted(); + } + + return m_device->isMounted(); +} + +QString StorageAccess::filePath() const +{ + QByteArrayList mntPoints; + + if (isLuksDevice()) { // encrypted (and unlocked) device + const QString path = clearTextPath(); + if (path.isEmpty() || path == "/") + return QString(); + Device holderDevice(path); + mntPoints = qdbus_cast(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(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(); +} + +bool StorageAccess::setup() +{ + if ( m_teardownInProgress || m_setupInProgress ) + return false; + m_setupInProgress = true; + m_device->broadcastActionRequested("setup"); + + if (m_device->isEncryptedContainer() && clearTextPath().isEmpty()) + 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, m_device->udi()); + } +} + +void StorageAccess::slotDBusReply( const QDBusMessage & /*reply*/ ) +{ + const QString ctPath = clearTextPath(); + if (m_setupInProgress) + { + if (isLuksDevice() && !isAccessible()) { // unlocked device, now mount it + 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() && !ctPath.isEmpty() && ctPath != "/") // unlocked device, lock it + { + callCryptoTeardown(); + } + else if (!ctPath.isEmpty() && ctPath != "/") { + 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->drivePath(); + 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 ) +{ + //qDebug() << Q_FUNC_INFO << "DBUS ERROR:" << error.name() << error.message(); + + 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_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(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; + Q_EMIT teardownDone(static_cast(error), errorString, m_device->udi()); + + checkAccessibility(); +} + +bool StorageAccess::mount() +{ + QString path = m_device->udi(); + const QString ctPath = clearTextPath(); + + if (isLuksDevice() && !ctPath.isEmpty()) { // mount options for the cleartext volume + path = ctPath; + } + + 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(); + const QString ctPath = clearTextPath(); + + if (isLuksDevice() && !ctPath.isEmpty()) { // unmount options for the cleartext volume + path = ctPath; + } + + 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++); +} + +QString StorageAccess::clearTextPath() const +{ + const QString prefix = "/org/freedesktop/UDisks2/block_devices"; + QDBusMessage call = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, prefix, + DBUS_INTERFACE_INTROSPECT, "Introspect"); + QDBusPendingReply 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 = prefix + "/" + nodeElem.attribute("name"); + Device holderDevice(udi); + + if (m_device->udi() == holderDevice.prop("CryptoBackingDevice").value().path()) { + //qDebug() << Q_FUNC_INFO << "CLEARTEXT device path: " << udi; + return udi; + } + } + } + } + + return QString(); +} + +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 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().path()) : m_device->udi(), + UD2_DBUS_INTERFACE_ENCRYPTED, "Lock"); + msg << QVariantMap(); // options, unused now + + 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..ec91f89 --- /dev/null +++ b/solid/solid/backends/udisks2/udisksstorageaccess.h @@ -0,0 +1,104 @@ +/* + Copyright 2009 Pino Toscano + Copyright 2009-2012 Lukáš Tinkl + + 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 . +*/ + +#ifndef UDISKS2STORAGEACCESS_H +#define UDISKS2STORAGEACCESS_H + +#include +#include "udisksdeviceinterface.h" + +#include +#include + +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(); + QString clearTextPath() const; + +private: + bool m_isAccessible; + bool m_setupInProgress; + bool m_teardownInProgress; + bool m_passphraseRequested; + QString m_lastReturnObject; + + 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 + Copyright 2010-2012 Lukáš Tinkl + + 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 . +*/ + +#include "udisksstoragedrive.h" + +#include "../shared/udevqt.h" + +#include +#include + +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 + Copyright 2010-2012 Lukáš Tinkl + + 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 . +*/ + +#ifndef UDISKS2STORAGEDRIVE_H +#define UDISKS2STORAGEDRIVE_H + +#include + +#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 + Copyright 2010-2012 Lukáš Tinkl + + 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 . +*/ + +#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().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 + + 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 . +*/ + +#ifndef UDISKS2STORAGEVOLUME_H +#define UDISKS2STORAGEVOLUME_H + +#include +#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..c7005ff 100644 --- a/solid/solid/managerbase.cpp +++ b/solid/solid/managerbase.cpp @@ -30,8 +30,11 @@ #if defined (Q_OS_MAC) #include "backends/iokit/iokitmanager.h" #elif defined (Q_OS_UNIX) -#include "backends/hal/halmanager.h" +#if defined (WITH_SOLID_UDISKS2) +#include "backends/udisks2/udisksmanager.h" +#else #include "backends/udisks/udisksmanager.h" +#endif #include "backends/upower/upowermanager.h" #if defined (HUPNP_FOUND) @@ -71,22 +74,17 @@ 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 +# if defined(WITH_SOLID_UDISKS2) + m_backends << new Solid::Backends::UDisks2::Manager(0) +# else m_backends << new Solid::Backends::UDisks::UDisksManager(0) +# endif << new Solid::Backends::UPower::UPowerManager(0) << new Solid::Backends::Fstab::FstabManager(0); - } # endif # if defined (HUPNP_FOUND) @@ -99,5 +97,3 @@ QList Solid::ManagerBasePrivate::managerBackends() const { return m_backends; } - - diff --git a/solid/tests/CMakeLists.txt b/solid/tests/CMakeLists.txt index ef507d1..9212741 100644 --- a/solid/tests/CMakeLists.txt +++ b/solid/tests/CMakeLists.txt @@ -16,20 +16,6 @@ target_link_libraries(fakehardwaretest solid_static ${QT_QTCORE_LIBRARY} ${QT_QT 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