File udisks2-support-for-devicemanager.patch of Package clementine

From d4e932db9a4e768737803afb331c1dd1acd3c9fe Mon Sep 17 00:00:00 2001
From: Valeriy <jazzvoid@gmail.com>
Date: Tue, 17 May 2016 22:56:16 +0300
Subject: [PATCH 1/7] udisks2 support for devicemanager (refs #3264)

---
 CMakeLists.txt                                  |   4 +
 src/CMakeLists.txt                              |  28 +++
 src/config.h.in                                 |   1 +
 src/core/metatypes.cpp                          |   3 +
 src/dbus/metatypes.h                            |   8 +-
 src/dbus/org.freedesktop.DBus.ObjectManager.xml |  19 ++
 src/dbus/org.freedesktop.UDisks2.Block.xml      |   9 +
 src/dbus/org.freedesktop.UDisks2.Drive.xml      |  17 ++
 src/dbus/org.freedesktop.UDisks2.Filesystem.xml |  18 ++
 src/devices/devicemanager.cpp                   |   9 +
 src/devices/udisks2lister.cpp                   | 286 ++++++++++++++++++++++++
 src/devices/udisks2lister.h                     |  77 +++++++
 12 files changed, 478 insertions(+), 1 deletion(-)
 create mode 100644 src/dbus/org.freedesktop.DBus.ObjectManager.xml
 create mode 100644 src/dbus/org.freedesktop.UDisks2.Block.xml
 create mode 100644 src/dbus/org.freedesktop.UDisks2.Drive.xml
 create mode 100644 src/dbus/org.freedesktop.UDisks2.Filesystem.xml
 create mode 100644 src/devices/udisks2lister.cpp
 create mode 100644 src/devices/udisks2lister.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6da158e..4bc74eb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -254,6 +254,10 @@ optional_component(DEVICEKIT ON "Devices: DeviceKit backend"
   DEPENDS "D-Bus support" HAVE_DBUS
 )
 
+optional_component(UDISKS2 ON "Devices: UDisks2 backend"
+  DEPENDS "D-Bus support" HAVE_DBUS
+)
+
 optional_component(SPOTIFY_BLOB ON "Spotify support: non-GPL binary helper"
   DEPENDS "protobuf" PROTOBUF_FOUND PROTOBUF_PROTOC_EXECUTABLE
   DEPENDS "libspotify" SPOTIFY_FOUND
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 4f0832b..ca6625a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -964,6 +964,29 @@ if(HAVE_DBUS)
         dbus/udisksdevice)
   endif(HAVE_DEVICEKIT)
 
+  if(HAVE_UDISKS2)
+      set_source_files_properties(dbus/org.freedesktop.DBus.ObjectManager.xml
+          PROPERTIES NO_NAMESPACE dbus/objectmanager INCLUDE dbus/metatypes.h)
+      set_source_files_properties(dbus/org.freedesktop.UDisks2.Filesystem.xml
+          PROPERTIES NO_NAMESPACE dbus/udisks2filesystem INCLUDE dbus/metatypes.h)
+      set_source_files_properties(dbus/org.freedesktop.UDisks2.Block.xml
+          PROPERTIES NO_NAMESPACE dbus/udisks2block INCLUDE dbus/metatypes.h)
+      set_source_files_properties(dbus/org.freedesktop.UDisks2.Drive.xml
+          PROPERTIES NO_NAMESPACE dbus/udisks2drive INCLUDE dbus/metatypes.h)
+      qt4_add_dbus_interface(SOURCES
+          dbus/org.freedesktop.DBus.ObjectManager.xml
+          dbus/objectmanager)
+      qt4_add_dbus_interface(SOURCES
+          dbus/org.freedesktop.UDisks2.Filesystem.xml
+          dbus/udisks2filesystem)
+      qt4_add_dbus_interface(SOURCES
+          dbus/org.freedesktop.UDisks2.Block.xml
+          dbus/udisks2block)
+      qt4_add_dbus_interface(SOURCES
+          dbus/org.freedesktop.UDisks2.Drive.xml
+          dbus/udisks2drive)
+  endif(HAVE_UDISKS2)
+
   # Wiimotedev interface classes
   if(ENABLE_WIIMOTEDEV)
     qt4_add_dbus_interface(SOURCES
@@ -999,6 +1022,11 @@ optional_source(HAVE_DEVICEKIT
   HEADERS devices/devicekitlister.h
 )
 
+optional_source(HAVE_UDISKS2
+  SOURCES devices/udisks2lister.cpp
+  HEADERS devices/udisks2lister.h
+)
+
 # Libgpod device backend
 optional_source(HAVE_LIBGPOD
   INCLUDE_DIRECTORIES ${LIBGPOD_INCLUDE_DIRS}
diff --git a/src/config.h.in b/src/config.h.in
index f22fe9b..2bd31b7 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -41,6 +41,7 @@
 #cmakedefine HAVE_SKYDRIVE
 #cmakedefine HAVE_SPARKLE
 #cmakedefine HAVE_SPOTIFY_DOWNLOADER
+#cmakedefine HAVE_UDISKS2
 #cmakedefine HAVE_VK
 #cmakedefine HAVE_WIIMOTEDEV
 #cmakedefine TAGLIB_HAS_OPUS
diff --git a/src/core/metatypes.cpp b/src/core/metatypes.cpp
index 62e2460..00b3553 100644
--- a/src/core/metatypes.cpp
+++ b/src/core/metatypes.cpp
@@ -125,5 +125,8 @@ void RegisterMetaTypes() {
   qDBusRegisterMetaType<MprisPlaylist>();
   qDBusRegisterMetaType<MaybePlaylist>();
   qDBusRegisterMetaType<MprisPlaylistList>();
+
+  qDBusRegisterMetaType<InterfacesAndProperties>();
+  qDBusRegisterMetaType<ManagedObjectList>();
 #endif
 }
diff --git a/src/dbus/metatypes.h b/src/dbus/metatypes.h
index 4e00245..83bc5e6 100644
--- a/src/dbus/metatypes.h
+++ b/src/dbus/metatypes.h
@@ -20,6 +20,12 @@
 
 #include <QMetaType>
 
-Q_DECLARE_METATYPE(QList<QByteArray>);
+Q_DECLARE_METATYPE(QList<QByteArray>)
+
+typedef QMap<QString, QVariantMap> InterfacesAndProperties;
+typedef QMap<QDBusObjectPath, InterfacesAndProperties> ManagedObjectList;
+
+Q_DECLARE_METATYPE(InterfacesAndProperties)
+Q_DECLARE_METATYPE(ManagedObjectList)
 
 #endif  // DBUS_METATYPES_H_
diff --git a/src/dbus/org.freedesktop.DBus.ObjectManager.xml b/src/dbus/org.freedesktop.DBus.ObjectManager.xml
new file mode 100644
index 0000000..efc389d
--- /dev/null
+++ b/src/dbus/org.freedesktop.DBus.ObjectManager.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+  <interface name="org.freedesktop.DBus.ObjectManager">
+    <method name="GetManagedObjects">
+      <arg name="objects" type="a{oa{sa{sv}}}" direction="out"/>
+      <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="ManagedObjectList"/>
+    </method>
+    <signal name="InterfacesAdded">
+      <arg name="object" type="o"/>
+      <arg name="interfaces" type="a{sa{sv}}"/>
+      <annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="InterfacesAndProperties"/>
+    </signal>
+    <signal name="InterfacesRemoved">
+      <arg type="o" name="object_path"/>
+      <arg type="as" name="interfaces"/>
+    </signal>
+  </interface>
+</node>
diff --git a/src/dbus/org.freedesktop.UDisks2.Block.xml b/src/dbus/org.freedesktop.UDisks2.Block.xml
new file mode 100644
index 0000000..f0e3a06
--- /dev/null
+++ b/src/dbus/org.freedesktop.UDisks2.Block.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+  <interface name="org.freedesktop.UDisks2.Block">
+    <property type="o" name="Drive" access="read"/>
+    <property type="s" name="IdLabel" access="read"/>
+    <property type="s" name="IdUUID" access="read"/>
+  </interface>
+</node>
diff --git a/src/dbus/org.freedesktop.UDisks2.Drive.xml b/src/dbus/org.freedesktop.UDisks2.Drive.xml
new file mode 100644
index 0000000..5312b22
--- /dev/null
+++ b/src/dbus/org.freedesktop.UDisks2.Drive.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0"?>
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+  <interface name="org.freedesktop.UDisks2.Drive">
+    <method name="Eject">
+      <arg type="a{sv}" name="options" direction="in"/>
+      <annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QVariantMap"/>
+    </method>
+    <property type="s" name="Vendor" access="read"/>
+    <property type="s" name="Model" access="read"/>
+    <property type="s" name="Revision" access="read"/>
+    <property type="s" name="Serial" access="read"/>
+    <property type="s" name="Id" access="read"/>
+    <property type="b" name="MediaRemovable" access="read"/>
+    <property type="t" name="Size" access="read"/>
+  </interface>
+</node>
diff --git a/src/dbus/org.freedesktop.UDisks2.Filesystem.xml b/src/dbus/org.freedesktop.UDisks2.Filesystem.xml
new file mode 100644
index 0000000..1781919
--- /dev/null
+++ b/src/dbus/org.freedesktop.UDisks2.Filesystem.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+  <interface name="org.freedesktop.UDisks2.Filesystem">
+    <method name="Mount">
+      <arg type="a{sv}" name="options" direction="in"/>
+      <annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QVariantMap"/>
+      <arg type="s" name="mount_path" direction="out"/>
+    </method>
+    <method name="Unmount">
+      <arg type="a{sv}" name="options" direction="in"/>
+      <annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QVariantMap"/>
+    </method>
+    <property type="aay" name="MountPoints" access="read">
+      <annotation name="org.qtproject.QtDBus.QtTypeName" value="QList&lt;QByteArray&gt;"/>
+    </property>
+  </interface>
+</node>
diff --git a/src/devices/devicemanager.cpp b/src/devices/devicemanager.cpp
index 6396b56..32ba336 100644
--- a/src/devices/devicemanager.cpp
+++ b/src/devices/devicemanager.cpp
@@ -59,6 +59,9 @@
 #ifdef HAVE_LIBMTP
 #include "mtpdevice.h"
 #endif
+#ifdef HAVE_UDISKS2
+#include "udisks2lister.h"
+#endif
 
 using std::bind;
 
@@ -191,6 +194,9 @@ DeviceManager::DeviceManager(Application* app, QObject* parent)
 #ifdef HAVE_DEVICEKIT
   AddLister(new DeviceKitLister);
 #endif
+#ifdef HAVE_UDISKS2
+  AddLister(new Udisks2Lister);
+#endif
 #ifdef HAVE_GIO
   AddLister(new GioLister);
 #endif
@@ -228,7 +234,10 @@ void DeviceManager::LoadAllDevices() {
   for (const DeviceDatabaseBackend::Device& device : devices) {
     DeviceInfo info;
     info.InitFromDb(device);
+
+    beginInsertRows(QModelIndex(), devices_.count(), devices_.count());
     devices_ << info;
+    endInsertRows();
   }
 }
 
diff --git a/src/devices/udisks2lister.cpp b/src/devices/udisks2lister.cpp
new file mode 100644
index 0000000..9925146
--- /dev/null
+++ b/src/devices/udisks2lister.cpp
@@ -0,0 +1,286 @@
+#include "udisks2lister.h"
+
+#include <QDBusConnection>
+
+#include "core/logging.h"
+#include "core/utilities.h"
+
+#include "dbus/udisks2filesystem.h"
+#include "dbus/udisks2block.h"
+#include "dbus/udisks2drive.h"
+
+const QString Udisks2Lister::udisks2service_ = "org.freedesktop.UDisks2";
+
+Udisks2Lister::Udisks2Lister() {
+
+}
+
+Udisks2Lister::~Udisks2Lister() {
+  qLog(Debug) << __PRETTY_FUNCTION__;
+}
+
+QStringList Udisks2Lister::DeviceUniqueIDs() {
+  QReadLocker locker(&device_data_lock_);
+  return device_data_.keys();
+}
+
+QVariantList Udisks2Lister::DeviceIcons(const QString &id) {
+  return QVariantList();
+}
+
+QString Udisks2Lister::DeviceManufacturer(const QString &id) {
+  QReadLocker locker(&device_data_lock_);
+  if (!device_data_.contains(id))
+    return "";
+  return device_data_[id].vendor;
+}
+
+QString Udisks2Lister::DeviceModel(const QString &id) {
+  QReadLocker locker(&device_data_lock_);
+  if (!device_data_.contains(id))
+    return "";
+  return device_data_[id].model;
+}
+
+quint64 Udisks2Lister::DeviceCapacity(const QString &id) {
+  QReadLocker locker(&device_data_lock_);
+  if (!device_data_.contains(id))
+    return 0;
+  return device_data_[id].capacity;
+}
+
+quint64 Udisks2Lister::DeviceFreeSpace(const QString &id) {
+  QReadLocker locker(&device_data_lock_);
+  if (!device_data_.contains(id))
+    return 0;
+  return device_data_[id].free_space;
+}
+
+QVariantMap Udisks2Lister::DeviceHardwareInfo(const QString &id) {
+  QReadLocker locker(&device_data_lock_);
+  if (!device_data_.contains(id))
+    return QVariantMap();
+
+  QVariantMap result;
+
+  const auto &data = device_data_[id];
+  result[QT_TR_NOOP("DBus path")] = data.dbus_path;
+  result[QT_TR_NOOP("Serial number")] = data.serial;
+  result[QT_TR_NOOP("Mount points")] = data.mount_paths.join(", ");
+  result[QT_TR_NOOP("Parition label")] = data.label;
+  result[QT_TR_NOOP("UUID")] = data.uuid;
+
+  return result;
+}
+
+QString Udisks2Lister::MakeFriendlyName(const QString &id) {
+  QReadLocker locker(&device_data_lock_);
+  if (!device_data_.contains(id))
+    return "";
+  return device_data_[id].friendly_name;
+}
+
+QList<QUrl> Udisks2Lister::MakeDeviceUrls(const QString &id) {
+  QReadLocker locker(&device_data_lock_);
+  if (!device_data_.contains(id))
+    return QList<QUrl>();
+  return QList<QUrl>() << QUrl::fromLocalFile(device_data_[id].mount_paths.at(0));
+}
+
+void Udisks2Lister::UnmountDevice(const QString &id) {
+  QReadLocker locker(&device_data_lock_);
+  if (!device_data_.contains(id))
+    return;
+
+  OrgFreedesktopUDisks2FilesystemInterface filesystem(
+        udisks2service_,
+        device_data_[id].dbus_path,
+        QDBusConnection::systemBus());
+
+  if (filesystem.isValid())
+  {
+    auto umountResult = filesystem.Unmount(QVariantMap());
+    umountResult.waitForFinished();
+
+    OrgFreedesktopUDisks2DriveInterface drive(
+          udisks2service_,
+          device_data_[id].dbus_drive_path,
+          QDBusConnection::systemBus());
+
+    if (drive.isValid())
+    {
+      auto ejectResult = drive.Eject(QVariantMap());
+      ejectResult.waitForFinished();
+    }
+  }
+}
+
+void Udisks2Lister::UpdateDeviceFreeSpace(const QString &id) {
+  QWriteLocker locker(&device_data_lock_);
+  device_data_[id].free_space = Utilities::FileSystemFreeSpace(device_data_[id].mount_paths.at(0));
+
+  emit DeviceChanged(id);
+}
+
+void Udisks2Lister::Init() {
+  udisks2_interface_.reset(new OrgFreedesktopDBusObjectManagerInterface(
+                             udisks2service_,
+                             "/org/freedesktop/UDisks2",
+                             QDBusConnection::systemBus()));
+
+  QDBusPendingReply<ManagedObjectList> reply = udisks2_interface_->GetManagedObjects();
+  reply.waitForFinished();
+
+  if (!reply.isValid()) {
+    qLog(Warning) << "Error enumerating udisks2 devices:"
+                  << reply.error().name() << reply.error().message();
+    udisks2_interface_.reset();
+    return;
+  }
+
+  for (const QDBusObjectPath &path : reply.value().keys()) {
+    auto partitionData = ReadPartitionData(path, false);
+
+    if (!partitionData.dbus_path.isEmpty())
+    {
+      QWriteLocker locker(&device_data_lock_);
+      device_data_[partitionData.unique_id()] = partitionData;
+    }
+  }
+
+  for (const auto &id : device_data_.keys()) {
+    emit DeviceAdded(id);
+  }
+
+  connect(udisks2_interface_.get(), SIGNAL(InterfacesAdded(QDBusObjectPath, InterfacesAndProperties)),
+          SLOT(DBusInterfaceAdded(QDBusObjectPath, InterfacesAndProperties)));
+  connect(udisks2_interface_.get(), SIGNAL(InterfacesRemoved(QDBusObjectPath, QStringList)),
+          SLOT(DBusInterfaceRemoved(QDBusObjectPath, QStringList)));
+}
+
+void Udisks2Lister::DBusInterfaceAdded(const QDBusObjectPath &path,
+                                       const InterfacesAndProperties &interfaces) {
+  // FIXME handle unmount jobs too
+  for (auto interface = interfaces.constBegin(); interface != interfaces.constEnd(); ++interface)
+  {
+    if (interface.key() != "org.freedesktop.UDisks2.Job"
+        || interface.value()["Operation"] != "filesystem-mount")
+      continue;
+
+    const QDBusArgument &objects = interface.value()["Objects"].value<QDBusArgument>();
+
+    QList<QDBusObjectPath> mountedParititons;
+    objects.beginArray();
+    while (!objects.atEnd()) {
+      QDBusObjectPath extractedPath;
+      objects >> extractedPath;
+      mountedParititons.push_back(extractedPath);
+    }
+    objects.endArray();
+
+    qLog(Debug) << "Udisks2 something mounted: " << mountedParititons.at(0).path();
+
+    {
+      QMutexLocker locker(&jobs_lock_);
+      mounting_jobs_[path.path()] = mountedParititons;
+    }
+  }
+}
+
+void Udisks2Lister::DBusInterfaceRemoved(const QDBusObjectPath &path, const QStringList &ifaces) {
+  if (!isPendingJob(path))
+    RemoveDevice(path);
+}
+
+bool Udisks2Lister::isPendingJob(const QDBusObjectPath &path)
+{
+  // should be actually done with a succcess signal from job, I guess, but it makes it kinda complicated
+  QMutexLocker locker(&jobs_lock_);
+
+  if (!mounting_jobs_.contains(path.path()))
+    return false;
+
+  const auto &mountpaths = mounting_jobs_[path.path()];
+  for (const auto &partition : mountpaths) {
+    auto data = ReadPartitionData(partition, true);
+    if (!data.dbus_path.isEmpty()) {
+      QWriteLocker locker(&device_data_lock_);
+      device_data_[data.unique_id()] = data;
+      DeviceAdded(data.unique_id());
+    }
+  }
+  mounting_jobs_.remove(path.path());
+  return true;
+}
+
+void Udisks2Lister::RemoveDevice(const QDBusObjectPath &path)
+{
+  QWriteLocker locker(&device_data_lock_);
+  QString id;
+  for (const auto &data : device_data_) {
+    if (data.dbus_path == path.path())
+      id = data.unique_id();
+  }
+
+  if (id.isEmpty())
+    return;
+
+  device_data_.remove(id);
+  DeviceRemoved(id);
+}
+
+Udisks2Lister::PartitionData Udisks2Lister::ReadPartitionData(const QDBusObjectPath &path,
+                                                              bool beingMounted) {
+  PartitionData result;
+  OrgFreedesktopUDisks2FilesystemInterface filesystem(
+        udisks2service_,
+        path.path(),
+        QDBusConnection::systemBus());
+  OrgFreedesktopUDisks2BlockInterface block(
+        udisks2service_,
+        path.path(),
+        QDBusConnection::systemBus());
+
+  if (filesystem.isValid()
+      && block.isValid()
+      && (beingMounted || !filesystem.mountPoints().empty())) {
+
+    OrgFreedesktopUDisks2DriveInterface drive(
+          udisks2service_,
+          block.drive().path(),
+          QDBusConnection::systemBus());
+
+    if (drive.isValid()
+        && drive.mediaRemovable()) {
+      result.dbus_path = path.path();
+      result.dbus_drive_path = block.drive().path();
+
+      result.serial = drive.serial();
+      result.vendor = drive.vendor();
+      result.model = drive.model();
+
+      result.label = block.idLabel();
+      result.uuid = block.idUUID();
+      result.capacity = drive.size();
+
+      if (!result.label.isEmpty())
+        result.friendly_name = result.label;
+      else
+        result.friendly_name = result.model + " " + result.uuid;
+
+      for (const auto &path : filesystem.mountPoints())
+        result.mount_paths.push_back(path);
+
+      result.free_space = Utilities::FileSystemFreeSpace(result.mount_paths.at(0));
+    }
+  }
+
+  return result;
+}
+
+QString Udisks2Lister::PartitionData::unique_id() const {
+  return QString("Udisks2/%1/%2/%3/%4/%5")
+      .arg(serial, vendor, model)
+      .arg(capacity)
+      .arg(uuid);
+}
diff --git a/src/devices/udisks2lister.h b/src/devices/udisks2lister.h
new file mode 100644
index 0000000..639db40
--- /dev/null
+++ b/src/devices/udisks2lister.h
@@ -0,0 +1,77 @@
+#pragma once
+
+#include <memory>
+
+#include "devicelister.h"
+
+#include "dbus/objectmanager.h"
+
+class Udisks2Lister : public DeviceLister {
+  Q_OBJECT
+
+public:
+  Udisks2Lister();
+  ~Udisks2Lister();
+
+  QStringList DeviceUniqueIDs();
+  QVariantList DeviceIcons(const QString &id);
+  QString DeviceManufacturer(const QString &id);
+  QString DeviceModel(const QString &id);
+  quint64 DeviceCapacity(const QString &id);
+  quint64 DeviceFreeSpace(const QString &id);
+  QVariantMap DeviceHardwareInfo(const QString &id);
+
+  QString MakeFriendlyName(const QString &id);
+  QList<QUrl> MakeDeviceUrls(const QString &id);
+
+  void UnmountDevice(const QString &id);
+
+public slots:
+  void UpdateDeviceFreeSpace(const QString &id);
+
+protected:
+  void Init();
+
+private slots:
+  void DBusInterfaceAdded(const QDBusObjectPath &path, const InterfacesAndProperties &ifaces);
+  void DBusInterfaceRemoved(const QDBusObjectPath &path, const QStringList &ifaces);
+
+private:
+  bool isPendingJob(const QDBusObjectPath &path);
+  void RemoveDevice(const QDBusObjectPath &path);
+
+  QMutex jobs_lock_;
+  QMap<QString, QList<QDBusObjectPath>> mounting_jobs_;
+
+private:
+  class PartitionData {
+  public:
+    QString unique_id() const;
+
+    QString dbus_path;
+    QString friendly_name;
+
+    // Device
+    QString serial;
+    QString vendor;
+    QString model;
+    quint64 capacity = 0;
+    QString dbus_drive_path;
+
+    // Paritition
+    QString label;
+    QString uuid;
+    quint64 free_space = 0;
+    QStringList mount_paths;
+  };
+
+  PartitionData ReadPartitionData(const QDBusObjectPath &path, bool beingMounted);
+
+  QReadWriteLock device_data_lock_;
+  QMap<QString, PartitionData> device_data_;
+
+private:
+  std::unique_ptr<OrgFreedesktopDBusObjectManagerInterface> udisks2_interface_;
+
+  static const QString udisks2service_;
+};

From 68001ff7e87f9ca1996a84eee928c31acd1ec564 Mon Sep 17 00:00:00 2001
From: Valeriy <jazzvoid@gmail.com>
Date: Sat, 21 May 2016 23:29:18 +0300
Subject: [PATCH 2/7] udisks2: handle unmount jobs too, more verbose logging

---
 src/devices/udisks2lister.cpp | 74 +++++++++++++++++++++++++++++++++----------
 src/devices/udisks2lister.h   | 13 ++++++--
 2 files changed, 67 insertions(+), 20 deletions(-)

diff --git a/src/devices/udisks2lister.cpp b/src/devices/udisks2lister.cpp
index 9925146..df6fb62 100644
--- a/src/devices/udisks2lister.cpp
+++ b/src/devices/udisks2lister.cpp
@@ -160,11 +160,17 @@ void Udisks2Lister::Init() {
 
 void Udisks2Lister::DBusInterfaceAdded(const QDBusObjectPath &path,
                                        const InterfacesAndProperties &interfaces) {
-  // FIXME handle unmount jobs too
   for (auto interface = interfaces.constBegin(); interface != interfaces.constEnd(); ++interface)
   {
-    if (interface.key() != "org.freedesktop.UDisks2.Job"
-        || interface.value()["Operation"] != "filesystem-mount")
+    if (interface.key() != "org.freedesktop.UDisks2.Job")
+      continue;
+
+    bool isMountJob = false;
+    if (interface.value()["Operation"] == "filesystem-mount")
+      isMountJob = true;
+    else if (interface.value()["Operation"] == "filesystem-unmount")
+      isMountJob = false;
+    else
       continue;
 
     const QDBusArgument &objects = interface.value()["Objects"].value<QDBusArgument>();
@@ -178,11 +184,19 @@ void Udisks2Lister::DBusInterfaceAdded(const QDBusObjectPath &path,
     }
     objects.endArray();
 
-    qLog(Debug) << "Udisks2 something mounted: " << mountedParititons.at(0).path();
+    if (mountedParititons.isEmpty()) {
+      qLog(Warning) << "Empty Udisks2 mount/umount job " << path.path();
+      return;
+    }
+
+    qLog(Debug) << "Adding Udisks job " << path.path()
+                << " | Operation = " << interface.value()["Operation"].toString()
+                << " with first path: " << mountedParititons.at(0).path();
 
     {
       QMutexLocker locker(&jobs_lock_);
-      mounting_jobs_[path.path()] = mountedParititons;
+      mounting_jobs_[path.path()].isMount = isMountJob;
+      mounting_jobs_[path.path()].mount_paths = mountedParititons;
     }
   }
 }
@@ -192,39 +206,65 @@ void Udisks2Lister::DBusInterfaceRemoved(const QDBusObjectPath &path, const QStr
     RemoveDevice(path);
 }
 
-bool Udisks2Lister::isPendingJob(const QDBusObjectPath &path)
-{
+bool Udisks2Lister::isPendingJob(const QDBusObjectPath &jobPath) {
   // should be actually done with a succcess signal from job, I guess, but it makes it kinda complicated
   QMutexLocker locker(&jobs_lock_);
 
-  if (!mounting_jobs_.contains(path.path()))
+  if (!mounting_jobs_.contains(jobPath.path()))
     return false;
 
-  const auto &mountpaths = mounting_jobs_[path.path()];
-  for (const auto &partition : mountpaths) {
+  const auto &mountPaths = mounting_jobs_[jobPath.path()].mount_paths;
+  const auto &isMount = mounting_jobs_[jobPath.path()].isMount;
+  for (const auto &partition : mountPaths) {
     auto data = ReadPartitionData(partition, true);
     if (!data.dbus_path.isEmpty()) {
-      QWriteLocker locker(&device_data_lock_);
-      device_data_[data.unique_id()] = data;
-      DeviceAdded(data.unique_id());
+      if (isMount) {
+        qLog(Debug) << "UDisks2 mount job finished: Drive = " << data.dbus_drive_path
+                    << " | Partition = " << data.dbus_path;
+        QWriteLocker locker(&device_data_lock_);
+        device_data_[data.unique_id()] = data;
+        DeviceAdded(data.unique_id());
+      } else {
+        QWriteLocker locker(&device_data_lock_);
+        QString id;
+        for (auto &data : device_data_) {
+          if (data.mount_paths.contains(partition.path())) {
+            qLog(Debug) << "UDisks2 umount job finished, found corresponding device: Drive = " << data.dbus_drive_path
+                        << " | Partition = " << data.dbus_path;
+            data.mount_paths.removeOne(partition.path());
+            if (data.mount_paths.empty())
+              id = data.unique_id();
+            break;
+          }
+        }
+
+        if (!id.isEmpty())
+        {
+          qLog(Debug) << "Partition " << data.dbus_path << " has no more mount points, removing it from device list";
+          device_data_.remove(id);
+          DeviceRemoved(id);
+        }
+      }
     }
   }
-  mounting_jobs_.remove(path.path());
+  mounting_jobs_.remove(jobPath.path());
   return true;
 }
 
-void Udisks2Lister::RemoveDevice(const QDBusObjectPath &path)
-{
+void Udisks2Lister::RemoveDevice(const QDBusObjectPath &devicePath) {
   QWriteLocker locker(&device_data_lock_);
   QString id;
   for (const auto &data : device_data_) {
-    if (data.dbus_path == path.path())
+    if (data.dbus_path == devicePath.path()) {
       id = data.unique_id();
+      break;
+    }
   }
 
   if (id.isEmpty())
     return;
 
+  qLog(Debug) << "UDisks2 device removed: " << devicePath.path();
   device_data_.remove(id);
   DeviceRemoved(id);
 }
diff --git a/src/devices/udisks2lister.h b/src/devices/udisks2lister.h
index 639db40..37320ed 100644
--- a/src/devices/udisks2lister.h
+++ b/src/devices/udisks2lister.h
@@ -37,11 +37,18 @@ private slots:
   void DBusInterfaceRemoved(const QDBusObjectPath &path, const QStringList &ifaces);
 
 private:
-  bool isPendingJob(const QDBusObjectPath &path);
-  void RemoveDevice(const QDBusObjectPath &path);
+  bool isPendingJob(const QDBusObjectPath &jobPath);
+  void RemoveDevice(const QDBusObjectPath &devicePath);
+
+  class MountJob
+  {
+  public:
+    bool isMount = true;
+    QList<QDBusObjectPath> mount_paths;
+  };
 
   QMutex jobs_lock_;
-  QMap<QString, QList<QDBusObjectPath>> mounting_jobs_;
+  QMap<QString, MountJob> mounting_jobs_;
 
 private:
   class PartitionData {

From ed986d38638be1cce632239466c349d1334228fa Mon Sep 17 00:00:00 2001
From: Valeriy <jazzvoid@gmail.com>
Date: Sun, 22 May 2016 23:44:22 +0300
Subject: [PATCH 3/7] UDisks2.Job interface support

---
 src/CMakeLists.txt                       |   5 ++
 src/dbus/org.freedesktop.UDisks2.Job.xml |  11 +++
 src/devices/udisks2lister.cpp            | 139 +++++++++++++++++++------------
 src/devices/udisks2lister.h              |  11 ++-
 4 files changed, 109 insertions(+), 57 deletions(-)
 create mode 100644 src/dbus/org.freedesktop.UDisks2.Job.xml

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index ca6625a..d7e9083 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -973,6 +973,8 @@ if(HAVE_DBUS)
           PROPERTIES NO_NAMESPACE dbus/udisks2block INCLUDE dbus/metatypes.h)
       set_source_files_properties(dbus/org.freedesktop.UDisks2.Drive.xml
           PROPERTIES NO_NAMESPACE dbus/udisks2drive INCLUDE dbus/metatypes.h)
+      set_source_files_properties(dbus/org.freedesktop.UDisks2.Job.xml
+          PROPERTIES NO_NAMESPACE dbus/udisks2job INCLUDE dbus/metatypes.h)
       qt4_add_dbus_interface(SOURCES
           dbus/org.freedesktop.DBus.ObjectManager.xml
           dbus/objectmanager)
@@ -985,6 +987,9 @@ if(HAVE_DBUS)
       qt4_add_dbus_interface(SOURCES
           dbus/org.freedesktop.UDisks2.Drive.xml
           dbus/udisks2drive)
+      qt4_add_dbus_interface(SOURCES
+          dbus/org.freedesktop.UDisks2.Job.xml
+          dbus/udisks2job)
   endif(HAVE_UDISKS2)
 
   # Wiimotedev interface classes
diff --git a/src/dbus/org.freedesktop.UDisks2.Job.xml b/src/dbus/org.freedesktop.UDisks2.Job.xml
new file mode 100644
index 0000000..2cd4253
--- /dev/null
+++ b/src/dbus/org.freedesktop.UDisks2.Job.xml
@@ -0,0 +1,11 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
+  <interface name="org.freedesktop.UDisks2.Job">
+    <property name="Operation" type="s" access="read"/>
+    <property name="Objects" type="ao" access="read"/>
+    <signal name="Completed">
+      <arg name="success" type="b"/>
+      <arg name="message" type="s"/>
+    </signal>
+  </interface>
+</node>
diff --git a/src/devices/udisks2lister.cpp b/src/devices/udisks2lister.cpp
index df6fb62..023de06 100644
--- a/src/devices/udisks2lister.cpp
+++ b/src/devices/udisks2lister.cpp
@@ -8,6 +8,7 @@
 #include "dbus/udisks2filesystem.h"
 #include "dbus/udisks2block.h"
 #include "dbus/udisks2drive.h"
+#include "dbus/udisks2job.h"
 
 const QString Udisks2Lister::udisks2service_ = "org.freedesktop.UDisks2";
 
@@ -165,6 +166,16 @@ void Udisks2Lister::DBusInterfaceAdded(const QDBusObjectPath &path,
     if (interface.key() != "org.freedesktop.UDisks2.Job")
       continue;
 
+    std::shared_ptr<OrgFreedesktopUDisks2JobInterface> job = std::make_shared<OrgFreedesktopUDisks2JobInterface>(
+          udisks2service_,
+          path.path(),
+          QDBusConnection::systemBus());
+
+    if (!job->isValid())
+      continue;
+
+    // For some reason access through Job interface returns all properties
+    // as invalid for unmount job so we're doing this the hard way
     bool isMountJob = false;
     if (interface.value()["Operation"] == "filesystem-mount")
       isMountJob = true;
@@ -173,30 +184,24 @@ void Udisks2Lister::DBusInterfaceAdded(const QDBusObjectPath &path,
     else
       continue;
 
-    const QDBusArgument &objects = interface.value()["Objects"].value<QDBusArgument>();
-
-    QList<QDBusObjectPath> mountedParititons;
-    objects.beginArray();
-    while (!objects.atEnd()) {
-      QDBusObjectPath extractedPath;
-      objects >> extractedPath;
-      mountedParititons.push_back(extractedPath);
-    }
-    objects.endArray();
+    QList<QDBusObjectPath> mountedParititons
+        = GetMountedPartitionsFromDBusArgument(interface.value()["Objects"].value<QDBusArgument>());
 
     if (mountedParititons.isEmpty()) {
       qLog(Warning) << "Empty Udisks2 mount/umount job " << path.path();
-      return;
+      continue;
     }
 
-    qLog(Debug) << "Adding Udisks job " << path.path()
-                << " | Operation = " << interface.value()["Operation"].toString()
-                << " with first path: " << mountedParititons.at(0).path();
-
     {
       QMutexLocker locker(&jobs_lock_);
-      mounting_jobs_[path.path()].isMount = isMountJob;
-      mounting_jobs_[path.path()].mount_paths = mountedParititons;
+      qLog(Debug) << "Adding pending job | DBus Path = " << job->path()
+                  << " | IsMountJob = " << isMountJob
+                  << " | First partition = " << mountedParititons.at(0).path();
+      mounting_jobs_[path].dbus_interface = job;
+      mounting_jobs_[path].isMount = isMountJob;
+      mounting_jobs_[path].mounted_partitions = mountedParititons;
+      connect(job.get(), SIGNAL(Completed(bool, const QString&)),
+              SLOT(JobCompleted(bool, const QString&)));
     }
   }
 }
@@ -207,47 +212,12 @@ void Udisks2Lister::DBusInterfaceRemoved(const QDBusObjectPath &path, const QStr
 }
 
 bool Udisks2Lister::isPendingJob(const QDBusObjectPath &jobPath) {
-  // should be actually done with a succcess signal from job, I guess, but it makes it kinda complicated
   QMutexLocker locker(&jobs_lock_);
 
-  if (!mounting_jobs_.contains(jobPath.path()))
+  if (!mounting_jobs_.contains(jobPath))
     return false;
 
-  const auto &mountPaths = mounting_jobs_[jobPath.path()].mount_paths;
-  const auto &isMount = mounting_jobs_[jobPath.path()].isMount;
-  for (const auto &partition : mountPaths) {
-    auto data = ReadPartitionData(partition, true);
-    if (!data.dbus_path.isEmpty()) {
-      if (isMount) {
-        qLog(Debug) << "UDisks2 mount job finished: Drive = " << data.dbus_drive_path
-                    << " | Partition = " << data.dbus_path;
-        QWriteLocker locker(&device_data_lock_);
-        device_data_[data.unique_id()] = data;
-        DeviceAdded(data.unique_id());
-      } else {
-        QWriteLocker locker(&device_data_lock_);
-        QString id;
-        for (auto &data : device_data_) {
-          if (data.mount_paths.contains(partition.path())) {
-            qLog(Debug) << "UDisks2 umount job finished, found corresponding device: Drive = " << data.dbus_drive_path
-                        << " | Partition = " << data.dbus_path;
-            data.mount_paths.removeOne(partition.path());
-            if (data.mount_paths.empty())
-              id = data.unique_id();
-            break;
-          }
-        }
-
-        if (!id.isEmpty())
-        {
-          qLog(Debug) << "Partition " << data.dbus_path << " has no more mount points, removing it from device list";
-          device_data_.remove(id);
-          DeviceRemoved(id);
-        }
-      }
-    }
-  }
-  mounting_jobs_.remove(jobPath.path());
+  mounting_jobs_.remove(jobPath);
   return true;
 }
 
@@ -269,6 +239,67 @@ void Udisks2Lister::RemoveDevice(const QDBusObjectPath &devicePath) {
   DeviceRemoved(id);
 }
 
+QList<QDBusObjectPath> Udisks2Lister::GetMountedPartitionsFromDBusArgument(const QDBusArgument &input) {
+  QList<QDBusObjectPath> result;
+
+  input.beginArray();
+  while (!input.atEnd()) {
+    QDBusObjectPath extractedPath;
+    input >> extractedPath;
+    result.push_back(extractedPath);
+  }
+  input.endArray();
+
+  return result;
+}
+
+void Udisks2Lister::JobCompleted(bool success, const QString &message) {
+  auto job = qobject_cast<OrgFreedesktopUDisks2JobInterface*>(sender());
+  QDBusObjectPath jobPath(job->path());
+
+  if (!job->isValid()
+      || !success
+      || !mounting_jobs_.contains(jobPath))
+    return;
+
+  qLog(Debug) << "Pending Job Completed | Path = " << job->path()
+              << " | Mount? = " << mounting_jobs_[jobPath].isMount
+              << " | Success = " << success;
+
+  for (const auto &mountedObject : mounting_jobs_[jobPath].mounted_partitions) {
+    auto data = ReadPartitionData(mountedObject, false);
+    if (data.dbus_path.isEmpty())
+      continue;
+
+    if (mounting_jobs_[jobPath].isMount) {
+      qLog(Debug) << "UDisks2 mount job finished: Drive = " << data.dbus_drive_path
+                  << " | Partition = " << data.dbus_path;
+      QWriteLocker locker(&device_data_lock_);
+      device_data_[data.unique_id()] = data;
+      DeviceAdded(data.unique_id());
+    } else {
+      QWriteLocker locker(&device_data_lock_);
+      QString id;
+      for (auto &data : device_data_) {
+        if (data.mount_paths.contains(mountedObject.path())) {
+          qLog(Debug) << "UDisks2 umount job finished, found corresponding device: Drive = " << data.dbus_drive_path
+                      << " | Partition = " << data.dbus_path;
+          data.mount_paths.removeOne(mountedObject.path());
+          if (data.mount_paths.empty())
+            id = data.unique_id();
+          break;
+        }
+      }
+
+      if (!id.isEmpty()) {
+        qLog(Debug) << "Partition " << data.dbus_path << " has no more mount points, removing it from device list";
+        device_data_.remove(id);
+        DeviceRemoved(id);
+      }
+    }
+  }
+}
+
 Udisks2Lister::PartitionData Udisks2Lister::ReadPartitionData(const QDBusObjectPath &path,
                                                               bool beingMounted) {
   PartitionData result;
diff --git a/src/devices/udisks2lister.h b/src/devices/udisks2lister.h
index 37320ed..62d2835 100644
--- a/src/devices/udisks2lister.h
+++ b/src/devices/udisks2lister.h
@@ -6,6 +6,8 @@
 
 #include "dbus/objectmanager.h"
 
+class OrgFreedesktopUDisks2JobInterface;
+
 class Udisks2Lister : public DeviceLister {
   Q_OBJECT
 
@@ -35,20 +37,23 @@ public slots:
 private slots:
   void DBusInterfaceAdded(const QDBusObjectPath &path, const InterfacesAndProperties &ifaces);
   void DBusInterfaceRemoved(const QDBusObjectPath &path, const QStringList &ifaces);
+  void JobCompleted(bool success, const QString &message);
 
 private:
   bool isPendingJob(const QDBusObjectPath &jobPath);
   void RemoveDevice(const QDBusObjectPath &devicePath);
+  QList<QDBusObjectPath> GetMountedPartitionsFromDBusArgument(const QDBusArgument &input);
 
-  class MountJob
+  class Udisks2Job
   {
   public:
     bool isMount = true;
-    QList<QDBusObjectPath> mount_paths;
+    QList<QDBusObjectPath> mounted_partitions;
+    std::shared_ptr<OrgFreedesktopUDisks2JobInterface> dbus_interface;
   };
 
   QMutex jobs_lock_;
-  QMap<QString, MountJob> mounting_jobs_;
+  QMap<QDBusObjectPath, Udisks2Job> mounting_jobs_;
 
 private:
   class PartitionData {

From cc6a99ef92b6f86c4db2310357a7a90a3f26a392 Mon Sep 17 00:00:00 2001
From: Valeriy <jazzvoid@gmail.com>
Date: Mon, 30 May 2016 18:24:02 +0300
Subject: [PATCH 4/7] handle our unmount responses because those unmount jobs
 expire too fast for jobs use dbus interface when possible clean up the code a
 bit

---
 src/dbus/metatypes.h          |  1 +
 src/devices/udisks2lister.cpp | 98 ++++++++++++++++++++++++-------------------
 src/devices/udisks2lister.h   | 20 +++++----
 3 files changed, 68 insertions(+), 51 deletions(-)

diff --git a/src/dbus/metatypes.h b/src/dbus/metatypes.h
index 83bc5e6..3ec6de1 100644
--- a/src/dbus/metatypes.h
+++ b/src/dbus/metatypes.h
@@ -19,6 +19,7 @@
 #define DBUS_METATYPES_H_
 
 #include <QMetaType>
+#include <QDBusObjectPath>
 
 Q_DECLARE_METATYPE(QList<QByteArray>)
 
diff --git a/src/devices/udisks2lister.cpp b/src/devices/udisks2lister.cpp
index 023de06..0af1884 100644
--- a/src/devices/udisks2lister.cpp
+++ b/src/devices/udisks2lister.cpp
@@ -5,6 +5,7 @@
 #include "core/logging.h"
 #include "core/utilities.h"
 
+#include "dbus/objectmanager.h"
 #include "dbus/udisks2filesystem.h"
 #include "dbus/udisks2block.h"
 #include "dbus/udisks2drive.h"
@@ -100,19 +101,29 @@ void Udisks2Lister::UnmountDevice(const QString &id) {
 
   if (filesystem.isValid())
   {
-    auto umountResult = filesystem.Unmount(QVariantMap());
-    umountResult.waitForFinished();
+    auto unmountResult = filesystem.Unmount(QVariantMap());
+    unmountResult.waitForFinished();
+
+    if (unmountResult.isError()) {
+      qLog(Warning) << "Failed to unmount " << id << ": " << unmountResult.error();
+      return;
+    }
 
     OrgFreedesktopUDisks2DriveInterface drive(
           udisks2service_,
           device_data_[id].dbus_drive_path,
           QDBusConnection::systemBus());
 
-    if (drive.isValid())
-    {
+    if (drive.isValid()) {
       auto ejectResult = drive.Eject(QVariantMap());
       ejectResult.waitForFinished();
+
+      if (ejectResult.isError())
+        qLog(Warning) << "Failed to eject " << id << ": " << ejectResult.error();
     }
+
+    device_data_.remove(id);
+    DeviceRemoved(id);
   }
 }
 
@@ -140,7 +151,7 @@ void Udisks2Lister::Init() {
   }
 
   for (const QDBusObjectPath &path : reply.value().keys()) {
-    auto partitionData = ReadPartitionData(path, false);
+    auto partitionData = ReadPartitionData(path);
 
     if (!partitionData.dbus_path.isEmpty())
     {
@@ -174,20 +185,17 @@ void Udisks2Lister::DBusInterfaceAdded(const QDBusObjectPath &path,
     if (!job->isValid())
       continue;
 
-    // For some reason access through Job interface returns all properties
-    // as invalid for unmount job so we're doing this the hard way
     bool isMountJob = false;
-    if (interface.value()["Operation"] == "filesystem-mount")
+    if (job->operation() == "filesystem-mount")
       isMountJob = true;
-    else if (interface.value()["Operation"] == "filesystem-unmount")
+    else if (job->operation() == "filesystem-unmount")
       isMountJob = false;
     else
       continue;
 
-    QList<QDBusObjectPath> mountedParititons
-        = GetMountedPartitionsFromDBusArgument(interface.value()["Objects"].value<QDBusArgument>());
+    auto mountedPartitions = job->objects();
 
-    if (mountedParititons.isEmpty()) {
+    if (mountedPartitions.isEmpty()) {
       qLog(Warning) << "Empty Udisks2 mount/umount job " << path.path();
       continue;
     }
@@ -196,10 +204,10 @@ void Udisks2Lister::DBusInterfaceAdded(const QDBusObjectPath &path,
       QMutexLocker locker(&jobs_lock_);
       qLog(Debug) << "Adding pending job | DBus Path = " << job->path()
                   << " | IsMountJob = " << isMountJob
-                  << " | First partition = " << mountedParititons.at(0).path();
+                  << " | First partition = " << mountedPartitions.at(0).path();
       mounting_jobs_[path].dbus_interface = job;
       mounting_jobs_[path].isMount = isMountJob;
-      mounting_jobs_[path].mounted_partitions = mountedParititons;
+      mounting_jobs_[path].mounted_partitions = mountedPartitions;
       connect(job.get(), SIGNAL(Completed(bool, const QString&)),
               SLOT(JobCompleted(bool, const QString&)));
     }
@@ -267,41 +275,45 @@ void Udisks2Lister::JobCompleted(bool success, const QString &message) {
               << " | Success = " << success;
 
   for (const auto &mountedObject : mounting_jobs_[jobPath].mounted_partitions) {
-    auto data = ReadPartitionData(mountedObject, false);
-    if (data.dbus_path.isEmpty())
+    auto partitionData = ReadPartitionData(mountedObject);
+    if (partitionData.dbus_path.isEmpty())
       continue;
 
-    if (mounting_jobs_[jobPath].isMount) {
-      qLog(Debug) << "UDisks2 mount job finished: Drive = " << data.dbus_drive_path
+    mounting_jobs_[jobPath].isMount ?
+          HandleFinishedMountJob(partitionData) : HandleFinishedUnmountJob(partitionData, mountedObject);
+  }
+}
+
+void Udisks2Lister::HandleFinishedMountJob(const Udisks2Lister::PartitionData &partitionData) {
+  qLog(Debug) << "UDisks2 mount job finished: Drive = " << partitionData.dbus_drive_path
+              << " | Partition = " << partitionData.dbus_path;
+  QWriteLocker locker(&device_data_lock_);
+  device_data_[partitionData.unique_id()] = partitionData;
+  DeviceAdded(partitionData.unique_id());
+}
+
+void Udisks2Lister::HandleFinishedUnmountJob(const Udisks2Lister::PartitionData &partitionData, const QDBusObjectPath &mountedObject) {
+  QWriteLocker locker(&device_data_lock_);
+  QString id;
+  for (auto &data : device_data_) {
+    if (data.mount_paths.contains(mountedObject.path())) {
+      qLog(Debug) << "UDisks2 umount job finished, found corresponding device: Drive = " << data.dbus_drive_path
                   << " | Partition = " << data.dbus_path;
-      QWriteLocker locker(&device_data_lock_);
-      device_data_[data.unique_id()] = data;
-      DeviceAdded(data.unique_id());
-    } else {
-      QWriteLocker locker(&device_data_lock_);
-      QString id;
-      for (auto &data : device_data_) {
-        if (data.mount_paths.contains(mountedObject.path())) {
-          qLog(Debug) << "UDisks2 umount job finished, found corresponding device: Drive = " << data.dbus_drive_path
-                      << " | Partition = " << data.dbus_path;
-          data.mount_paths.removeOne(mountedObject.path());
-          if (data.mount_paths.empty())
-            id = data.unique_id();
-          break;
-        }
-      }
-
-      if (!id.isEmpty()) {
-        qLog(Debug) << "Partition " << data.dbus_path << " has no more mount points, removing it from device list";
-        device_data_.remove(id);
-        DeviceRemoved(id);
-      }
+      data.mount_paths.removeOne(mountedObject.path());
+      if (data.mount_paths.empty())
+        id = data.unique_id();
+      break;
     }
   }
+
+  if (!id.isEmpty()) {
+    qLog(Debug) << "Partition " << partitionData.dbus_path << " has no more mount points, removing it from device list";
+    device_data_.remove(id);
+    DeviceRemoved(id);
+  }
 }
 
-Udisks2Lister::PartitionData Udisks2Lister::ReadPartitionData(const QDBusObjectPath &path,
-                                                              bool beingMounted) {
+Udisks2Lister::PartitionData Udisks2Lister::ReadPartitionData(const QDBusObjectPath &path) {
   PartitionData result;
   OrgFreedesktopUDisks2FilesystemInterface filesystem(
         udisks2service_,
@@ -314,7 +326,7 @@ Udisks2Lister::PartitionData Udisks2Lister::ReadPartitionData(const QDBusObjectP
 
   if (filesystem.isValid()
       && block.isValid()
-      && (beingMounted || !filesystem.mountPoints().empty())) {
+      && !filesystem.mountPoints().empty()) {
 
     OrgFreedesktopUDisks2DriveInterface drive(
           udisks2service_,
diff --git a/src/devices/udisks2lister.h b/src/devices/udisks2lister.h
index 62d2835..feac8da 100644
--- a/src/devices/udisks2lister.h
+++ b/src/devices/udisks2lister.h
@@ -2,10 +2,15 @@
 
 #include <memory>
 
-#include "devicelister.h"
+#include <QReadWriteLock>
+#include <QMutex>
+#include <QStringList>
+#include <QDBusArgument>
 
-#include "dbus/objectmanager.h"
+#include "devicelister.h"
+#include "dbus/metatypes.h"
 
+class OrgFreedesktopDBusObjectManagerInterface;
 class OrgFreedesktopUDisks2JobInterface;
 
 class Udisks2Lister : public DeviceLister {
@@ -44,9 +49,7 @@ private slots:
   void RemoveDevice(const QDBusObjectPath &devicePath);
   QList<QDBusObjectPath> GetMountedPartitionsFromDBusArgument(const QDBusArgument &input);
 
-  class Udisks2Job
-  {
-  public:
+  struct Udisks2Job {
     bool isMount = true;
     QList<QDBusObjectPath> mounted_partitions;
     std::shared_ptr<OrgFreedesktopUDisks2JobInterface> dbus_interface;
@@ -56,8 +59,7 @@ private slots:
   QMap<QDBusObjectPath, Udisks2Job> mounting_jobs_;
 
 private:
-  class PartitionData {
-  public:
+  struct PartitionData {
     QString unique_id() const;
 
     QString dbus_path;
@@ -77,7 +79,9 @@ private slots:
     QStringList mount_paths;
   };
 
-  PartitionData ReadPartitionData(const QDBusObjectPath &path, bool beingMounted);
+  PartitionData ReadPartitionData(const QDBusObjectPath &path);
+  void HandleFinishedMountJob(const Udisks2Lister::PartitionData &partitionData);
+  void HandleFinishedUnmountJob(const Udisks2Lister::PartitionData &partitionData, const QDBusObjectPath &mountedObject);
 
   QReadWriteLock device_data_lock_;
   QMap<QString, PartitionData> device_data_;

From 0172f7265bd087f65026d584e4679fab54f167fb Mon Sep 17 00:00:00 2001
From: Valeriy <jazzvoid@gmail.com>
Date: Tue, 31 May 2016 18:19:46 +0300
Subject: [PATCH 5/7] fix code style

---
 src/devices/udisks2lister.cpp | 32 ++++++++++++++++----------------
 src/devices/udisks2lister.h   | 37 ++++++++++++++++++++-----------------
 2 files changed, 36 insertions(+), 33 deletions(-)

diff --git a/src/devices/udisks2lister.cpp b/src/devices/udisks2lister.cpp
index 0af1884..ccea4fc 100644
--- a/src/devices/udisks2lister.cpp
+++ b/src/devices/udisks2lister.cpp
@@ -11,14 +11,14 @@
 #include "dbus/udisks2drive.h"
 #include "dbus/udisks2job.h"
 
-const QString Udisks2Lister::udisks2service_ = "org.freedesktop.UDisks2";
+constexpr char Udisks2Lister::udisks2_service_[];
 
 Udisks2Lister::Udisks2Lister() {
 
 }
 
 Udisks2Lister::~Udisks2Lister() {
-  qLog(Debug) << __PRETTY_FUNCTION__;
+
 }
 
 QStringList Udisks2Lister::DeviceUniqueIDs() {
@@ -95,7 +95,7 @@ void Udisks2Lister::UnmountDevice(const QString &id) {
     return;
 
   OrgFreedesktopUDisks2FilesystemInterface filesystem(
-        udisks2service_,
+        udisks2_service_,
         device_data_[id].dbus_path,
         QDBusConnection::systemBus());
 
@@ -110,7 +110,7 @@ void Udisks2Lister::UnmountDevice(const QString &id) {
     }
 
     OrgFreedesktopUDisks2DriveInterface drive(
-          udisks2service_,
+          udisks2_service_,
           device_data_[id].dbus_drive_path,
           QDBusConnection::systemBus());
 
@@ -136,7 +136,7 @@ void Udisks2Lister::UpdateDeviceFreeSpace(const QString &id) {
 
 void Udisks2Lister::Init() {
   udisks2_interface_.reset(new OrgFreedesktopDBusObjectManagerInterface(
-                             udisks2service_,
+                             udisks2_service_,
                              "/org/freedesktop/UDisks2",
                              QDBusConnection::systemBus()));
 
@@ -178,18 +178,18 @@ void Udisks2Lister::DBusInterfaceAdded(const QDBusObjectPath &path,
       continue;
 
     std::shared_ptr<OrgFreedesktopUDisks2JobInterface> job = std::make_shared<OrgFreedesktopUDisks2JobInterface>(
-          udisks2service_,
+          udisks2_service_,
           path.path(),
           QDBusConnection::systemBus());
 
     if (!job->isValid())
       continue;
 
-    bool isMountJob = false;
+    bool is_mount_job = false;
     if (job->operation() == "filesystem-mount")
-      isMountJob = true;
+      is_mount_job = true;
     else if (job->operation() == "filesystem-unmount")
-      isMountJob = false;
+      is_mount_job = false;
     else
       continue;
 
@@ -203,10 +203,10 @@ void Udisks2Lister::DBusInterfaceAdded(const QDBusObjectPath &path,
     {
       QMutexLocker locker(&jobs_lock_);
       qLog(Debug) << "Adding pending job | DBus Path = " << job->path()
-                  << " | IsMountJob = " << isMountJob
+                  << " | IsMountJob = " << is_mount_job
                   << " | First partition = " << mountedPartitions.at(0).path();
       mounting_jobs_[path].dbus_interface = job;
-      mounting_jobs_[path].isMount = isMountJob;
+      mounting_jobs_[path].is_mount = is_mount_job;
       mounting_jobs_[path].mounted_partitions = mountedPartitions;
       connect(job.get(), SIGNAL(Completed(bool, const QString&)),
               SLOT(JobCompleted(bool, const QString&)));
@@ -271,7 +271,7 @@ void Udisks2Lister::JobCompleted(bool success, const QString &message) {
     return;
 
   qLog(Debug) << "Pending Job Completed | Path = " << job->path()
-              << " | Mount? = " << mounting_jobs_[jobPath].isMount
+              << " | Mount? = " << mounting_jobs_[jobPath].is_mount
               << " | Success = " << success;
 
   for (const auto &mountedObject : mounting_jobs_[jobPath].mounted_partitions) {
@@ -279,7 +279,7 @@ void Udisks2Lister::JobCompleted(bool success, const QString &message) {
     if (partitionData.dbus_path.isEmpty())
       continue;
 
-    mounting_jobs_[jobPath].isMount ?
+    mounting_jobs_[jobPath].is_mount ?
           HandleFinishedMountJob(partitionData) : HandleFinishedUnmountJob(partitionData, mountedObject);
   }
 }
@@ -316,11 +316,11 @@ void Udisks2Lister::HandleFinishedUnmountJob(const Udisks2Lister::PartitionData
 Udisks2Lister::PartitionData Udisks2Lister::ReadPartitionData(const QDBusObjectPath &path) {
   PartitionData result;
   OrgFreedesktopUDisks2FilesystemInterface filesystem(
-        udisks2service_,
+        udisks2_service_,
         path.path(),
         QDBusConnection::systemBus());
   OrgFreedesktopUDisks2BlockInterface block(
-        udisks2service_,
+        udisks2_service_,
         path.path(),
         QDBusConnection::systemBus());
 
@@ -329,7 +329,7 @@ Udisks2Lister::PartitionData Udisks2Lister::ReadPartitionData(const QDBusObjectP
       && !filesystem.mountPoints().empty()) {
 
     OrgFreedesktopUDisks2DriveInterface drive(
-          udisks2service_,
+          udisks2_service_,
           block.drive().path(),
           QDBusConnection::systemBus());
 
diff --git a/src/devices/udisks2lister.h b/src/devices/udisks2lister.h
index feac8da..1143d74 100644
--- a/src/devices/udisks2lister.h
+++ b/src/devices/udisks2lister.h
@@ -1,11 +1,12 @@
-#pragma once
+#ifndef UDISKS2LISTER_H
+#define UDISKS2LISTER_H
 
 #include <memory>
 
-#include <QReadWriteLock>
+#include <QDBusArgument>
 #include <QMutex>
+#include <QReadWriteLock>
 #include <QStringList>
-#include <QDBusArgument>
 
 #include "devicelister.h"
 #include "dbus/metatypes.h"
@@ -20,24 +21,24 @@ class Udisks2Lister : public DeviceLister {
   Udisks2Lister();
   ~Udisks2Lister();
 
-  QStringList DeviceUniqueIDs();
-  QVariantList DeviceIcons(const QString &id);
-  QString DeviceManufacturer(const QString &id);
-  QString DeviceModel(const QString &id);
-  quint64 DeviceCapacity(const QString &id);
-  quint64 DeviceFreeSpace(const QString &id);
-  QVariantMap DeviceHardwareInfo(const QString &id);
+  QStringList DeviceUniqueIDs() override;
+  QVariantList DeviceIcons(const QString &id) override;
+  QString DeviceManufacturer(const QString &id) override;
+  QString DeviceModel(const QString &id) override;
+  quint64 DeviceCapacity(const QString &id) override;
+  quint64 DeviceFreeSpace(const QString &id) override;
+  QVariantMap DeviceHardwareInfo(const QString &id) override;
 
-  QString MakeFriendlyName(const QString &id);
-  QList<QUrl> MakeDeviceUrls(const QString &id);
+  QString MakeFriendlyName(const QString &id) override;
+  QList<QUrl> MakeDeviceUrls(const QString &id) override;
 
-  void UnmountDevice(const QString &id);
+  void UnmountDevice(const QString &id) override;
 
 public slots:
-  void UpdateDeviceFreeSpace(const QString &id);
+  void UpdateDeviceFreeSpace(const QString &id) override;
 
 protected:
-  void Init();
+  void Init() override;
 
 private slots:
   void DBusInterfaceAdded(const QDBusObjectPath &path, const InterfacesAndProperties &ifaces);
@@ -50,7 +51,7 @@ private slots:
   QList<QDBusObjectPath> GetMountedPartitionsFromDBusArgument(const QDBusArgument &input);
 
   struct Udisks2Job {
-    bool isMount = true;
+    bool is_mount = true;
     QList<QDBusObjectPath> mounted_partitions;
     std::shared_ptr<OrgFreedesktopUDisks2JobInterface> dbus_interface;
   };
@@ -89,5 +90,7 @@ private slots:
 private:
   std::unique_ptr<OrgFreedesktopDBusObjectManagerInterface> udisks2_interface_;
 
-  static const QString udisks2service_;
+  static constexpr char udisks2_service_[] = "org.freedesktop.UDisks2";
 };
+
+#endif // UDISKS2LISTER_H

From 1812f089b02b1abb98545968e40fc63b4ac330a2 Mon Sep 17 00:00:00 2001
From: Valeriy <jazzvoid@gmail.com>
Date: Tue, 31 May 2016 18:31:00 +0300
Subject: [PATCH 6/7] feed udisks2lister.* through format.py add copyright
 headers

---
 src/devices/udisks2lister.cpp | 235 +++++++++++++++++++++---------------------
 src/devices/udisks2lister.h   |  77 +++++++++-----
 2 files changed, 166 insertions(+), 146 deletions(-)

diff --git a/src/devices/udisks2lister.cpp b/src/devices/udisks2lister.cpp
index ccea4fc..289383e 100644
--- a/src/devices/udisks2lister.cpp
+++ b/src/devices/udisks2lister.cpp
@@ -1,71 +1,78 @@
+/* This file is part of Clementine.
+   Copyright 2016, Valeriy Malov <jazzvoid@gmail.com>
+
+   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 <http://www.gnu.org/licenses/>.
+*/
+
 #include "udisks2lister.h"
 
 #include <QDBusConnection>
 
 #include "core/logging.h"
 #include "core/utilities.h"
-
 #include "dbus/objectmanager.h"
-#include "dbus/udisks2filesystem.h"
 #include "dbus/udisks2block.h"
 #include "dbus/udisks2drive.h"
+#include "dbus/udisks2filesystem.h"
 #include "dbus/udisks2job.h"
 
 constexpr char Udisks2Lister::udisks2_service_[];
 
-Udisks2Lister::Udisks2Lister() {
+Udisks2Lister::Udisks2Lister() {}
 
-}
-
-Udisks2Lister::~Udisks2Lister() {
-
-}
+Udisks2Lister::~Udisks2Lister() {}
 
 QStringList Udisks2Lister::DeviceUniqueIDs() {
   QReadLocker locker(&device_data_lock_);
   return device_data_.keys();
 }
 
-QVariantList Udisks2Lister::DeviceIcons(const QString &id) {
+QVariantList Udisks2Lister::DeviceIcons(const QString& id) {
   return QVariantList();
 }
 
-QString Udisks2Lister::DeviceManufacturer(const QString &id) {
+QString Udisks2Lister::DeviceManufacturer(const QString& id) {
   QReadLocker locker(&device_data_lock_);
-  if (!device_data_.contains(id))
-    return "";
+  if (!device_data_.contains(id)) return "";
   return device_data_[id].vendor;
 }
 
-QString Udisks2Lister::DeviceModel(const QString &id) {
+QString Udisks2Lister::DeviceModel(const QString& id) {
   QReadLocker locker(&device_data_lock_);
-  if (!device_data_.contains(id))
-    return "";
+  if (!device_data_.contains(id)) return "";
   return device_data_[id].model;
 }
 
-quint64 Udisks2Lister::DeviceCapacity(const QString &id) {
+quint64 Udisks2Lister::DeviceCapacity(const QString& id) {
   QReadLocker locker(&device_data_lock_);
-  if (!device_data_.contains(id))
-    return 0;
+  if (!device_data_.contains(id)) return 0;
   return device_data_[id].capacity;
 }
 
-quint64 Udisks2Lister::DeviceFreeSpace(const QString &id) {
+quint64 Udisks2Lister::DeviceFreeSpace(const QString& id) {
   QReadLocker locker(&device_data_lock_);
-  if (!device_data_.contains(id))
-    return 0;
+  if (!device_data_.contains(id)) return 0;
   return device_data_[id].free_space;
 }
 
-QVariantMap Udisks2Lister::DeviceHardwareInfo(const QString &id) {
+QVariantMap Udisks2Lister::DeviceHardwareInfo(const QString& id) {
   QReadLocker locker(&device_data_lock_);
-  if (!device_data_.contains(id))
-    return QVariantMap();
+  if (!device_data_.contains(id)) return QVariantMap();
 
   QVariantMap result;
 
-  const auto &data = device_data_[id];
+  const auto& data = device_data_[id];
   result[QT_TR_NOOP("DBus path")] = data.dbus_path;
   result[QT_TR_NOOP("Serial number")] = data.serial;
   result[QT_TR_NOOP("Mount points")] = data.mount_paths.join(", ");
@@ -75,51 +82,48 @@ QVariantMap Udisks2Lister::DeviceHardwareInfo(const QString &id) {
   return result;
 }
 
-QString Udisks2Lister::MakeFriendlyName(const QString &id) {
+QString Udisks2Lister::MakeFriendlyName(const QString& id) {
   QReadLocker locker(&device_data_lock_);
-  if (!device_data_.contains(id))
-    return "";
+  if (!device_data_.contains(id)) return "";
   return device_data_[id].friendly_name;
 }
 
-QList<QUrl> Udisks2Lister::MakeDeviceUrls(const QString &id) {
+QList<QUrl> Udisks2Lister::MakeDeviceUrls(const QString& id) {
   QReadLocker locker(&device_data_lock_);
-  if (!device_data_.contains(id))
-    return QList<QUrl>();
-  return QList<QUrl>() << QUrl::fromLocalFile(device_data_[id].mount_paths.at(0));
+  if (!device_data_.contains(id)) return QList<QUrl>();
+  return QList<QUrl>() << QUrl::fromLocalFile(
+             device_data_[id].mount_paths.at(0));
 }
 
-void Udisks2Lister::UnmountDevice(const QString &id) {
+void Udisks2Lister::UnmountDevice(const QString& id) {
   QReadLocker locker(&device_data_lock_);
-  if (!device_data_.contains(id))
-    return;
+  if (!device_data_.contains(id)) return;
 
   OrgFreedesktopUDisks2FilesystemInterface filesystem(
-        udisks2_service_,
-        device_data_[id].dbus_path,
-        QDBusConnection::systemBus());
+      udisks2_service_, device_data_[id].dbus_path,
+      QDBusConnection::systemBus());
 
-  if (filesystem.isValid())
-  {
+  if (filesystem.isValid()) {
     auto unmountResult = filesystem.Unmount(QVariantMap());
     unmountResult.waitForFinished();
 
     if (unmountResult.isError()) {
-      qLog(Warning) << "Failed to unmount " << id << ": " << unmountResult.error();
+      qLog(Warning) << "Failed to unmount " << id << ": "
+                    << unmountResult.error();
       return;
     }
 
-    OrgFreedesktopUDisks2DriveInterface drive(
-          udisks2_service_,
-          device_data_[id].dbus_drive_path,
-          QDBusConnection::systemBus());
+    OrgFreedesktopUDisks2DriveInterface drive(udisks2_service_,
+                                              device_data_[id].dbus_drive_path,
+                                              QDBusConnection::systemBus());
 
     if (drive.isValid()) {
       auto ejectResult = drive.Eject(QVariantMap());
       ejectResult.waitForFinished();
 
       if (ejectResult.isError())
-        qLog(Warning) << "Failed to eject " << id << ": " << ejectResult.error();
+        qLog(Warning) << "Failed to eject " << id << ": "
+                      << ejectResult.error();
     }
 
     device_data_.remove(id);
@@ -127,20 +131,21 @@ void Udisks2Lister::UnmountDevice(const QString &id) {
   }
 }
 
-void Udisks2Lister::UpdateDeviceFreeSpace(const QString &id) {
+void Udisks2Lister::UpdateDeviceFreeSpace(const QString& id) {
   QWriteLocker locker(&device_data_lock_);
-  device_data_[id].free_space = Utilities::FileSystemFreeSpace(device_data_[id].mount_paths.at(0));
+  device_data_[id].free_space =
+      Utilities::FileSystemFreeSpace(device_data_[id].mount_paths.at(0));
 
   emit DeviceChanged(id);
 }
 
 void Udisks2Lister::Init() {
   udisks2_interface_.reset(new OrgFreedesktopDBusObjectManagerInterface(
-                             udisks2_service_,
-                             "/org/freedesktop/UDisks2",
-                             QDBusConnection::systemBus()));
+      udisks2_service_, "/org/freedesktop/UDisks2",
+      QDBusConnection::systemBus()));
 
-  QDBusPendingReply<ManagedObjectList> reply = udisks2_interface_->GetManagedObjects();
+  QDBusPendingReply<ManagedObjectList> reply =
+      udisks2_interface_->GetManagedObjects();
   reply.waitForFinished();
 
   if (!reply.isValid()) {
@@ -150,40 +155,38 @@ void Udisks2Lister::Init() {
     return;
   }
 
-  for (const QDBusObjectPath &path : reply.value().keys()) {
+  for (const QDBusObjectPath& path : reply.value().keys()) {
     auto partitionData = ReadPartitionData(path);
 
-    if (!partitionData.dbus_path.isEmpty())
-    {
+    if (!partitionData.dbus_path.isEmpty()) {
       QWriteLocker locker(&device_data_lock_);
       device_data_[partitionData.unique_id()] = partitionData;
     }
   }
 
-  for (const auto &id : device_data_.keys()) {
+  for (const auto& id : device_data_.keys()) {
     emit DeviceAdded(id);
   }
 
-  connect(udisks2_interface_.get(), SIGNAL(InterfacesAdded(QDBusObjectPath, InterfacesAndProperties)),
+  connect(udisks2_interface_.get(),
+          SIGNAL(InterfacesAdded(QDBusObjectPath, InterfacesAndProperties)),
           SLOT(DBusInterfaceAdded(QDBusObjectPath, InterfacesAndProperties)));
-  connect(udisks2_interface_.get(), SIGNAL(InterfacesRemoved(QDBusObjectPath, QStringList)),
+  connect(udisks2_interface_.get(),
+          SIGNAL(InterfacesRemoved(QDBusObjectPath, QStringList)),
           SLOT(DBusInterfaceRemoved(QDBusObjectPath, QStringList)));
 }
 
-void Udisks2Lister::DBusInterfaceAdded(const QDBusObjectPath &path,
-                                       const InterfacesAndProperties &interfaces) {
-  for (auto interface = interfaces.constBegin(); interface != interfaces.constEnd(); ++interface)
-  {
-    if (interface.key() != "org.freedesktop.UDisks2.Job")
-      continue;
+void Udisks2Lister::DBusInterfaceAdded(
+    const QDBusObjectPath& path, const InterfacesAndProperties& interfaces) {
+  for (auto interface = interfaces.constBegin();
+       interface != interfaces.constEnd(); ++interface) {
+    if (interface.key() != "org.freedesktop.UDisks2.Job") continue;
 
-    std::shared_ptr<OrgFreedesktopUDisks2JobInterface> job = std::make_shared<OrgFreedesktopUDisks2JobInterface>(
-          udisks2_service_,
-          path.path(),
-          QDBusConnection::systemBus());
+    std::shared_ptr<OrgFreedesktopUDisks2JobInterface> job =
+        std::make_shared<OrgFreedesktopUDisks2JobInterface>(
+            udisks2_service_, path.path(), QDBusConnection::systemBus());
 
-    if (!job->isValid())
-      continue;
+    if (!job->isValid()) continue;
 
     bool is_mount_job = false;
     if (job->operation() == "filesystem-mount")
@@ -214,40 +217,39 @@ void Udisks2Lister::DBusInterfaceAdded(const QDBusObjectPath &path,
   }
 }
 
-void Udisks2Lister::DBusInterfaceRemoved(const QDBusObjectPath &path, const QStringList &ifaces) {
-  if (!isPendingJob(path))
-    RemoveDevice(path);
+void Udisks2Lister::DBusInterfaceRemoved(const QDBusObjectPath& path,
+                                         const QStringList& ifaces) {
+  if (!isPendingJob(path)) RemoveDevice(path);
 }
 
-bool Udisks2Lister::isPendingJob(const QDBusObjectPath &jobPath) {
+bool Udisks2Lister::isPendingJob(const QDBusObjectPath& jobPath) {
   QMutexLocker locker(&jobs_lock_);
 
-  if (!mounting_jobs_.contains(jobPath))
-    return false;
+  if (!mounting_jobs_.contains(jobPath)) return false;
 
   mounting_jobs_.remove(jobPath);
   return true;
 }
 
-void Udisks2Lister::RemoveDevice(const QDBusObjectPath &devicePath) {
+void Udisks2Lister::RemoveDevice(const QDBusObjectPath& devicePath) {
   QWriteLocker locker(&device_data_lock_);
   QString id;
-  for (const auto &data : device_data_) {
+  for (const auto& data : device_data_) {
     if (data.dbus_path == devicePath.path()) {
       id = data.unique_id();
       break;
     }
   }
 
-  if (id.isEmpty())
-    return;
+  if (id.isEmpty()) return;
 
   qLog(Debug) << "UDisks2 device removed: " << devicePath.path();
   device_data_.remove(id);
   DeviceRemoved(id);
 }
 
-QList<QDBusObjectPath> Udisks2Lister::GetMountedPartitionsFromDBusArgument(const QDBusArgument &input) {
+QList<QDBusObjectPath> Udisks2Lister::GetMountedPartitionsFromDBusArgument(
+    const QDBusArgument& input) {
   QList<QDBusObjectPath> result;
 
   input.beginArray();
@@ -261,80 +263,74 @@ QList<QDBusObjectPath> Udisks2Lister::GetMountedPartitionsFromDBusArgument(const
   return result;
 }
 
-void Udisks2Lister::JobCompleted(bool success, const QString &message) {
+void Udisks2Lister::JobCompleted(bool success, const QString& message) {
   auto job = qobject_cast<OrgFreedesktopUDisks2JobInterface*>(sender());
   QDBusObjectPath jobPath(job->path());
 
-  if (!job->isValid()
-      || !success
-      || !mounting_jobs_.contains(jobPath))
-    return;
+  if (!job->isValid() || !success || !mounting_jobs_.contains(jobPath)) return;
 
   qLog(Debug) << "Pending Job Completed | Path = " << job->path()
               << " | Mount? = " << mounting_jobs_[jobPath].is_mount
               << " | Success = " << success;
 
-  for (const auto &mountedObject : mounting_jobs_[jobPath].mounted_partitions) {
+  for (const auto& mountedObject : mounting_jobs_[jobPath].mounted_partitions) {
     auto partitionData = ReadPartitionData(mountedObject);
-    if (partitionData.dbus_path.isEmpty())
-      continue;
+    if (partitionData.dbus_path.isEmpty()) continue;
 
-    mounting_jobs_[jobPath].is_mount ?
-          HandleFinishedMountJob(partitionData) : HandleFinishedUnmountJob(partitionData, mountedObject);
+    mounting_jobs_[jobPath].is_mount
+        ? HandleFinishedMountJob(partitionData)
+        : HandleFinishedUnmountJob(partitionData, mountedObject);
   }
 }
 
-void Udisks2Lister::HandleFinishedMountJob(const Udisks2Lister::PartitionData &partitionData) {
-  qLog(Debug) << "UDisks2 mount job finished: Drive = " << partitionData.dbus_drive_path
+void Udisks2Lister::HandleFinishedMountJob(
+    const Udisks2Lister::PartitionData& partitionData) {
+  qLog(Debug) << "UDisks2 mount job finished: Drive = "
+              << partitionData.dbus_drive_path
               << " | Partition = " << partitionData.dbus_path;
   QWriteLocker locker(&device_data_lock_);
   device_data_[partitionData.unique_id()] = partitionData;
   DeviceAdded(partitionData.unique_id());
 }
 
-void Udisks2Lister::HandleFinishedUnmountJob(const Udisks2Lister::PartitionData &partitionData, const QDBusObjectPath &mountedObject) {
+void Udisks2Lister::HandleFinishedUnmountJob(
+    const Udisks2Lister::PartitionData& partitionData,
+    const QDBusObjectPath& mountedObject) {
   QWriteLocker locker(&device_data_lock_);
   QString id;
-  for (auto &data : device_data_) {
+  for (auto& data : device_data_) {
     if (data.mount_paths.contains(mountedObject.path())) {
-      qLog(Debug) << "UDisks2 umount job finished, found corresponding device: Drive = " << data.dbus_drive_path
-                  << " | Partition = " << data.dbus_path;
+      qLog(Debug)
+          << "UDisks2 umount job finished, found corresponding device: Drive = "
+          << data.dbus_drive_path << " | Partition = " << data.dbus_path;
       data.mount_paths.removeOne(mountedObject.path());
-      if (data.mount_paths.empty())
-        id = data.unique_id();
+      if (data.mount_paths.empty()) id = data.unique_id();
       break;
     }
   }
 
   if (!id.isEmpty()) {
-    qLog(Debug) << "Partition " << partitionData.dbus_path << " has no more mount points, removing it from device list";
+    qLog(Debug) << "Partition " << partitionData.dbus_path
+                << " has no more mount points, removing it from device list";
     device_data_.remove(id);
     DeviceRemoved(id);
   }
 }
 
-Udisks2Lister::PartitionData Udisks2Lister::ReadPartitionData(const QDBusObjectPath &path) {
+Udisks2Lister::PartitionData Udisks2Lister::ReadPartitionData(
+    const QDBusObjectPath& path) {
   PartitionData result;
   OrgFreedesktopUDisks2FilesystemInterface filesystem(
-        udisks2_service_,
-        path.path(),
-        QDBusConnection::systemBus());
-  OrgFreedesktopUDisks2BlockInterface block(
-        udisks2_service_,
-        path.path(),
-        QDBusConnection::systemBus());
-
-  if (filesystem.isValid()
-      && block.isValid()
-      && !filesystem.mountPoints().empty()) {
+      udisks2_service_, path.path(), QDBusConnection::systemBus());
+  OrgFreedesktopUDisks2BlockInterface block(udisks2_service_, path.path(),
+                                            QDBusConnection::systemBus());
 
+  if (filesystem.isValid() && block.isValid() &&
+      !filesystem.mountPoints().empty()) {
     OrgFreedesktopUDisks2DriveInterface drive(
-          udisks2_service_,
-          block.drive().path(),
-          QDBusConnection::systemBus());
+        udisks2_service_, block.drive().path(), QDBusConnection::systemBus());
 
-    if (drive.isValid()
-        && drive.mediaRemovable()) {
+    if (drive.isValid() && drive.mediaRemovable()) {
       result.dbus_path = path.path();
       result.dbus_drive_path = block.drive().path();
 
@@ -351,10 +347,11 @@ Udisks2Lister::PartitionData Udisks2Lister::ReadPartitionData(const QDBusObjectP
       else
         result.friendly_name = result.model + " " + result.uuid;
 
-      for (const auto &path : filesystem.mountPoints())
+      for (const auto& path : filesystem.mountPoints())
         result.mount_paths.push_back(path);
 
-      result.free_space = Utilities::FileSystemFreeSpace(result.mount_paths.at(0));
+      result.free_space =
+          Utilities::FileSystemFreeSpace(result.mount_paths.at(0));
     }
   }
 
diff --git a/src/devices/udisks2lister.h b/src/devices/udisks2lister.h
index 1143d74..8cf03f3 100644
--- a/src/devices/udisks2lister.h
+++ b/src/devices/udisks2lister.h
@@ -1,3 +1,20 @@
+/* This file is part of Clementine.
+   Copyright 2016, Valeriy Malov <jazzvoid@gmail.com>
+
+   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 <http://www.gnu.org/licenses/>.
+*/
+
 #ifndef UDISKS2LISTER_H
 #define UDISKS2LISTER_H
 
@@ -17,38 +34,41 @@ class OrgFreedesktopUDisks2JobInterface;
 class Udisks2Lister : public DeviceLister {
   Q_OBJECT
 
-public:
+ public:
   Udisks2Lister();
   ~Udisks2Lister();
 
   QStringList DeviceUniqueIDs() override;
-  QVariantList DeviceIcons(const QString &id) override;
-  QString DeviceManufacturer(const QString &id) override;
-  QString DeviceModel(const QString &id) override;
-  quint64 DeviceCapacity(const QString &id) override;
-  quint64 DeviceFreeSpace(const QString &id) override;
-  QVariantMap DeviceHardwareInfo(const QString &id) override;
+  QVariantList DeviceIcons(const QString& id) override;
+  QString DeviceManufacturer(const QString& id) override;
+  QString DeviceModel(const QString& id) override;
+  quint64 DeviceCapacity(const QString& id) override;
+  quint64 DeviceFreeSpace(const QString& id) override;
+  QVariantMap DeviceHardwareInfo(const QString& id) override;
 
-  QString MakeFriendlyName(const QString &id) override;
-  QList<QUrl> MakeDeviceUrls(const QString &id) override;
+  QString MakeFriendlyName(const QString& id) override;
+  QList<QUrl> MakeDeviceUrls(const QString& id) override;
 
-  void UnmountDevice(const QString &id) override;
+  void UnmountDevice(const QString& id) override;
 
-public slots:
-  void UpdateDeviceFreeSpace(const QString &id) override;
+ public slots:
+  void UpdateDeviceFreeSpace(const QString& id) override;
 
-protected:
+ protected:
   void Init() override;
 
-private slots:
-  void DBusInterfaceAdded(const QDBusObjectPath &path, const InterfacesAndProperties &ifaces);
-  void DBusInterfaceRemoved(const QDBusObjectPath &path, const QStringList &ifaces);
-  void JobCompleted(bool success, const QString &message);
+ private slots:
+  void DBusInterfaceAdded(const QDBusObjectPath& path,
+                          const InterfacesAndProperties& ifaces);
+  void DBusInterfaceRemoved(const QDBusObjectPath& path,
+                            const QStringList& ifaces);
+  void JobCompleted(bool success, const QString& message);
 
-private:
-  bool isPendingJob(const QDBusObjectPath &jobPath);
-  void RemoveDevice(const QDBusObjectPath &devicePath);
-  QList<QDBusObjectPath> GetMountedPartitionsFromDBusArgument(const QDBusArgument &input);
+ private:
+  bool isPendingJob(const QDBusObjectPath& jobPath);
+  void RemoveDevice(const QDBusObjectPath& devicePath);
+  QList<QDBusObjectPath> GetMountedPartitionsFromDBusArgument(
+      const QDBusArgument& input);
 
   struct Udisks2Job {
     bool is_mount = true;
@@ -59,7 +79,7 @@ private slots:
   QMutex jobs_lock_;
   QMap<QDBusObjectPath, Udisks2Job> mounting_jobs_;
 
-private:
+ private:
   struct PartitionData {
     QString unique_id() const;
 
@@ -80,17 +100,20 @@ private slots:
     QStringList mount_paths;
   };
 
-  PartitionData ReadPartitionData(const QDBusObjectPath &path);
-  void HandleFinishedMountJob(const Udisks2Lister::PartitionData &partitionData);
-  void HandleFinishedUnmountJob(const Udisks2Lister::PartitionData &partitionData, const QDBusObjectPath &mountedObject);
+  PartitionData ReadPartitionData(const QDBusObjectPath& path);
+  void HandleFinishedMountJob(
+      const Udisks2Lister::PartitionData& partitionData);
+  void HandleFinishedUnmountJob(
+      const Udisks2Lister::PartitionData& partitionData,
+      const QDBusObjectPath& mountedObject);
 
   QReadWriteLock device_data_lock_;
   QMap<QString, PartitionData> device_data_;
 
-private:
+ private:
   std::unique_ptr<OrgFreedesktopDBusObjectManagerInterface> udisks2_interface_;
 
   static constexpr char udisks2_service_[] = "org.freedesktop.UDisks2";
 };
 
-#endif // UDISKS2LISTER_H
+#endif  // UDISKS2LISTER_H

From ecaa9de7883eb0d68b5efcf3616a3b6865cffcb6 Mon Sep 17 00:00:00 2001
From: Valeriy <jazzvoid@gmail.com>
Date: Tue, 31 May 2016 20:31:39 +0300
Subject: [PATCH 7/7] fix variable names

---
 src/devices/udisks2lister.cpp | 80 ++++++++++++++++++++++---------------------
 src/devices/udisks2lister.h   | 10 +++---
 2 files changed, 46 insertions(+), 44 deletions(-)

diff --git a/src/devices/udisks2lister.cpp b/src/devices/udisks2lister.cpp
index 289383e..c5c72ef 100644
--- a/src/devices/udisks2lister.cpp
+++ b/src/devices/udisks2lister.cpp
@@ -104,12 +104,12 @@ void Udisks2Lister::UnmountDevice(const QString& id) {
       QDBusConnection::systemBus());
 
   if (filesystem.isValid()) {
-    auto unmountResult = filesystem.Unmount(QVariantMap());
-    unmountResult.waitForFinished();
+    auto unmount_result = filesystem.Unmount(QVariantMap());
+    unmount_result.waitForFinished();
 
-    if (unmountResult.isError()) {
+    if (unmount_result.isError()) {
       qLog(Warning) << "Failed to unmount " << id << ": "
-                    << unmountResult.error();
+                    << unmount_result.error();
       return;
     }
 
@@ -118,12 +118,12 @@ void Udisks2Lister::UnmountDevice(const QString& id) {
                                               QDBusConnection::systemBus());
 
     if (drive.isValid()) {
-      auto ejectResult = drive.Eject(QVariantMap());
-      ejectResult.waitForFinished();
+      auto eject_result = drive.Eject(QVariantMap());
+      eject_result.waitForFinished();
 
-      if (ejectResult.isError())
+      if (eject_result.isError())
         qLog(Warning) << "Failed to eject " << id << ": "
-                      << ejectResult.error();
+                      << eject_result.error();
     }
 
     device_data_.remove(id);
@@ -156,11 +156,11 @@ void Udisks2Lister::Init() {
   }
 
   for (const QDBusObjectPath& path : reply.value().keys()) {
-    auto partitionData = ReadPartitionData(path);
+    auto partition_data = ReadPartitionData(path);
 
-    if (!partitionData.dbus_path.isEmpty()) {
+    if (!partition_data.dbus_path.isEmpty()) {
       QWriteLocker locker(&device_data_lock_);
-      device_data_[partitionData.unique_id()] = partitionData;
+      device_data_[partition_data.unique_id()] = partition_data;
     }
   }
 
@@ -189,16 +189,17 @@ void Udisks2Lister::DBusInterfaceAdded(
     if (!job->isValid()) continue;
 
     bool is_mount_job = false;
-    if (job->operation() == "filesystem-mount")
+    if (job->operation() == "filesystem-mount") {
       is_mount_job = true;
-    else if (job->operation() == "filesystem-unmount")
+    } else if (job->operation() == "filesystem-unmount") {
       is_mount_job = false;
-    else
+    } else {
       continue;
+    }
 
-    auto mountedPartitions = job->objects();
+    auto mounted_partitions = job->objects();
 
-    if (mountedPartitions.isEmpty()) {
+    if (mounted_partitions.isEmpty()) {
       qLog(Warning) << "Empty Udisks2 mount/umount job " << path.path();
       continue;
     }
@@ -207,10 +208,10 @@ void Udisks2Lister::DBusInterfaceAdded(
       QMutexLocker locker(&jobs_lock_);
       qLog(Debug) << "Adding pending job | DBus Path = " << job->path()
                   << " | IsMountJob = " << is_mount_job
-                  << " | First partition = " << mountedPartitions.at(0).path();
+                  << " | First partition = " << mounted_partitions.at(0).path();
       mounting_jobs_[path].dbus_interface = job;
       mounting_jobs_[path].is_mount = is_mount_job;
-      mounting_jobs_[path].mounted_partitions = mountedPartitions;
+      mounting_jobs_[path].mounted_partitions = mounted_partitions;
       connect(job.get(), SIGNAL(Completed(bool, const QString&)),
               SLOT(JobCompleted(bool, const QString&)));
     }
@@ -222,20 +223,20 @@ void Udisks2Lister::DBusInterfaceRemoved(const QDBusObjectPath& path,
   if (!isPendingJob(path)) RemoveDevice(path);
 }
 
-bool Udisks2Lister::isPendingJob(const QDBusObjectPath& jobPath) {
+bool Udisks2Lister::isPendingJob(const QDBusObjectPath& job_path) {
   QMutexLocker locker(&jobs_lock_);
 
-  if (!mounting_jobs_.contains(jobPath)) return false;
+  if (!mounting_jobs_.contains(job_path)) return false;
 
-  mounting_jobs_.remove(jobPath);
+  mounting_jobs_.remove(job_path);
   return true;
 }
 
-void Udisks2Lister::RemoveDevice(const QDBusObjectPath& devicePath) {
+void Udisks2Lister::RemoveDevice(const QDBusObjectPath& device_path) {
   QWriteLocker locker(&device_data_lock_);
   QString id;
   for (const auto& data : device_data_) {
-    if (data.dbus_path == devicePath.path()) {
+    if (data.dbus_path == device_path.path()) {
       id = data.unique_id();
       break;
     }
@@ -243,7 +244,7 @@ void Udisks2Lister::RemoveDevice(const QDBusObjectPath& devicePath) {
 
   if (id.isEmpty()) return;
 
-  qLog(Debug) << "UDisks2 device removed: " << devicePath.path();
+  qLog(Debug) << "UDisks2 device removed: " << device_path.path();
   device_data_.remove(id);
   DeviceRemoved(id);
 }
@@ -273,44 +274,45 @@ void Udisks2Lister::JobCompleted(bool success, const QString& message) {
               << " | Mount? = " << mounting_jobs_[jobPath].is_mount
               << " | Success = " << success;
 
-  for (const auto& mountedObject : mounting_jobs_[jobPath].mounted_partitions) {
-    auto partitionData = ReadPartitionData(mountedObject);
-    if (partitionData.dbus_path.isEmpty()) continue;
+  for (const auto& mounted_object :
+       mounting_jobs_[jobPath].mounted_partitions) {
+    auto partition_data = ReadPartitionData(mounted_object);
+    if (partition_data.dbus_path.isEmpty()) continue;
 
     mounting_jobs_[jobPath].is_mount
-        ? HandleFinishedMountJob(partitionData)
-        : HandleFinishedUnmountJob(partitionData, mountedObject);
+        ? HandleFinishedMountJob(partition_data)
+        : HandleFinishedUnmountJob(partition_data, mounted_object);
   }
 }
 
 void Udisks2Lister::HandleFinishedMountJob(
-    const Udisks2Lister::PartitionData& partitionData) {
+    const Udisks2Lister::PartitionData& partition_data) {
   qLog(Debug) << "UDisks2 mount job finished: Drive = "
-              << partitionData.dbus_drive_path
-              << " | Partition = " << partitionData.dbus_path;
+              << partition_data.dbus_drive_path
+              << " | Partition = " << partition_data.dbus_path;
   QWriteLocker locker(&device_data_lock_);
-  device_data_[partitionData.unique_id()] = partitionData;
-  DeviceAdded(partitionData.unique_id());
+  device_data_[partition_data.unique_id()] = partition_data;
+  DeviceAdded(partition_data.unique_id());
 }
 
 void Udisks2Lister::HandleFinishedUnmountJob(
-    const Udisks2Lister::PartitionData& partitionData,
-    const QDBusObjectPath& mountedObject) {
+    const Udisks2Lister::PartitionData& partition_data,
+    const QDBusObjectPath& mounted_object) {
   QWriteLocker locker(&device_data_lock_);
   QString id;
   for (auto& data : device_data_) {
-    if (data.mount_paths.contains(mountedObject.path())) {
+    if (data.mount_paths.contains(mounted_object.path())) {
       qLog(Debug)
           << "UDisks2 umount job finished, found corresponding device: Drive = "
           << data.dbus_drive_path << " | Partition = " << data.dbus_path;
-      data.mount_paths.removeOne(mountedObject.path());
+      data.mount_paths.removeOne(mounted_object.path());
       if (data.mount_paths.empty()) id = data.unique_id();
       break;
     }
   }
 
   if (!id.isEmpty()) {
-    qLog(Debug) << "Partition " << partitionData.dbus_path
+    qLog(Debug) << "Partition " << partition_data.dbus_path
                 << " has no more mount points, removing it from device list";
     device_data_.remove(id);
     DeviceRemoved(id);
diff --git a/src/devices/udisks2lister.h b/src/devices/udisks2lister.h
index 8cf03f3..3a2a012 100644
--- a/src/devices/udisks2lister.h
+++ b/src/devices/udisks2lister.h
@@ -65,8 +65,8 @@ class Udisks2Lister : public DeviceLister {
   void JobCompleted(bool success, const QString& message);
 
  private:
-  bool isPendingJob(const QDBusObjectPath& jobPath);
-  void RemoveDevice(const QDBusObjectPath& devicePath);
+  bool isPendingJob(const QDBusObjectPath& job_path);
+  void RemoveDevice(const QDBusObjectPath& device_path);
   QList<QDBusObjectPath> GetMountedPartitionsFromDBusArgument(
       const QDBusArgument& input);
 
@@ -102,10 +102,10 @@ class Udisks2Lister : public DeviceLister {
 
   PartitionData ReadPartitionData(const QDBusObjectPath& path);
   void HandleFinishedMountJob(
-      const Udisks2Lister::PartitionData& partitionData);
+      const Udisks2Lister::PartitionData& partition_data);
   void HandleFinishedUnmountJob(
-      const Udisks2Lister::PartitionData& partitionData,
-      const QDBusObjectPath& mountedObject);
+      const Udisks2Lister::PartitionData& partition_data,
+      const QDBusObjectPath& mounted_object);
 
   QReadWriteLock device_data_lock_;
   QMap<QString, PartitionData> device_data_;
openSUSE Build Service is sponsored by