271 lines
8.1 KiB
C++
271 lines
8.1 KiB
C++
/*
|
|
Copyright 2010 Michael Zanetti <mzanetti@kde.org>
|
|
Copyright 2010 Lukas Tinkl <ltinkl@redhat.com>
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) version 3, or any
|
|
later version accepted by the membership of KDE e.V. (or its
|
|
successor approved by the membership of KDE e.V.), which shall
|
|
act as a proxy defined in Section 6 of version 3 of the license.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "udisksmanager.h"
|
|
#include "udisks.h"
|
|
|
|
#include <QDBusReply>
|
|
#include <QDebug>
|
|
#include <QDBusMetaType>
|
|
#include <QDBusConnectionInterface>
|
|
|
|
#include "../shared/rootdevice.h"
|
|
|
|
using namespace Solid::Backends::UDisks;
|
|
using namespace Solid::Backends::Shared;
|
|
|
|
UDisksManager::UDisksManager(QObject *parent)
|
|
: Solid::Ifaces::DeviceManager(parent),
|
|
m_manager(UD_DBUS_SERVICE,
|
|
UD_DBUS_PATH,
|
|
UD_DBUS_INTERFACE_DISKS,
|
|
QDBusConnection::systemBus())
|
|
{
|
|
m_supportedInterfaces
|
|
<< Solid::DeviceInterface::GenericInterface
|
|
<< Solid::DeviceInterface::Block
|
|
<< Solid::DeviceInterface::StorageAccess
|
|
<< Solid::DeviceInterface::StorageDrive
|
|
<< Solid::DeviceInterface::OpticalDrive
|
|
<< Solid::DeviceInterface::OpticalDisc
|
|
<< Solid::DeviceInterface::StorageVolume;
|
|
|
|
qDBusRegisterMetaType<QList<QDBusObjectPath> >();
|
|
qDBusRegisterMetaType<QVariantMap>();
|
|
|
|
bool serviceFound = m_manager.isValid();
|
|
if (!serviceFound) {
|
|
// find out whether it will be activated automatically
|
|
QDBusMessage message = QDBusMessage::createMethodCall("org.freedesktop.DBus",
|
|
"/org/freedesktop/DBus",
|
|
"org.freedesktop.DBus",
|
|
"ListActivatableNames");
|
|
|
|
QDBusReply<QStringList> reply = QDBusConnection::systemBus().call(message);
|
|
if (reply.isValid() && reply.value().contains(UD_DBUS_SERVICE)) {
|
|
QDBusConnection::systemBus().interface()->startService(UD_DBUS_SERVICE);
|
|
serviceFound = true;
|
|
}
|
|
}
|
|
|
|
if (serviceFound) {
|
|
connect(&m_manager, SIGNAL(DeviceAdded(QDBusObjectPath)),
|
|
this, SLOT(slotDeviceAdded(QDBusObjectPath)));
|
|
connect(&m_manager, SIGNAL(DeviceRemoved(QDBusObjectPath)),
|
|
this, SLOT(slotDeviceRemoved(QDBusObjectPath)));
|
|
connect(&m_manager, SIGNAL(DeviceChanged(QDBusObjectPath)),
|
|
this, SLOT(slotDeviceChanged(QDBusObjectPath)));
|
|
}
|
|
}
|
|
|
|
UDisksManager::~UDisksManager()
|
|
{
|
|
|
|
}
|
|
|
|
QObject* UDisksManager::createDevice(const QString& udi)
|
|
{
|
|
if (udi==udiPrefix()) {
|
|
RootDevice *root = new RootDevice(udi);
|
|
|
|
root->setProduct(tr("Storage"));
|
|
root->setDescription(tr("Storage devices"));
|
|
root->setIcon("server-database"); // Obviously wasn't meant for that, but maps nicely in oxygen icon set :-p
|
|
|
|
return root;
|
|
|
|
} else if (deviceCache().contains(udi)) {
|
|
return new UDisksDevice(udi);
|
|
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
QStringList UDisksManager::devicesFromQuery(const QString& parentUdi, Solid::DeviceInterface::Type type)
|
|
{
|
|
QStringList result;
|
|
|
|
if (!parentUdi.isEmpty())
|
|
{
|
|
foreach (const QString &udi, deviceCache())
|
|
{
|
|
if (udi==udiPrefix())
|
|
continue;
|
|
|
|
UDisksDevice device(udi);
|
|
if (device.queryDeviceInterface(type) && device.parentUdi() == parentUdi)
|
|
result << udi;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
else if (type != Solid::DeviceInterface::Unknown)
|
|
{
|
|
foreach (const QString &udi, deviceCache())
|
|
{
|
|
if (udi==udiPrefix())
|
|
continue;
|
|
|
|
UDisksDevice device(udi);
|
|
if (device.queryDeviceInterface(type))
|
|
result << udi;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
return deviceCache();
|
|
}
|
|
|
|
QStringList UDisksManager::allDevices()
|
|
{
|
|
m_knownDrivesWithMedia.clear();
|
|
m_deviceCache.clear();
|
|
m_deviceCache << udiPrefix();
|
|
|
|
foreach(const QString &udi, allDevicesInternal())
|
|
{
|
|
m_deviceCache.append(udi);
|
|
|
|
UDisksDevice device(udi);
|
|
if (device.queryDeviceInterface(Solid::DeviceInterface::OpticalDrive)) // forge a special (separate) device for optical discs
|
|
{
|
|
if (device.prop("DeviceIsOpticalDisc").toBool())
|
|
{
|
|
if (!m_knownDrivesWithMedia.contains(udi))
|
|
m_knownDrivesWithMedia.append(udi);
|
|
m_deviceCache.append(udi + ":media");
|
|
}
|
|
}
|
|
}
|
|
|
|
return m_deviceCache;
|
|
}
|
|
|
|
QStringList UDisksManager::allDevicesInternal()
|
|
{
|
|
QDBusReply<QList<QDBusObjectPath> > reply = m_manager.call("EnumerateDevices");
|
|
|
|
if (!reply.isValid()) {
|
|
qWarning() << Q_FUNC_INFO << " error: " << reply.error().name();
|
|
return QStringList();
|
|
}
|
|
|
|
QStringList retList;
|
|
foreach(const QDBusObjectPath &path, reply.value()) {
|
|
retList << path.path();
|
|
}
|
|
|
|
return retList;
|
|
}
|
|
|
|
QSet< Solid::DeviceInterface::Type > UDisksManager::supportedInterfaces() const
|
|
{
|
|
return m_supportedInterfaces;
|
|
}
|
|
|
|
QString UDisksManager::udiPrefix() const
|
|
{
|
|
return UD_UDI_DISKS_PREFIX;
|
|
}
|
|
|
|
void UDisksManager::slotDeviceAdded(const QDBusObjectPath &opath)
|
|
{
|
|
const QString udi = opath.path();
|
|
|
|
if (!m_deviceCache.contains(udi)) {
|
|
m_deviceCache.append(udi);
|
|
}
|
|
|
|
UDisksDevice device(udi);
|
|
if (device.queryDeviceInterface(Solid::DeviceInterface::StorageDrive)
|
|
&& !device.prop("DeviceIsMediaAvailable").toBool()
|
|
&& !m_dirtyDevices.contains(udi))
|
|
m_dirtyDevices.append(udi);
|
|
|
|
emit deviceAdded(udi);
|
|
slotDeviceChanged(opath); // case: hotswap event (optical drive with media inside)
|
|
}
|
|
|
|
void UDisksManager::slotDeviceRemoved(const QDBusObjectPath &opath)
|
|
{
|
|
const QString udi = opath.path();
|
|
|
|
// case: hotswap event (optical drive with media inside)
|
|
if (m_knownDrivesWithMedia.contains(udi)) {
|
|
m_knownDrivesWithMedia.removeAll(udi);
|
|
m_deviceCache.removeAll(udi + ":media");
|
|
emit deviceRemoved(udi + ":media");
|
|
}
|
|
|
|
if (m_dirtyDevices.contains(udi))
|
|
m_dirtyDevices.removeAll(udi);
|
|
|
|
emit deviceRemoved(udi);
|
|
m_deviceCache.removeAll(opath.path());
|
|
}
|
|
|
|
void UDisksManager::slotDeviceChanged(const QDBusObjectPath &opath)
|
|
{
|
|
const QString udi = opath.path();
|
|
UDisksDevice device(udi);
|
|
|
|
if (device.queryDeviceInterface(Solid::DeviceInterface::OpticalDrive))
|
|
{
|
|
if (!m_knownDrivesWithMedia.contains(udi) && device.prop("DeviceIsOpticalDisc").toBool())
|
|
{
|
|
m_knownDrivesWithMedia.append(udi);
|
|
if (!m_deviceCache.isEmpty()) {
|
|
m_deviceCache.append(udi + ":media");
|
|
}
|
|
emit deviceAdded(udi + ":media");
|
|
}
|
|
|
|
if (m_knownDrivesWithMedia.contains(udi) && !device.prop("DeviceIsOpticalDisc").toBool())
|
|
{
|
|
m_knownDrivesWithMedia.removeAll(udi);
|
|
m_deviceCache.removeAll(udi + ":media");
|
|
emit deviceRemoved(udi + ":media");
|
|
}
|
|
}
|
|
|
|
if (device.queryDeviceInterface(Solid::DeviceInterface::StorageDrive)
|
|
&& device.prop("DeviceIsMediaAvailable").toBool()
|
|
&& m_dirtyDevices.contains(udi))
|
|
{
|
|
//qDebug() << "dirty device added:" << udi;
|
|
emit deviceAdded(udi);
|
|
m_dirtyDevices.removeAll(udi);
|
|
}
|
|
}
|
|
|
|
const QStringList &UDisksManager::deviceCache()
|
|
{
|
|
if (m_deviceCache.isEmpty())
|
|
allDevices();
|
|
|
|
return m_deviceCache;
|
|
}
|
|
|
|
|
|
#include "backends/udisks/moc_udisksmanager.cpp"
|