Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[diskusage] Add DiskUsage QML component
  • Loading branch information
thp committed Mar 6, 2015
1 parent 2b4c5fb commit 49af751
Show file tree
Hide file tree
Showing 5 changed files with 339 additions and 2 deletions.
187 changes: 187 additions & 0 deletions src/diskusage.cpp
@@ -0,0 +1,187 @@
/*
* Copyright (C) 2015 Jolla Ltd.
* Contact: Thomas Perl <thomas.perl@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 "diskusage.h"
#include "diskusage_p.h"

#include <QThread>
#include <QDir>
#include <QProcess>
#include <QDebug>
#include <QJSEngine>

DiskUsageWorker::DiskUsageWorker(QObject *parent)
: QObject(parent)
, m_quit(false)
{
}

DiskUsageWorker::~DiskUsageWorker()
{
}

static quint64 calculateSize(const QString &directory)
{
QDir d(directory);
if (!d.exists() || !d.isReadable()) {
return 0L;
}

QProcess du;
du.start("du", QStringList() << "-sb" << directory, QIODevice::ReadOnly);
du.waitForFinished();
if (du.exitStatus() != QProcess::NormalExit) {
qWarning() << "Could not determine size of:" << directory;
return 0L;
}
QStringList size_directory = QString::fromUtf8(du.readAll()).split('\t');

if (size_directory.size() > 1) {
return size_directory[0].toULongLong();
}

return 0L;
}

void DiskUsageWorker::submit(QStringList paths, QJSValue *callback)
{
QVariantMap usage;

foreach (const QString &path, paths) {
usage[path] = calculateSize(path);

if (m_quit) {
break;
}
}

for (QVariantMap::iterator it = usage.begin(); it != usage.end(); ++it) {
const QString &path = it.key();
qlonglong bytes = it.value().toLongLong();

for (QVariantMap::const_iterator it2 = usage.cbegin(); it2 != usage.cend(); ++it2) {
const QString &subpath = it2.key();
const qlonglong subbytes = it2.value().toLongLong();

if (subpath.length() > path.length() && subpath.indexOf(path) == 0) {
bytes -= subbytes;
}
}

if (it.value() != bytes) {
it.value() = bytes;
}
}

emit finished(usage, callback);
}


class DiskUsagePrivate
{
Q_DISABLE_COPY(DiskUsagePrivate)
Q_DECLARE_PUBLIC(DiskUsage)

DiskUsage * const q_ptr;

public:
DiskUsagePrivate(DiskUsage *usage);
~DiskUsagePrivate();

private:
QThread m_thread;
DiskUsageWorker *m_worker;
};

DiskUsagePrivate::DiskUsagePrivate(DiskUsage *usage)
: q_ptr(usage)
, m_thread()
, m_worker(new DiskUsageWorker())
{
m_worker->moveToThread(&m_thread);

QObject::connect(usage, SIGNAL(submit(QStringList, QJSValue *)),
m_worker, SLOT(submit(QStringList, QJSValue *)));

QObject::connect(m_worker, SIGNAL(finished(QVariantMap, QJSValue *)),
usage, SLOT(finished(QVariantMap, QJSValue *)));

m_thread.start();
}

DiskUsagePrivate::~DiskUsagePrivate()
{
// Make sure the worker quits as soon as possible
m_worker->scheduleQuit();

// Wait for thread to shut down
m_thread.quit();
if (!m_thread.wait(10 * 1000)) {
qWarning("Worker thread did not quit in time");
}

m_worker->deleteLater();
}


DiskUsage::DiskUsage(QObject *parent)
: QObject(parent)
, d_ptr(new DiskUsagePrivate(this))
, m_working(false)
{
}

DiskUsage::~DiskUsage()
{
}

void DiskUsage::calculate(const QStringList &paths, QJSValue callback)
{
QJSValue *cb = 0;

if (!callback.isNull() && !callback.isUndefined() && callback.isCallable()) {
cb = new QJSValue(callback);
}

setWorking(true);
emit submit(paths, cb);
}

void DiskUsage::finished(QVariantMap usage, QJSValue *callback)
{
if (callback) {
callback->call(QJSValueList() << callback->engine()->toScriptValue(usage));
delete callback;
}

setWorking(false);
}
85 changes: 85 additions & 0 deletions src/diskusage.h
@@ -0,0 +1,85 @@
/*
* Copyright (C) 2015 Jolla Ltd.
* Contact: Thomas Perl <thomas.perl@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 DISKUSAGE_H
#define DISKUSAGE_H

#include <QObject>
#include <QVariant>
#include <QJSValue>
#include <QScopedPointer>

class DiskUsagePrivate;

class DiskUsage : public QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(DiskUsage)

// True while calculation takes place
Q_PROPERTY(bool working
READ working
NOTIFY workingChanged)

public:
explicit DiskUsage(QObject *parent=0);
virtual ~DiskUsage();

// Calculate the disk usage of the given paths, then call
// callback with a QVariantMap (mapping paths to usages in bytes)
Q_INVOKABLE void calculate(const QStringList &paths, QJSValue callback);

signals:
void workingChanged();

signals:
void submit(QStringList paths, QJSValue *callback);

private slots:
void finished(QVariantMap usage, QJSValue *callback);

private:
bool working() const { return m_working; }

void setWorking(bool working) {
if (m_working != working) {
m_working = working;
emit workingChanged();
}
}

private:
QScopedPointer<DiskUsagePrivate> const d_ptr;
bool m_working;
};

#endif /* DISKUSAGE_H */
60 changes: 60 additions & 0 deletions src/diskusage_p.h
@@ -0,0 +1,60 @@
/*
* Copyright (C) 2015 Jolla Ltd.
* Contact: Thomas Perl <thomas.perl@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 DISKUSAGE_P_H
#define DISKUSAGE_P_H

#include <QObject>
#include <QVariant>
#include <QJSValue>

class DiskUsageWorker : public QObject
{
Q_OBJECT

public:
explicit DiskUsageWorker(QObject *parent=0);
virtual ~DiskUsageWorker();

void scheduleQuit() { m_quit = true; }

public slots:
void submit(QStringList paths, QJSValue *callback);

signals:
void finished(QVariantMap usage, QJSValue *callback);

private:
bool m_quit;
};

#endif /* DISKUSAGE_P_H */
2 changes: 2 additions & 0 deletions src/plugin/plugin.cpp
Expand Up @@ -43,6 +43,7 @@
#include "aboutsettings.h"
#include "devicelockiface.h"
#include "developermodesettings.h"
#include "diskusage.h"

class SystemSettingsPlugin : public QQmlExtensionPlugin
{
Expand All @@ -68,6 +69,7 @@ class SystemSettingsPlugin : public QQmlExtensionPlugin
qmlRegisterType<DeviceLockInterface>(uri, 1, 0, "DeviceLockInterface");
qmlRegisterType<DeveloperModeSettings>(uri, 1, 0, "DeveloperModeSettings");
qRegisterMetaType<DeveloperModeSettings::Status>("DeveloperModeSettings::Status");
qmlRegisterType<DiskUsage>(uri, 1, 0, "DiskUsage");
}
};

Expand Down
7 changes: 5 additions & 2 deletions src/src.pro
Expand Up @@ -21,7 +21,8 @@ SOURCES += \
usbsettings.cpp \
aboutsettings.cpp \
devicelockiface.cpp \
developermodesettings.cpp
developermodesettings.cpp \
diskusage.cpp

HEADERS += \
languagemodel.h \
Expand All @@ -33,7 +34,9 @@ HEADERS += \
usbsettings.h \
aboutsettings.h \
devicelockiface.h \
developermodesettings.h
developermodesettings.h \
diskusage.h \
diskusage_p.h

develheaders.path = /usr/include/systemsettings
develheaders.files = $$HEADERS
Expand Down

0 comments on commit 49af751

Please sign in to comment.