[app] Made root directory configurable for removable storage

The dconf entry is /apps/harbour-books/removableRoot
This commit is contained in:
Slava Monich 2016-10-22 20:43:00 +03:00
parent 1d4fdeaea9
commit af9271dff5
12 changed files with 273 additions and 166 deletions

View file

@ -39,9 +39,9 @@ ApplicationWindow {
allowedOrientations: {
switch (Settings.orientation) {
default:
case BooksSettings.OrientationAny: return Orientation.All
case BooksSettings.OrientationPortrait: return Orientation.Portrait
case BooksSettings.OrientationLandscape: return Orientation.Landscape
case Settings.OrientationAny: return Orientation.All
case Settings.OrientationPortrait: return Orientation.Portrait
case Settings.OrientationLandscape: return Orientation.Landscape
}
}

View file

@ -51,7 +51,6 @@
#define BOOKS_QML_FILE BOOKS_QML_DIR "/BooksMain.qml"
#define BOOKS_INTERNAL_ROOT "Documents/Books"
#define BOOKS_REMOVABLE_ROOT "Books"
#define BOOKS_QML_PLUGIN "harbour.books"
#define BOOKS_QML_PLUGIN_V1 1

View file

@ -47,12 +47,14 @@
#define KEY_PAGE_DETAILS "pageDetails"
#define KEY_CURRENT_BOOK "currentBook"
#define KEY_CURRENT_FOLDER "currentFolder"
#define KEY_REMOVABLE_ROOT "removableRoot"
#define KEY_INVERT_COLORS "invertColors"
#define KEY_ORIENTATION "orientation"
#define DEFAULT_FONT_SIZE 0
#define DEFAULT_PAGE_DETAILS 0
#define DEFAULT_CURRENT_BOOK QString()
#define DEFAULT_CURRENT_FOLDER QString()
#define DEFAULT_REMOVABLE_ROOT "Books"
#define DEFAULT_INVERT_COLORS false
#define DEFAULT_ORIENTATION (BooksSettings::OrientationAny)
@ -227,6 +229,7 @@ public:
MGConfItem* iCurrentFolderConf;
MGConfItem* iCurrentBookPathConf;
MGConfItem* iOrientationConf;
MGConfItem* iRemovableRootConf;
mutable shared_ptr<ZLTextStyle> iTextStyle[FontSizeSteps+1];
BooksBook* iCurrentBook;
QString iCurrentStorageDevice;
@ -244,11 +247,10 @@ BooksSettings::Private::Private(BooksSettings* aParent) :
iCurrentFolderConf(new MGConfItem(DCONF_PATH KEY_CURRENT_FOLDER, this)),
iCurrentBookPathConf(new MGConfItem(DCONF_PATH KEY_CURRENT_BOOK, this)),
iOrientationConf(new MGConfItem(DCONF_PATH KEY_ORIENTATION, this)),
iRemovableRootConf(new MGConfItem(DCONF_PATH KEY_REMOVABLE_ROOT, this)),
iCurrentBook(NULL)
{
iFontSize = currentFontSize();
updateCurrentBook();
updateCurrentStorage();
connect(iFontSizeConf, SIGNAL(valueChanged()), SLOT(onFontSizeValueChanged()));
connect(iCurrentFolderConf, SIGNAL(valueChanged()), SLOT(onCurrentFolderChanged()));
connect(iCurrentBookPathConf, SIGNAL(valueChanged()), SLOT(onCurrentBookPathChanged()));
@ -256,6 +258,7 @@ BooksSettings::Private::Private(BooksSettings* aParent) :
connect(iInvertColorsConf, SIGNAL(valueChanged()), iParent, SIGNAL(invertColorsChanged()));
connect(iInvertColorsConf, SIGNAL(valueChanged()), iParent, SIGNAL(pageBackgroundColorChanged()));
connect(iOrientationConf, SIGNAL(valueChanged()), iParent, SIGNAL(orientationChanged()));
connect(iRemovableRootConf, SIGNAL(valueChanged()), iParent, SIGNAL(removableRootChanged()));
}
int
@ -406,7 +409,7 @@ BooksSettings::Private::onCurrentBookPathChanged()
// BooksSettings
// ==========================================================================
BooksSettings::BooksSettings(QObject* aParent) : QObject(aParent),
BooksSettings::BooksSettings() :
iPrivate(new Private(this))
{
}
@ -420,6 +423,15 @@ BooksSettings::sharedInstance()
// recipient of the signal drops the last shared reference.
instance = QSharedPointer<BooksSettings>(new BooksSettings, &QObject::deleteLater);
Private::sSharedInstance = instance;
// Finish initialization. These invoke BooksStorageManager::instance()
// which in turn calls BooksSettings::sharedInstance() to call
// removableRoot(). Now that Private::sSharedInstance is set, it
// won't cause infinite recursion although the returned BooksSettings
// object will be slightly under-initialized, so to speak. But that's
// ok as long as BooksStorageManager::instance() doesn't need anything
// from BooksSettings other than removableRoot()
instance->iPrivate->updateCurrentBook();
instance->iPrivate->updateCurrentStorage();
}
return instance;
}
@ -501,6 +513,12 @@ BooksSettings::setInvertColors(
iPrivate->iInvertColorsConf->set(aValue);
}
QString
BooksSettings::removableRoot() const
{
return iPrivate->iRemovableRootConf->value(DEFAULT_REMOVABLE_ROOT).toString();
}
QString
BooksSettings::relativePath() const
{

View file

@ -36,8 +36,8 @@
#include "BooksTypes.h"
#include "ZLTextStyle.h"
#include <QObject>
#include <QColor>
#include <QtQml>
#include <QSharedPointer>
class BooksSettings : public QObject
@ -52,12 +52,16 @@ class BooksSettings : public QObject
Q_PROPERTY(QString currentFolder READ currentFolder WRITE setCurrentFolder NOTIFY currentFolderChanged)
Q_PROPERTY(QString currentStorage READ currentStorage NOTIFY currentStorageChanged)
Q_PROPERTY(QString relativePath READ relativePath NOTIFY relativePathChanged)
Q_PROPERTY(QString removableRoot READ removableRoot NOTIFY removableRootChanged)
Q_PROPERTY(QColor primaryPageToolColor READ primaryPageToolColor CONSTANT)
Q_PROPERTY(QColor highlightPageToolColor READ highlightPageToolColor NOTIFY invertColorsChanged)
Q_PROPERTY(QColor pageBackgroundColor READ pageBackgroundColor NOTIFY pageBackgroundColorChanged)
Q_PROPERTY(int orientation READ orientation NOTIFY orientationChanged)
class TextStyle;
// Use sharedInstance() to instantiate this class
BooksSettings();
public:
enum FontSize {
MinFontSize = -5,
@ -72,8 +76,6 @@ public:
OrientationLandscape
};
explicit BooksSettings(QObject* aParent = NULL);
static QSharedPointer<BooksSettings> sharedInstance();
Q_INVOKABLE bool increaseFontSize();
@ -94,6 +96,7 @@ public:
void setCurrentBook(QObject* aBook);
QString relativePath() const;
QString removableRoot() const;
QString currentFolder() const;
void setCurrentFolder(QString aValue);
@ -113,6 +116,7 @@ Q_SIGNALS:
void currentFolderChanged();
void currentStorageChanged();
void relativePathChanged();
void removableRootChanged();
void pageBackgroundColorChanged();
void orientationChanged();
@ -121,6 +125,4 @@ private:
Private* iPrivate;
};
QML_DECLARE_TYPE(BooksSettings)
#endif // BOOKS_SETTINGS_H

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2015 Jolla Ltd.
* Copyright (C) 2015-2016 Jolla Ltd.
* Contact: Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of the BSD license as follows:
@ -14,7 +14,7 @@
* 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
* * Neither the name of Jolla Ltd nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
@ -516,7 +516,9 @@ void BooksShelf::init()
#if QT_VERSION < 0x050000
setRoleNames(roleNames());
#endif
QQmlEngine::setObjectOwnership(&iStorage, QQmlEngine::CppOwnership);
connect(BooksStorageManager::instance(),
SIGNAL(storageReplaced(BooksStorage,BooksStorage)),
SLOT(onStorageReplaced(BooksStorage,BooksStorage)));
}
void BooksShelf::setRelativePath(QString aPath)
@ -537,6 +539,14 @@ void BooksShelf::setDevice(QString aDevice)
}
}
void BooksShelf::onStorageReplaced(BooksStorage aOld, BooksStorage aNew)
{
if (iStorage == aOld) {
iStorage = aNew;
updatePath();
}
}
void BooksShelf::setName(QString aName)
{
if (iStorage.isValid() &&

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2015 Jolla Ltd.
* Copyright (C) 2015-2016 Jolla Ltd.
* Contact: Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of the BSD license as follows:
@ -14,7 +14,7 @@
* 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
* * Neither the name of Jolla Ltd nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
@ -147,6 +147,7 @@ private Q_SLOTS:
void onCopyTaskProgressChanged();
void onCopyTaskDone();
void onDeleteTaskDone();
void onStorageReplaced(BooksStorage aOldStorage, BooksStorage aNewStorage);
void saveState();
private:

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2015 Jolla Ltd.
* Copyright (C) 2015-2016 Jolla Ltd.
* Contact: Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of the BSD license as follows:
@ -14,7 +14,7 @@
* 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
* * Neither the name of Jolla Ltd nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
@ -32,6 +32,7 @@
*/
#include "BooksStorage.h"
#include "BooksSettings.h"
#include "BooksDefs.h"
#include "HarbourDebug.h"
@ -62,7 +63,8 @@ class BooksStorage::Private: public QObject
Q_OBJECT
public:
Private(QString aDevice, QDir aBooksDir, bool aInternal);
Private(QString aDevice, QString aMountPoint, QString aBooksDir,
bool aInternal);
bool isRemoved() const;
bool equal(const Private& aData) const;
@ -76,14 +78,23 @@ Q_SIGNALS:
public:
QAtomicInt iRef;
QString iDevice;
QString iMountPoint;
QDir iBooksDir;
QDir iConfigDir;
bool iInternal;
bool iPresent;
};
BooksStorage::Private::Private(QString aDevice, QDir aBooksDir, bool aInternal) :
iRef(1), iDevice(aDevice), iBooksDir(aBooksDir), iInternal(aInternal),
BooksStorage::Private::Private(
QString aDevice,
QString aMountPoint,
QString aBooksDir,
bool aInternal) :
iRef(1),
iDevice(aDevice),
iMountPoint(aMountPoint),
iBooksDir(aBooksDir),
iInternal(aInternal),
iPresent(true)
{
QString cfgDir;
@ -97,7 +108,7 @@ BooksStorage::Private::Private(QString aDevice, QDir aBooksDir, bool aInternal)
cfgDir += subDir;
} else {
cfgDir += REMOVABLE_STATE_DIR "/";
QString label = QDir(Private::mountPoint(aBooksDir.path())).dirName();
QString label = QDir(Private::mountPoint(aBooksDir)).dirName();
if (label.isEmpty()) label = "sdcard";
cfgDir += label;
}
@ -106,10 +117,12 @@ BooksStorage::Private::Private(QString aDevice, QDir aBooksDir, bool aInternal)
bool BooksStorage::Private::equal(const BooksStorage::Private& aData) const
{
return iInternal == iInternal &&
iPresent == iPresent &&
return iInternal == aData.iInternal &&
iPresent == aData.iPresent &&
iMountPoint == aData.iMountPoint &&
iDevice == aData.iDevice &&
iBooksDir == aData.iBooksDir;
iBooksDir == aData.iBooksDir &&
iConfigDir == aData.iConfigDir;
}
bool BooksStorage::Private::isMountPoint(QString aPath)
@ -153,9 +166,9 @@ BooksStorage::BooksStorage(const BooksStorage& aStorage) :
if (iPrivate) iPrivate->iRef.ref();
}
BooksStorage::BooksStorage(QString aDevice, QDir aBooksDir, bool aInternal) :
QObject(NULL),
iPrivate(new Private(aDevice, aBooksDir, aInternal)),
BooksStorage::BooksStorage(QString aDevice, QString aMount, QString aBooksDir,
bool aInternal) : QObject(NULL),
iPrivate(new Private(aDevice, aMount, aBooksDir, aInternal)),
iPassThrough(false)
{
HDEBUG("config dir" << qPrintable(configDir().path()));
@ -253,17 +266,26 @@ void BooksStorage::set(const BooksStorage& aStorage)
#define STORAGE_SCAN_INTERVAL 100
#define STORAGE_SCAN_TIMEOUT 5000
class BooksStorageManager::Private {
class BooksStorageManager::Private : public QObject {
Q_OBJECT
public:
static BooksStorageManager* gInstance;
Private();
Private(BooksStorageManager* aParent);
~Private();
int findDevice(QString aDevice) const;
int findPath(QString aPath, QString* aRelPath) const;
bool scanMounts();
public Q_SLOTS:
void onDeviceEvent(int);
void onRemovableRootChanged();
void onScanMounts();
public:
BooksStorageManager* iParent;
QSharedPointer<BooksSettings> iSettings;
QList<BooksStorage> iStorageList;
struct udev* iUdev;
struct udev_monitor* iMonitor;
@ -275,7 +297,10 @@ public:
BooksStorageManager* BooksStorageManager::Private::gInstance = NULL;
BooksStorageManager::Private::Private() :
BooksStorageManager::Private::Private(BooksStorageManager* aParent) :
QObject(aParent),
iParent(aParent),
iSettings(BooksSettings::sharedInstance()),
iUdev(udev_new()),
iMonitor(NULL),
iDescriptor(-1),
@ -303,21 +328,22 @@ BooksStorageManager::Private::Private() :
QString mount(entries.at(1));
if (mount == homeMount) {
homeDevice = entries.at(0);
HDEBUG("home device" << homeDevice);
HDEBUG("internal" << homeDevice);
} else if (mount.startsWith(mediaPrefix)) {
QString dev = entries.at(0);
QString path = mount;
QString path(mount);
if (!path.endsWith('/')) path += '/';
path += QLatin1String(BOOKS_REMOVABLE_ROOT);
HDEBUG("removable device" << dev << path);
iStorageList.append(BooksStorage(dev, path, false));
path += iSettings->removableRoot();
BooksStorage bs(dev, mount, path, false);
HDEBUG("removable" << dev << bs.booksDir().path());
iStorageList.append(bs);
}
}
}
mounts.close();
}
iStorageList.insert(0, BooksStorage(homeDevice, homeBooks, true));
iStorageList.insert(0, BooksStorage(homeDevice, homeMount, homeBooks, true));
if (iUdev) {
iMonitor = udev_monitor_new_from_netlink(iUdev, "udev");
@ -329,9 +355,28 @@ BooksStorageManager::Private::Private() :
if (iDescriptor >= 0) {
iNotifier = new QSocketNotifier(iDescriptor,
QSocketNotifier::Read);
connect(iNotifier, SIGNAL(activated(int)),
SLOT(onDeviceEvent(int)));
}
}
}
connect(iSettings.data(), SIGNAL(removableRootChanged()),
SLOT(onRemovableRootChanged()));
}
BooksStorageManager::Private::~Private()
{
if (iUdev) {
if (iMonitor) {
if (iDescriptor >= 0) {
delete iNotifier;
close(iDescriptor);
}
udev_monitor_unref(iMonitor);
}
udev_unref(iUdev);
}
}
int BooksStorageManager::Private::findDevice(QString aDevice) const
@ -369,17 +414,127 @@ int BooksStorageManager::Private::findPath(QString aPath, QString* aRelPath) con
return -1;
}
BooksStorageManager::Private::~Private()
bool BooksStorageManager::Private::scanMounts()
{
if (iUdev) {
if (iMonitor) {
if (iDescriptor >= 0) {
delete iNotifier;
close(iDescriptor);
bool newStorageFound = false;
QList<BooksStorage> newMounts;
QFile mounts(STORAGE_MOUNTS_FILE);
if (mounts.open(QIODevice::ReadOnly | QIODevice::Text)) {
// For some reason QTextStream can't read /proc/mounts line by line
QByteArray contents = mounts.readAll();
QTextStream in(&contents);
QString mediaPrefix(STORAGE_MOUNT_PREFIX);
while (!in.atEnd()) {
QString line = in.readLine();
QStringList entries = line.split(' ', QString::SkipEmptyParts);
if (entries.count() > 2) {
QString mount(entries.at(1));
if (mount.startsWith(mediaPrefix)) {
QString dev = entries.at(0);
int index = findDevice(dev);
if (index < 0) {
QString path = mount;
if (!path.endsWith('/')) path += '/';
path += iSettings->removableRoot();
HDEBUG("new removable device" << dev << path);
BooksStorage storage(dev, mount, path, false);
iStorageList.append(storage);
Q_EMIT iParent->storageAdded(storage);
newStorageFound = true;
}
udev_monitor_unref(iMonitor);
}
udev_unref(iUdev);
}
}
mounts.close();
}
return newStorageFound;
}
void BooksStorageManager::Private::onScanMounts()
{
if (scanMounts()) {
iScanMountsTimer->stop();
} else {
QDateTime now = QDateTime::currentDateTime();
if (now > iScanDeadline) {
HDEBUG("timeout waiting for new mount to appear");
iScanMountsTimer->stop();
} else {
HDEBUG("no new mounts found");
}
}
}
void BooksStorageManager::Private::onDeviceEvent(int)
{
struct udev_device* dev = udev_monitor_receive_device(iMonitor);
if (dev) {
const char* devnode = udev_device_get_devnode(dev);
const char* action = udev_device_get_action(dev);
HDEBUG("got device");
HDEBUG(" node:" << devnode);
HDEBUG(" subsystem:" << udev_device_get_subsystem(dev));
HDEBUG(" devtype:" << udev_device_get_devtype(dev));
HDEBUG(" action:" << action);
if (devnode && action) {
if (!(strcmp(action, STORAGE_ACTION_ADD))) {
// Mount list isn't updated yet when we receive this
// notification. It takes hundreds of milliseconds until
// it gets mounted and becomes accessible.
if (!scanMounts()) {
HDEBUG("no new mounts found");
if (!iScanMountsTimer) {
QTimer* timer = new QTimer(this);
timer->setSingleShot(false);
timer->setInterval(STORAGE_SCAN_INTERVAL);
connect(timer, SIGNAL(timeout()), SLOT(onScanMounts()));
iScanMountsTimer = timer;
}
iScanMountsTimer->start();
iScanDeadline = QDateTime::currentDateTime().
addMSecs(STORAGE_SCAN_TIMEOUT);
}
} else if (!(strcmp(action, STORAGE_ACTION_REMOVE))) {
int pos = findDevice(devnode);
if (pos >= 0) {
HDEBUG("removable device is gone");
BooksStorage storage = iStorageList.takeAt(pos);
storage.iPrivate->iPresent = false;
Q_EMIT storage.iPrivate->removed();
Q_EMIT iParent->storageRemoved(storage);
}
}
}
udev_device_unref(dev);
} else {
HWARN("no device!");
}
}
void BooksStorageManager::Private::onRemovableRootChanged()
{
int i;
HDEBUG(iSettings->removableRoot());
QList<BooksStorage> replaced; // old-new pairs
for (i=iStorageList.count()-1; i>=0; i--) {
BooksStorage storage = iStorageList.at(i);
if (!storage.isInternal()) {
QString path(storage.iPrivate->iMountPoint);
if (!path.endsWith('/')) path += '/';
path += iSettings->removableRoot();
BooksStorage updated(storage.iPrivate->iDevice,
storage.iPrivate->iMountPoint, path, false);
if (!storage.equal(updated)) {
replaced.append(storage);
replaced.append(updated);
iStorageList.replace(i, updated);
} else {
HWARN(storage.root() << "didn't change");
}
}
}
for (i=0; (i+1)<replaced.count(); i+=2) {
Q_EMIT iParent->storageReplaced(replaced.at(i), replaced.at(i+1));
}
}
@ -402,12 +557,8 @@ void BooksStorageManager::deleteInstance()
}
BooksStorageManager::BooksStorageManager() :
iPrivate(new Private)
iPrivate(new Private(this))
{
if (iPrivate->iNotifier) {
connect(iPrivate->iNotifier, SIGNAL(activated(int)),
SLOT(onDeviceEvent(int)));
}
}
BooksStorageManager::~BooksStorageManager()
@ -415,7 +566,6 @@ BooksStorageManager::~BooksStorageManager()
if (Private::gInstance == this) {
Private::gInstance = NULL;
}
delete iPrivate;
}
int BooksStorageManager::count() const
@ -440,100 +590,4 @@ BooksStorage BooksStorageManager::storageForPath(QString aPath, QString* aRelPat
return (index >= 0) ? iPrivate->iStorageList.at(index) : BooksStorage();
}
void BooksStorageManager::onDeviceEvent(int)
{
struct udev_device* dev = udev_monitor_receive_device(iPrivate->iMonitor);
if (dev) {
const char* devnode = udev_device_get_devnode(dev);
const char* action = udev_device_get_action(dev);
HDEBUG("got device");
HDEBUG(" node:" << devnode);
HDEBUG(" subsystem:" << udev_device_get_subsystem(dev));
HDEBUG(" devtype:" << udev_device_get_devtype(dev));
HDEBUG(" action:" << action);
if (devnode && action) {
if (!(strcmp(action, STORAGE_ACTION_ADD))) {
// Mount list isn't updated yet when we receive this
// notification. It takes hundreds of milliseconds until
// it gets mounted and becomes accessible.
if (!scanMounts()) {
HDEBUG("no new mounts found");
if (!iPrivate->iScanMountsTimer) {
QTimer* timer = new QTimer(this);
timer->setSingleShot(false);
timer->setInterval(STORAGE_SCAN_INTERVAL);
connect(timer, SIGNAL(timeout()), SLOT(onScanMounts()));
iPrivate->iScanMountsTimer = timer;
}
iPrivate->iScanMountsTimer->start();
iPrivate->iScanDeadline = QDateTime::currentDateTime().
addMSecs(STORAGE_SCAN_TIMEOUT);
}
} else if (!(strcmp(action, STORAGE_ACTION_REMOVE))) {
int pos = iPrivate->findDevice(devnode);
if (pos >= 0) {
HDEBUG("removable device is gone");
BooksStorage storage = iPrivate->iStorageList.takeAt(pos);
storage.iPrivate->iPresent = false;
Q_EMIT storage.iPrivate->removed();
Q_EMIT storageRemoved(storage);
}
}
}
udev_device_unref(dev);
} else {
HWARN("no device!");
}
}
bool BooksStorageManager::scanMounts()
{
bool newStorageFound = false;
QFile mounts(STORAGE_MOUNTS_FILE);
if (mounts.open(QIODevice::ReadOnly | QIODevice::Text)) {
// For some reason QTextStream can't read /proc/mounts line by line
QByteArray contents = mounts.readAll();
QTextStream in(&contents);
QString mediaPrefix(STORAGE_MOUNT_PREFIX);
while (!in.atEnd()) {
QString line = in.readLine();
QStringList entries = line.split(' ', QString::SkipEmptyParts);
if (entries.count() > 2) {
QString mount(entries.at(1));
if (mount.startsWith(mediaPrefix)) {
QString dev = entries.at(0);
int index = iPrivate->findDevice(dev);
if (index < 0) {
QString path = mount;
if (!path.endsWith('/')) path += '/';
path += QLatin1String(BOOKS_REMOVABLE_ROOT);
HDEBUG("new removable device" << dev << path);
BooksStorage storage(dev, path, false);
iPrivate->iStorageList.append(storage);
Q_EMIT storageAdded(storage);
newStorageFound = true;
}
}
}
}
mounts.close();
}
return newStorageFound;
}
void BooksStorageManager::onScanMounts()
{
if (scanMounts()) {
iPrivate->iScanMountsTimer->stop();
} else {
QDateTime now = QDateTime::currentDateTime();
if (now > iPrivate->iScanDeadline) {
HDEBUG("timeout waiting for new mount to appear");
iPrivate->iScanMountsTimer->stop();
} else {
HDEBUG("no new mounts found");
}
}
}
#include "BooksStorage.moc"

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2015 Jolla Ltd.
* Copyright (C) 2015-2016 Jolla Ltd.
* Contact: Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of the BSD license as follows:
@ -14,7 +14,7 @@
* 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
* * Neither the name of Jolla Ltd nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
@ -38,6 +38,7 @@
#include <QList>
#include <QDir>
class BooksSettings;
class BooksStorageManager;
class BooksStorage: public QObject
@ -76,7 +77,7 @@ Q_SIGNALS:
private:
friend class BooksStorageManager;
BooksStorage(QString, QDir, bool);
BooksStorage(QString, QString, QString, bool);
void connectNotify(const QMetaMethod& aSignal);
private:
@ -102,14 +103,10 @@ public:
Q_SIGNALS:
void storageAdded(BooksStorage aStorage);
void storageRemoved(BooksStorage aStorage);
void storageReplaced(BooksStorage aOldStorage, BooksStorage aNewStorage);
private:
BooksStorageManager();
bool scanMounts();
private Q_SLOTS:
void onDeviceEvent(int);
void onScanMounts();
private:
class Private;

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2015 Jolla Ltd.
* Copyright (C) 2015-2016 Jolla Ltd.
* Contact: Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of the BSD license as follows:
@ -14,7 +14,7 @@
* 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
* * Neither the name of Jolla Ltd nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
@ -90,6 +90,9 @@ BooksStorageModel::BooksStorageModel(QObject* aParent) :
connect(mgr,
SIGNAL(storageRemoved(BooksStorage)),
SLOT(onStorageRemoved(BooksStorage)));
connect(mgr,
SIGNAL(storageReplaced(BooksStorage,BooksStorage)),
SLOT(onStorageReplaced(BooksStorage,BooksStorage)));
}
BooksStorageModel::~BooksStorageModel()
@ -210,6 +213,24 @@ void BooksStorageModel::onStorageRemoved(BooksStorage aStorage)
endRemoveRows();
Q_EMIT countChanged();
} else {
HWARN("device not dfound on the list");
HWARN("device not found on the list");
}
}
void BooksStorageModel::onStorageReplaced(BooksStorage aOld, BooksStorage aNew)
{
int index = find(aOld);
if (index >=0) {
QModelIndex modelIndex(createIndex(index, 0));
QVector<int> roles(4);
roles.append(BooksStorageRoot);
roles.append(BooksStorageDevice);
roles.append(BooksStorageRemovable);
roles.append(BooksStorageDeleteAllRequest);
HWARN(aOld.root() << "->" << aNew.root());
iList.at(index)->iStorage = aNew;
Q_EMIT dataChanged(modelIndex, modelIndex, roles);
} else {
HWARN("device not found on the list");
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2015 Jolla Ltd.
* Copyright (C) 2015-2016 Jolla Ltd.
* Contact: Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of the BSD license as follows:
@ -14,7 +14,7 @@
* 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
* * Neither the name of Jolla Ltd nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
@ -72,6 +72,7 @@ Q_SIGNALS:
private Q_SLOTS:
void onStorageAdded(BooksStorage aStorage);
void onStorageRemoved(BooksStorage aStorage);
void onStorageReplaced(BooksStorage aOldStorage, BooksStorage aNewStorage);
private:
bool validIndex(int aIndex) const;

View file

@ -171,7 +171,6 @@ bool ZLibrary::init(int& aArgc, char** &aArgv)
}
HDEBUG("screen" << booksPPI << "dpi");
BooksStorageManager::instance();
ZLQtTimeManager::createInstance();
ZLQtFSManager::createInstance();
BooksDialogManager::createInstance();
@ -179,6 +178,13 @@ bool ZLibrary::init(int& aArgc, char** &aArgv)
ZLEncodingCollection::Instance().registerProvider(new IConvEncodingConverterProvider());
ZLApplication::Instance();
ZLFile::initCache();
// Due to the weird inter-dependency between BooksSettings and
// BooksStorageManager, BooksSettings has to be created first.
// Doing it the other way around will result in two instances of
// BooksStorageManager being created :)
QSharedPointer<BooksSettings> settings = BooksSettings::sharedInstance();
BooksStorageManager::instance();
return true;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2015 Jolla Ltd.
* Copyright (C) 2015-2016 Jolla Ltd.
* Contact: Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of the BSD license as follows:
@ -14,7 +14,7 @@
* 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
* * Neither the name of Jolla Ltd nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
@ -37,7 +37,6 @@
#include "BooksBookModel.h"
#include "BooksCoverModel.h"
#include "BooksConfig.h"
#include "BooksSettings.h"
#include "BooksImportModel.h"
#include "BooksPathModel.h"
#include "BooksStorageModel.h"
@ -79,7 +78,6 @@ Q_DECL_EXPORT int main(int argc, char **argv)
BOOKS_QML_REGISTER(BooksPageWidget, "PageWidget");
BOOKS_QML_REGISTER(BooksListWatcher, "ListWatcher");
BOOKS_QML_REGISTER(BooksCoverWidget, "BookCover");
BOOKS_QML_REGISTER(BooksSettings, "BooksSettings");
BOOKS_QML_REGISTER(BooksHints, "BooksHints");
HarbourLib::registerTypes(BOOKS_QML_PLUGIN,
BOOKS_QML_PLUGIN_V1, BOOKS_QML_PLUGIN_V2);