Commit acbd5676 authored by Raine Makelainen's avatar Raine Makelainen

Merge branch 'jb40936' into 'master'

[nemo-systemsettings] Change PartitionManager to use Udisks2. Contributes to JB#40936

See merge request !46
parents f87ef524 0b3114a0
......@@ -22,6 +22,7 @@ BuildRequires: pkgconfig(usb-moded-qt5)
BuildRequires: pkgconfig(libshadowutils)
BuildRequires: pkgconfig(blkid)
BuildRequires: pkgconfig(libcrypto)
BuildRequires: pkgconfig(nemodbus) >= 2.1.16
BuildRequires: pkgconfig(nemomodels-qt5)
BuildRequires: pkgconfig(libsailfishkeyprovider) >= 0.0.14
BuildRequires: pkgconfig(connman-qt5)
......
......@@ -32,99 +32,6 @@
#include "partition_p.h"
#include "partitionmanager_p.h"
static const auto systemdService = QStringLiteral("org.freedesktop.systemd1");
static const auto systemdPath = QStringLiteral("/org/freedesktop/systemd1");
static const auto propertiesInterface = QStringLiteral("org.freedesktop.DBus.Properties");
static const auto unitInterface = QStringLiteral("org.freedesktop.systemd1.Unit");
static const auto managerInterface = QStringLiteral("org.freedesktop.systemd1.Manager");
static const auto activeStateProperty = QStringLiteral("ActiveState");
void PartitionPrivate::getUnit()
{
if (storageType != Partition::External) {
return;
}
const QString serviceName = QStringLiteral("mount-sd@") + deviceName + QStringLiteral(".service");
Q_ASSERT(!pendingCall);
Q_ASSERT(unitPath.isEmpty());
pendingCall = DBus::call<QDBusObjectPath, QString>(
this,
systemdPath,
managerInterface,
QStringLiteral("GetUnit"),
serviceName,
[this](const QDBusObjectPath &path) {
pendingCall = nullptr;
setUnitPath(path.path());
}, [this](const QDBusError &error) {
pendingCall = nullptr;
qWarning("Failed to query the unit path of %s: %s", qPrintable(devicePath), qPrintable(error.message()));
});
}
void PartitionPrivate::setUnitPath(const QString &path)
{
unitPath = path;
QDBusConnection systemBus = QDBusConnection::systemBus();
if (!systemBus.connect(
systemdService,
unitPath,
propertiesInterface,
QStringLiteral("PropertiesChanged"),
this,
SLOT(propertiesChanged(QString,QVariantMap,QStringList)))) {
qWarning("Failed to connect to unit properties changed signal: %s", qPrintable(systemBus.lastError().message()));
}
updateState();
}
void PartitionPrivate::updateState()
{
if (unitPath.isEmpty()) {
return;
}
delete pendingCall;
pendingCall = DBus::call<QVariant, QString, QString>(
this,
unitPath,
propertiesInterface,
QStringLiteral("Get"),
unitInterface,
activeStateProperty,
[this](const QVariant &state) {
pendingCall = nullptr;
activeState = state.toString();
mountFailed = activeState == QStringLiteral("failed");
if (manager) {
manager->refresh(this);
}
}, [this](const QDBusError &error) {
pendingCall = nullptr;
qWarning("Failed to query the active state of %s: %s", qPrintable(devicePath), qPrintable(error.message()));
});
}
void PartitionPrivate::propertiesChanged(
const QString &, const QVariantMap &, const QStringList &invalidated)
{
if (invalidated.contains(activeStateProperty)) {
updateState();
}
}
Partition::Partition()
{
}
......
......@@ -34,19 +34,13 @@
#include "partition.h"
#include <QDBusConnection>
#include <QDBusPendingCallWatcher>
#include <QDBusPendingReply>
class PartitionManagerPrivate;
class PartitionPrivate : public QObject, public QSharedData
class PartitionPrivate : public QSharedData
{
Q_OBJECT
public:
PartitionPrivate(PartitionManagerPrivate *manager)
: manager(manager)
, pendingCall(nullptr)
, bytesAvailable(0)
, bytesTotal(0)
, bytesFree(0)
......@@ -59,21 +53,13 @@ public:
{
}
public slots:
void propertiesChanged(const QString &interface, const QVariantMap &changed, const QStringList &invalidated);
public:
void getUnit();
void setUnitPath(const QString &path);
void updateState();
bool isParent(const QExplicitlySharedDataPointer<PartitionPrivate> &child) const {
return (deviceRoot && child->deviceName.startsWith(deviceName + QLatin1Char('p')));
}
PartitionManagerPrivate *manager;
QDBusPendingCallWatcher *pendingCall;
QString unitPath;
QString deviceName;
QString devicePath;
QString mountPath;
......@@ -90,73 +76,4 @@ public:
bool deviceRoot;
};
namespace DBus {
inline QVariantList packArguments()
{
return QVariantList();
}
template <typename Argument> inline QVariantList packArguments(const Argument &argument)
{
return QVariantList() << QVariant::fromValue(argument);
}
// This should be varidic to support an arbitrary number of arguments, but I seem to be missing
// something obvious and hitting type deduction failures.
template <typename Argument0, typename Argument1> inline QVariantList packArguments(const Argument0 argument0, const Argument1 &argument1)
{
return QVariantList() << QVariant::fromValue(argument0) << QVariant::fromValue(argument1);
}
template <typename Return, typename... Arguments, typename Finished, typename Error>
QDBusPendingCallWatcher *call(
QObject *parent,
const QString &path,
const QString &interface,
const QString &method,
const Arguments&... arguments,
const Finished &onFinished,
const Error &onError)
{
QDBusMessage message = QDBusMessage::createMethodCall(
QStringLiteral("org.freedesktop.systemd1"), path, interface, method);
message.setArguments(packArguments<Arguments ...>(arguments...));
QDBusConnection systemBus = QDBusConnection::systemBus();
QDBusPendingCall call = systemBus.asyncCall(message);
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, parent);
QObject::connect(watcher, &QDBusPendingCallWatcher::finished, [onFinished, onError](QDBusPendingCallWatcher *watcher) {
watcher->deleteLater();
QDBusPendingReply<Return> reply = *watcher;
if (reply.isError()) {
onError(reply.error());
} else {
onFinished(reply.value());
}
});
return watcher;
}
template <typename... Arguments>
void invoke(
const QString &path,
const QString &interface,
const QString &method,
const Arguments&... arguments)
{
QDBusMessage message = QDBusMessage::createMethodCall(
QStringLiteral("org.freedesktop.systemd1"), path, interface, method);
message.setArguments(packArguments(arguments...));
QDBusConnection::systemBus().asyncCall(message);
}
}
#endif
......@@ -30,8 +30,8 @@
*/
#include "partitionmanager_p.h"
#include "udisks2monitor_p.h"
#include <QDBusInterface>
#include <QFile>
#include <QRegularExpression>
......@@ -40,13 +40,8 @@
#include <mntent.h>
#include <sys/statvfs.h>
static const auto systemdService = QStringLiteral("org.freedesktop.systemd1");
static const auto systemdPath = QStringLiteral("/org/freedesktop/systemd1");
static const auto managerInterface = QStringLiteral("org.freedesktop.systemd1.Manager");
static const auto userName = QString(qgetenv("USER"));
static const auto externalMountPath = QString("/run/media/%1/").arg(userName);
static const auto mountServiceName = QString("run-media-%1").arg(userName);
PartitionManagerPrivate *PartitionManagerPrivate::sharedInstance = nullptr;
......@@ -55,6 +50,7 @@ PartitionManagerPrivate::PartitionManagerPrivate()
Q_ASSERT(!sharedInstance);
sharedInstance = this;
m_udisksMonitor.reset(new UDisks2::Monitor(this));
QExplicitlySharedDataPointer<PartitionPrivate> root(new PartitionPrivate(this));
root->storageType = Partition::System;
......@@ -98,35 +94,6 @@ PartitionManagerPrivate::PartitionManagerPrivate()
root->storageType = Partition::Mass;
}
QDBusConnection systemBus = QDBusConnection::systemBus();
QDBusInterface systemd(systemdService,
systemdPath,
managerInterface,
systemBus);
// Subscribe to systemd signals.
systemd.call(QDBus::NoBlock, QStringLiteral("Subscribe"));
if (!systemBus.connect(
systemdService,
systemdPath,
managerInterface,
QStringLiteral("UnitNew"),
this,
SLOT(newUnit(QString,QDBusObjectPath)))) {
qWarning("Failed to connect to new unit signal: %s", qPrintable(systemBus.lastError().message()));
}
if (!systemBus.connect(
systemdService,
systemdPath,
managerInterface,
QStringLiteral("UnitRemoved"),
this,
SLOT(removedUnit(QString,QDBusObjectPath)))) {
qWarning("Failed to connect to removed unit signal: %s", qPrintable(systemBus.lastError().message()));
}
if (root->status == Partition::Mounted) {
m_root = Partition(QExplicitlySharedDataPointer<PartitionPrivate>(root));
}
......@@ -189,7 +156,7 @@ void PartitionManagerPrivate::refresh()
partitionFile.readLine();
static const QRegularExpression whitespace(QStringLiteral("\\s+"));
static const QRegularExpression externalMedia(QStringLiteral("^mmcblk(?!0)\\d+(?:p\\d+$)?|^sd[a-z](\\d+)$"));
static const QRegularExpression externalMedia(QString("^%1$").arg(externalDevice));
static const QRegularExpression deviceRoot(QStringLiteral("^mmcblk\\d+$"));
while (!partitionFile.atEnd()) {
......@@ -247,9 +214,6 @@ void PartitionManagerPrivate::refresh()
}
for (const auto partition : addedPartitions) {
if (partition->storageType == Partition::External) {
partition->getUnit();
}
emit partitionAdded(Partition(partition));
}
......@@ -334,8 +298,6 @@ void PartitionManagerPrivate::refresh(const Partitions &partitions, Partitions &
for (auto partition : partitions) {
if (partition->status == Partition::Mounted) {
struct statvfs64 stat;
if (::statvfs64(partition->mountPath.toUtf8().constData(), &stat) == 0) {
partition->bytesTotal = stat.f_blocks * stat.f_frsize;
qint64 bytesFree = stat.f_bfree * stat.f_frsize;
......@@ -379,53 +341,6 @@ void PartitionManagerPrivate::refresh(const Partitions &partitions, Partitions &
}
}
static const QString mountPathFromSystemdService(const QString &serviceName)
{
// Format is like run-media-<user>-0403\\x2d02011.mount
// run-media-<user>-KINGSTON.mount
QString mountPath = serviceName;
mountPath.replace("-", "/");
mountPath.replace("\\x2d", "-");
mountPath.insert(0, "/");
// .mount (6) from the back
return mountPath.mid(0, mountPath.length() - 6);
}
void PartitionManagerPrivate::newUnit(const QString &serviceName, const QDBusObjectPath &objectPath)
{
Q_UNUSED(objectPath)
if (!serviceName.startsWith(mountServiceName)) {
return;
}
// Always refresh when an sdcard got mounted.
refresh();
}
void PartitionManagerPrivate::removedUnit(const QString &serviceName, const QDBusObjectPath &objectPath)
{
Q_UNUSED(objectPath)
if (!serviceName.startsWith(mountServiceName)) {
return;
}
const QString mountPath = mountPathFromSystemdService(serviceName);
for (Partitions::iterator it = m_partitions.begin(); it != m_partitions.end(); ++it) {
const auto partition = *it;
if (partition->mountPath == mountPath) {
refresh();
return;
}
}
}
PartitionManager::PartitionManager(QObject *parent)
: QObject(parent)
, d(PartitionManagerPrivate::instance())
......
......@@ -32,10 +32,18 @@
#ifndef PARTITIONMANAGER_P_H
#define PARTITIONMANAGER_P_H
#include <partitionmanager.h>
#include <partition_p.h>
#include "partitionmanager.h"
#include "partition_p.h"
#include <QMap>
#include <QVector>
#include <QScopedPointer>
namespace UDisks2 {
class Monitor;
}
static const auto externalDevice = QStringLiteral("mmcblk(?!0)\\d+(?:p\\d+$)?|(sd[a-z]\\d+)");
class PartitionManagerPrivate : public QObject, public QSharedData
{
......@@ -60,16 +68,16 @@ signals:
void partitionAdded(const Partition &partition);
void partitionRemoved(const Partition &partition);
private slots:
void newUnit(const QString &serviceName, const QDBusObjectPath &objectPath);
void removedUnit(const QString &serviceName, const QDBusObjectPath &objectPath);
private:
static PartitionManagerPrivate *sharedInstance;
Partitions m_partitions;
Partition m_root;
QScopedPointer<UDisks2::Monitor> m_udisksMonitor;
// Allow direct access to the Partitions.
friend class UDisks2::Monitor;
};
......
......@@ -7,7 +7,7 @@ QT -= gui
CONFIG += c++11 hide_symbols link_pkgconfig
PKGCONFIG += profile mlite5 mce timed-qt5 libshadowutils blkid libcrypto nemomodels-qt5 libsailfishkeyprovider connman-qt5
PKGCONFIG += ssu-sysinfo
PKGCONFIG += ssu-sysinfo nemodbus
system(qdbusxml2cpp -p mceiface.h:mceiface.cpp mce.xml)
system(qdbusxml2cpp -c ConnmanVpnProxy -p connmanvpnproxy ../dbus/net.connman.vpn.xml -i qdbusxml2cpp_dbus_types.h)
......@@ -34,7 +34,9 @@ SOURCES += \
partitionmodel.cpp \
deviceinfo.cpp \
locationsettings.cpp \
timezoneinfo.cpp
timezoneinfo.cpp \
udisks2job.cpp \
udisks2monitor.cpp
PUBLIC_HEADERS = \
languagemodel.h \
......@@ -66,7 +68,10 @@ HEADERS += \
diskusage_p.h \
locationsettings_p.h \
partition_p.h \
partitionmanager_p.h
partitionmanager_p.h \
udisks2defines.h \
udisks2job_p.h \
udisks2monitor_p.h
DEFINES += \
SYSTEMSETTINGS_BUILD_LIBRARY
......
/*
* Copyright (C) 2018 Jolla Ltd. <raine.makelainen@jolla.com>
*
* You may use this file under the terms of the BSD license as follows:
*
* "Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Nemo Mobile nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
*/
#ifndef UDISKS2_DEFINES
#define UDISKS2_DEFINES
#define DBUS_OBJECT_MANAGER_INTERFACE QLatin1String("org.freedesktop.DBus.ObjectManager")
#define UDISKS2_SERVICE QLatin1String("org.freedesktop.UDisks2")
#define UDISKS2_PATH QLatin1String("/org/freedesktop/UDisks2")
#define UDISKS2_BLOCK_INTERFACE QLatin1String("org.freedesktop.UDisks2.Block")
#define UDISKS2_PARTITION_INTERFACE QLatin1String("org.freedesktop.UDisks2.Partition")
#define UDISKS2_JOB_INTERFACE QLatin1String("org.freedesktop.UDisks2.Job")
#define UDISKS2_JOB_KEY_OPERATION QLatin1String("Operation")
#define UDISKS2_JOB_KEY_OBJECTS QLatin1String("Objects")
#define UDISKS2_JOB_OP_FS_UNMOUNT QLatin1String("filesystem-unmount")
#define UDISKS2_JOB_OP_FS_MOUNT QLatin1String("filesystem-mount")
#define UDISKS2_JOB_OP_CLEANUP QLatin1String("cleanup")
// Errors
#define UDISKS2_ERROR_DEVICE_BUSY QLatin1String("org.freedesktop.UDisks2.Error.DeviceBusy")
#define UDISKS2_ERROR_TARGET_BUSY QLatin1String("target is busy")
#endif
/*
* Copyright (C) 2018 Jolla Ltd. <raine.makelainen@jolla.com>
*
* You may use this file under the terms of the BSD license as follows:
*
* "Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Nemo Mobile nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
*/
#include "udisks2job_p.h"
#include "udisks2monitor_p.h"
#include "udisks2defines.h"
#include <QDBusConnection>
#include <QDebug>
#include <nemo-dbus/dbus.h>
UDisks2::Job::Job(const QString &path, const QVariantMap &data, QObject *parent)
: QObject(parent)
, m_path(path)
, m_data(data)
, m_status(Added)
, m_completed(false)
, m_success(false)
, m_connection(QDBusConnection::systemBus())
{
if (!m_connection.connect(
UDISKS2_SERVICE,
m_path,
UDISKS2_JOB_INTERFACE,
QStringLiteral("Completed"),
this,
SLOT(updateCompleted(bool, QString)))) {
qWarning("Failed to connect to Job's at path %p completed signal: %s: ", qPrintable(m_path), qPrintable(m_connection.lastError().message()));
}
// TODO: Move mount / unmount via Udisks2 to PartitionManager
connect(Monitor::instance(), &Monitor::errorMessage, this, [this](const QString &objectPath, const QString &errorName) {
QStringList objects = value(UDISKS2_JOB_KEY_OBJECTS).toStringList();
if (objects.contains(objectPath) && errorName == UDISKS2_ERROR_DEVICE_BUSY) {
m_message = errorName;
if (!isCompleted() && deviceBusy()) {
updateCompleted(false, m_message);
}
}
});
}
UDisks2::Job::~Job()
{
}
bool UDisks2::Job::isCompleted() const
{
return m_completed;
}
bool UDisks2::Job::success() const
{
return m_success;
}
QString UDisks2::Job::message() const
{
return m_message;
}
bool UDisks2::Job::deviceBusy() const
{
return m_message == UDISKS2_ERROR_TARGET_BUSY || m_message == UDISKS2_ERROR_DEVICE_BUSY;
}
QString UDisks2::Job::path() const
{
return m_path;
}
QVariant UDisks2::Job::value(const QString &key) const
{
return NemoDBus::demarshallDBusArgument(m_data.value(key));
}
UDisks2::Job::Status UDisks2::Job::status() const
{
return m_status;
}
UDisks2::Job::Operation UDisks2::Job::operation() const
{
QString operation = value(UDISKS2_JOB_KEY_OPERATION).toString();
if (operation == UDISKS2_JOB_OP_FS_MOUNT) {
return Mount;
} else if (operation == UDISKS2_JOB_OP_FS_UNMOUNT) {
return Unmount;
} else {
return Unknown;
}
}
void UDisks2::Job::updateCompleted(bool success, const QString &message)
{
m_completed = true;
m_success = success;
m_message = message;
m_status = UDisks2::Job::Completed;
emit completed(success);
QDBusConnection systemBus = QDBusConnection::systemBus();
systemBus.disconnect(
UDISKS2_SERVICE,
m_path,
UDISKS2_JOB_INTERFACE,
QStringLiteral("Completed"),
this,
SLOT(updateJobStatus(bool, QString)));
}
/*
* Copyright (C) 2018 Jolla Ltd. <raine.makelainen@jolla.com>
*
* You may use this file under the terms of the BSD license as follows:
*
* "Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Nemo Mobile nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
*/
#ifndef UDISKS2_JOB_H
#define UDISKS2_JOB_H
#include <QObject>
#include <QDBusConnection>
#include <QString>
#include <QVariantMap>
namespace UDisks2 {
class Job : public QObject
{
Q_OBJECT
public:
Job(const QString &path, const QVariantMap &data, QObject *parent = nullptr);
~Job();
enum Status {
Added,
Completed
};
Q_ENUM(Status)
enum Operation {
Mount,
Unmount,
Unknown
};
Q_ENUM(Operation)
bool isCompleted() const;
bool success() const;
QString message() const;
bool deviceBusy() const;
QString path() const;
QVariant value(const QString &key) const;
Status status() const;
Operation operation() const;
signals:
void completed(bool success);
private slots:
void updateCompleted(bool success, const QString &message);
private:
QString m_path;
QVariantMap m_data;
Status m_status;
QString m_message;
bool m_completed;
bool m_success;
QDBusConnection m_connection;
};
}
#endif
/*
* Copyright (C) 2018 Jolla Ltd. <raine.makelainen@jolla.com>
*
* You may use this file under the terms of the BSD license as follows:
*
* "Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in