diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index c7dbe3db6..fc41ad3ac 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -52,6 +52,10 @@ set(SOURCES
core/taskmanager.cpp
core/utilities.cpp
+ devices/device.cpp
+ devices/deviceengine.cpp
+ devices/filesystemdeviceengine.cpp
+
engines/enginebase.cpp
library/groupbydialog.cpp
@@ -168,6 +172,10 @@ set(HEADERS
core/songloader.h
core/taskmanager.h
+ devices/device.h
+ devices/deviceengine.h
+ devices/filesystemdeviceengine.h
+
engines/enginebase.h
library/groupbydialog.h
@@ -398,6 +406,11 @@ list(APPEND OTHER_SOURCES
if(NOT APPLE AND NOT WIN32)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/dbus)
+ # Hack to get it to generate interfaces without namespaces - required
+ # because otherwise org::freedesktop::UDisks and
+ # org::freedesktop::UDisks::Device conflict.
+ list(APPEND QT_DBUSXML2CPP_EXECUTABLE -N)
+
# MPRIS DBUS interfaces
qt4_add_dbus_adaptor(SOURCES
dbus/org.freedesktop.MediaPlayer.player.xml
diff --git a/src/devices/device.cpp b/src/devices/device.cpp
new file mode 100644
index 000000000..cdbbf852d
--- /dev/null
+++ b/src/devices/device.cpp
@@ -0,0 +1,22 @@
+/* This file is part of Clementine.
+
+ Clementine is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Clementine 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Clementine. If not, see .
+*/
+
+#include "device.h"
+
+Device::Device(QObject *parent)
+ : QObject(parent)
+{
+}
diff --git a/src/devices/device.h b/src/devices/device.h
new file mode 100644
index 000000000..5e0ab69f9
--- /dev/null
+++ b/src/devices/device.h
@@ -0,0 +1,29 @@
+/* This file is part of Clementine.
+
+ Clementine is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Clementine 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Clementine. If not, see .
+*/
+
+#ifndef DEVICE_H
+#define DEVICE_H
+
+#include
+
+class Device : public QObject {
+ Q_OBJECT
+
+public:
+ Device(QObject *parent = 0);
+};
+
+#endif // DEVICE_H
diff --git a/src/devices/deviceengine.cpp b/src/devices/deviceengine.cpp
new file mode 100644
index 000000000..c948866a1
--- /dev/null
+++ b/src/devices/deviceengine.cpp
@@ -0,0 +1,22 @@
+/* This file is part of Clementine.
+
+ Clementine is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Clementine 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Clementine. If not, see .
+*/
+
+#include "deviceengine.h"
+
+DeviceEngine::DeviceEngine(QObject *parent)
+ : QAbstractItemModel(parent)
+{
+}
diff --git a/src/devices/deviceengine.h b/src/devices/deviceengine.h
new file mode 100644
index 000000000..a66aa5c12
--- /dev/null
+++ b/src/devices/deviceengine.h
@@ -0,0 +1,42 @@
+/* This file is part of Clementine.
+
+ Clementine is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Clementine 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Clementine. If not, see .
+*/
+
+#ifndef DEVICEENGINE_H
+#define DEVICEENGINE_H
+
+#include
+
+class DeviceEngine : public QAbstractItemModel {
+ Q_OBJECT
+
+public:
+ DeviceEngine(QObject* parent = 0);
+
+ enum Column {
+ Column_UniqueID = 0,
+ Column_FriendlyName,
+ Column_Manufacturer,
+ Column_Model,
+ Column_Capacity,
+ Column_FreeSpace,
+
+ LastDeviceEngineColumn
+ };
+
+ virtual bool Init() = 0;
+};
+
+#endif // DEVICEENGINE_H
diff --git a/src/devices/filesystemdeviceengine.cpp b/src/devices/filesystemdeviceengine.cpp
new file mode 100644
index 000000000..b4e40e994
--- /dev/null
+++ b/src/devices/filesystemdeviceengine.cpp
@@ -0,0 +1,191 @@
+/* This file is part of Clementine.
+
+ Clementine is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Clementine 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Clementine. If not, see .
+*/
+
+#include "filesystemdeviceengine.h"
+#include "dbus/udisks.h"
+#include "dbus/udisksdevice.h"
+
+FilesystemDeviceEngine::FilesystemDeviceEngine(QObject *parent)
+ : DeviceEngine(parent)
+{
+}
+
+FilesystemDeviceEngine::~FilesystemDeviceEngine() {
+}
+
+bool FilesystemDeviceEngine::Init() {
+ interface_.reset(new OrgFreedesktopUDisksInterface(
+ OrgFreedesktopUDisksInterface::staticInterfaceName(),
+ "/org/freedesktop/UDisks", QDBusConnection::systemBus()));
+
+ if (!interface_->isValid()) {
+ qWarning() << "Error connecting to the DeviceKit-disks DBUS service";
+ interface_.reset();
+ return false;
+ }
+
+ connect(interface_.get(), SIGNAL(DeviceAdded(QDBusObjectPath)), SLOT(DeviceAdded(QDBusObjectPath)));
+ connect(interface_.get(), SIGNAL(DeviceRemoved(QDBusObjectPath)), SLOT(DeviceRemoved(QDBusObjectPath)));
+ connect(interface_.get(), SIGNAL(DeviceChanged(QDBusObjectPath)), SLOT(DeviceChanged(QDBusObjectPath)));
+
+ Reset();
+ return true;
+}
+
+QModelIndex FilesystemDeviceEngine::index(int row, int column, const QModelIndex &parent) const {
+ if (parent.isValid())
+ return QModelIndex();
+ return createIndex(row, column);
+}
+
+int FilesystemDeviceEngine::rowCount(const QModelIndex &parent) const {
+ if (parent.isValid())
+ return 0;
+ return device_info_.count();
+}
+
+int FilesystemDeviceEngine::columnCount(const QModelIndex &parent) const {
+ return LastFilesystemDeviceEngineColumn;
+}
+
+QVariant FilesystemDeviceEngine::data(const QModelIndex &index, int role) const {
+ const DeviceInfo& info = device_info_[index.row()];
+
+ switch (index.column()) {
+ case Column_UniqueID:
+ return info.unique_id();
+
+ case Column_FriendlyName:
+ if (!info.device_presentation_name.isEmpty())
+ return info.device_presentation_name;
+ if (!info.drive_model.isEmpty() || !info.drive_vendor.isEmpty())
+ return QString("%1 %2").arg(info.drive_vendor, info.drive_model);
+ return info.drive_serial;
+
+ case Column_Manufacturer:
+ return info.drive_vendor;
+
+ case Column_Model:
+ return info.drive_model;
+
+ case Column_Capacity:
+ return info.device_size;
+
+ case Column_FreeSpace:
+ return QVariant();
+
+ case Column_DbusPath:
+ return info.dbus_path;
+
+ case Column_MountPath:
+ return info.device_mount_paths.isEmpty() ? QVariant() : info.device_mount_paths[0];
+
+ default:
+ return QVariant();
+ }
+}
+
+void FilesystemDeviceEngine::Reset() {
+ QDBusPendingReply > reply = interface_->EnumerateDevices();
+ reply.waitForFinished();
+
+ if (!reply.isValid()) {
+ qWarning() << "Error enumerating DeviceKit-disks devices:" << reply.error();
+ return;
+ }
+
+#if QT_VERSION >= 0x040600
+ emit beginResetModel();
+#endif
+
+ device_info_.clear();
+ foreach (const QDBusObjectPath& path, reply.value()) {
+ DeviceInfo info = ReadDeviceInfo(path);
+ if (info.suitable)
+ device_info_ << info;
+ }
+
+#if QT_VERSION >= 0x040600
+ emit endResetModel();
+#else
+ reset();
+#endif
+}
+
+FilesystemDeviceEngine::DeviceInfo FilesystemDeviceEngine::ReadDeviceInfo(
+ const QDBusObjectPath &path) const {
+ DeviceInfo ret;
+
+ OrgFreedesktopUDisksDeviceInterface device(
+ OrgFreedesktopUDisksDeviceInterface::staticInterfaceName(),
+ path.path(), QDBusConnection::systemBus());
+ if (!device.isValid()) {
+ qWarning() << "Error connecting to the device interface on" << path.path();
+ return ret;
+ }
+
+ // Don't do anything with internal drives, hidden drives, or things that
+ // aren't partitions
+ if (device.deviceIsSystemInternal() ||
+ device.devicePresentationHide() ||
+ !device.deviceIsPartition()) {
+ return ret;
+ }
+
+ ret.suitable = true;
+ ret.dbus_path = path.path();
+ ret.drive_serial = device.driveSerial();
+ ret.drive_model = device.driveModel();
+ ret.drive_vendor = device.driveVendor();
+ ret.device_presentation_name = device.devicePresentationName();
+ ret.device_presentation_icon_name = device.devicePresentationIconName();
+ ret.device_size = device.deviceSize();
+ return ret;
+}
+
+void FilesystemDeviceEngine::DeviceAdded(const QDBusObjectPath &path) {
+ DeviceInfo info = ReadDeviceInfo(path);
+ if (!info.suitable)
+ return;
+
+ emit beginInsertRows(QModelIndex(), device_info_.count(), device_info_.count());
+ device_info_ << info;
+ emit endInsertRows();
+}
+
+void FilesystemDeviceEngine::DeviceRemoved(const QDBusObjectPath &path) {
+ QModelIndex index = FindDevice(path);
+ if (!index.isValid())
+ return;
+
+ emit beginRemoveRows(QModelIndex(), index.row(), index.row());
+ device_info_.removeAt(index.row());
+ emit endRemoveRows();
+}
+
+void FilesystemDeviceEngine::DeviceChanged(const QDBusObjectPath &path) {
+ QModelIndex index = FindDevice(path);
+ DeviceInfo info = ReadDeviceInfo(path);
+
+ if (index.isValid() && !info.suitable)
+ DeviceRemoved(path);
+ else if (!index.isValid() && info.suitable)
+ DeviceAdded(path);
+ else if (index.isValid() && info.suitable) {
+ device_info_[index.row()] = info;
+ emit dataChanged(index, index.sibling(index.row(), columnCount()));
+ }
+}
diff --git a/src/devices/filesystemdeviceengine.h b/src/devices/filesystemdeviceengine.h
new file mode 100644
index 000000000..762834719
--- /dev/null
+++ b/src/devices/filesystemdeviceengine.h
@@ -0,0 +1,84 @@
+/* This file is part of Clementine.
+
+ Clementine is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Clementine 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Clementine. If not, see .
+*/
+
+#ifndef FILESYSTEMDEVICEENGINE_H
+#define FILESYSTEMDEVICEENGINE_H
+
+#include "deviceengine.h"
+
+#include
+
+#include
+
+class OrgFreedesktopUDisksInterface;
+
+class QDBusObjectPath;
+
+class FilesystemDeviceEngine : public DeviceEngine {
+ Q_OBJECT
+
+public:
+ FilesystemDeviceEngine(QObject *parent = 0);
+ ~FilesystemDeviceEngine();
+
+ enum Column {
+ Column_MountPath = LastDeviceEngineColumn,
+ Column_DbusPath,
+
+ LastFilesystemDeviceEngineColumn
+ };
+
+ bool Init();
+
+ QModelIndex index(int row, int column, const QModelIndex &parent) const;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const;
+ QVariant data(const QModelIndex &index, int role) const;
+
+private slots:
+ void DeviceAdded(const QDBusObjectPath& path);
+ void DeviceRemoved(const QDBusObjectPath& path);
+ void DeviceChanged(const QDBusObjectPath& path);
+
+private:
+ struct DeviceInfo {
+ DeviceInfo() : suitable(false), device_size(0) {}
+
+ bool suitable;
+ QString dbus_path;
+ QString drive_serial;
+ QString drive_model;
+ QString drive_vendor;
+ QString device_presentation_name;
+ QString device_presentation_icon_name;
+ QStringList device_mount_paths;
+ quint64 device_size;
+
+ QString unique_id() const;
+ };
+
+ void Reset();
+ DeviceInfo ReadDeviceInfo(const QDBusObjectPath& path) const;
+
+ QModelIndex FindDevice(const QDBusObjectPath& path) const;
+
+private:
+ boost::scoped_ptr interface_;
+
+ QList device_info_;
+};
+
+#endif // FILESYSTEMDEVICEENGINE_H
diff --git a/src/widgets/osd.cpp b/src/widgets/osd.cpp
index 8f61a5208..64fa7b079 100644
--- a/src/widgets/osd.cpp
+++ b/src/widgets/osd.cpp
@@ -18,6 +18,10 @@
#include "osdpretty.h"
#include "ui/systemtrayicon.h"
+#ifdef Q_WS_X11
+# include "dbus/notification.h"
+#endif
+
#include
#include
#include
diff --git a/src/widgets/osd.h b/src/widgets/osd.h
index 9647d3ca5..36b0860be 100644
--- a/src/widgets/osd.h
+++ b/src/widgets/osd.h
@@ -17,6 +17,7 @@
#ifndef OSD_H
#define OSD_H
+#include
#include
#include
@@ -26,6 +27,7 @@
#include "core/song.h"
class NetworkAccessManager;
+class OrgFreedesktopNotificationsInterface;
class OSDPretty;
class SystemTrayIcon;
@@ -34,7 +36,6 @@ class QDBusPendingCallWatcher;
#ifdef Q_WS_X11
# include
# include
-# include "dbus/notification.h"
QDBusArgument& operator<< (QDBusArgument& arg, const QImage& image);
const QDBusArgument& operator>> (const QDBusArgument& arg, QImage& image);
@@ -118,7 +119,7 @@ class OSD : public QObject {
#endif // Q_OS_DARWIN
#ifdef Q_WS_X11
- boost::scoped_ptr interface_;
+ boost::scoped_ptr interface_;
uint notification_id_;
QDateTime last_notification_time_;
#endif
diff --git a/src/widgets/osd_x11.cpp b/src/widgets/osd_x11.cpp
index e704b969d..21425e257 100644
--- a/src/widgets/osd_x11.cpp
+++ b/src/widgets/osd_x11.cpp
@@ -15,6 +15,7 @@
*/
#include "osd.h"
+#include "dbus/notification.h"
#include
#include
@@ -52,8 +53,8 @@ const QDBusArgument& operator>> (const QDBusArgument& arg, QImage& image) {
}
void OSD::Init() {
- interface_.reset(new org::freedesktop::Notifications(
- "org.freedesktop.Notifications",
+ interface_.reset(new OrgFreedesktopNotificationsInterface(
+ OrgFreedesktopNotificationsInterface::staticInterfaceName(),
"/org/freedesktop/Notifications",
QDBusConnection::sessionBus()));
if (!interface_->isValid()) {