[app] Tweaking book copy

This commit is contained in:
Slava Monich 2015-12-12 11:36:22 +03:00
parent 84b9b77523
commit c95bb79aa2
13 changed files with 230 additions and 117 deletions

View file

@ -138,14 +138,24 @@ Item {
ProgressCircle {
id: progressIndicator
width: parent.width/2
width: busyIndicator.width
height: width
anchors.centerIn: parent
anchors.centerIn: busyIndicator
opacity: (copying && !longCopyTimer.running && value > 0 && value < 1) ? 1 : 0
visible: opacity > 0
Behavior on opacity { FadeAnimation {} }
}
BusyIndicator {
id: busyIndicator
size: BusyIndicatorSize.Medium
x: cover.x + cover.centerX - width/2
y: cover.y + cover.centerY - height/2
visible: opacity > 0
running: copying && !longCopyTimer.running && (progressIndicator.value <= 0 || progressIndicator.value >= 1)
Behavior on opacity { enabled: false }
}
function withinDeleteButton(x, y) {
return x >= deleteButton.x - deleteButton.margin &&
x < deleteButton.x + deleteButton.width + deleteButton.margin &&

View file

@ -37,6 +37,7 @@
#include "BooksTextView.h"
#include "BooksTextStyle.h"
#include "BooksPaintContext.h"
#include "BooksUtil.h"
#include "HarbourJson.h"
#include "HarbourDebug.h"
@ -46,6 +47,7 @@
#include "bookmodel/BookModel.h"
#include "library/Author.h"
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QDirIterator>
@ -132,15 +134,16 @@ bool BooksBook::CoverPaintContext::gotIt() const
class BooksBook::CoverTask : public BooksTask
{
public:
CoverTask(QString aStateDir, shared_ptr<Book> aBook) :
iStateDir(aStateDir), iBook(aBook), iCoverMissing(false) {}
CoverTask(QString aStateDir, shared_ptr<Book> aBook, QString aImagePath) :
iStateDir(aStateDir), iBook(aBook), iImagePath(aImagePath),
iCoverMissing(false) {}
bool hasImage() const;
QString cachedImagePath() const;
public:
QString iStateDir;
shared_ptr<Book> iBook;
QString iImagePath;
QImage iCoverImage;
bool iCoverMissing;
};
@ -150,16 +153,6 @@ inline bool BooksBook::CoverTask::hasImage() const
return iCoverImage.width() > 0 && iCoverImage.height() > 0;
}
QString BooksBook::CoverTask::cachedImagePath() const
{
if (!iStateDir.isEmpty()) {
return iStateDir + "/" +
QString::fromStdString(iBook->file().name(false)) +
BOOK_COVER_SUFFIX + "jpg";
}
return QString();
}
// ==========================================================================
// BooksBook::LoadCoverTask
// ==========================================================================
@ -168,8 +161,8 @@ class BooksBook::LoadCoverTask : public BooksBook::CoverTask
{
public:
LoadCoverTask(QString aStateDir, shared_ptr<Book> aBook,
shared_ptr<FormatPlugin> aFormatPlugin) :
BooksBook::CoverTask(aStateDir, aBook),
shared_ptr<FormatPlugin> aFormatPlugin, QString aImagePath) :
BooksBook::CoverTask(aStateDir, aBook, aImagePath),
iFormatPlugin(aFormatPlugin) {}
virtual void performTask();
@ -234,8 +227,8 @@ void BooksBook::LoadCoverTask::performTask()
class BooksBook::GuessCoverTask : public BooksBook::CoverTask
{
public:
GuessCoverTask(QString aStateDir, shared_ptr<Book> aBook) :
BooksBook::CoverTask(aStateDir, aBook) {}
GuessCoverTask(QString aStateDir, shared_ptr<Book> aBook, QString aImagePath) :
BooksBook::CoverTask(aStateDir, aBook, aImagePath) {}
virtual void performTask();
};
@ -264,17 +257,16 @@ void BooksBook::GuessCoverTask::performTask()
iCoverImage.width() << "as cover for" << iBook->title().c_str());
// Save the extracted image
QString coverPath(cachedImagePath());
if (!coverPath.isEmpty()) {
QFileInfo file(coverPath);
if (!iImagePath.isEmpty()) {
QFileInfo file(iImagePath);
QDir dir(file.dir());
if (!dir.mkpath(dir.absolutePath())) {
HWARN("failed to create" << qPrintable(dir.absolutePath()));
}
if (iCoverImage.save(coverPath)) {
HDEBUG("saved cover to" << qPrintable(coverPath));
if (iCoverImage.save(iImagePath)) {
HDEBUG("saved cover to" << qPrintable(iImagePath));
} else {
HWARN("failed to save" << qPrintable(coverPath));
HWARN("failed to save" << qPrintable(iImagePath));
}
}
} else if (isCanceled()) {
@ -285,12 +277,11 @@ void BooksBook::GuessCoverTask::performTask()
// Create empty file. Guessing the cover image is an expensive task,
// we don't want to do it every time the application is started.
QString coverPath(cachedImagePath());
if (!coverPath.isEmpty() &&
if (!iImagePath.isEmpty() &&
// Check if the book file still exists - the failure could've
// been caused by the SD-card removal.
QFile::exists(QString::fromStdString(iBook->file().path()))) {
QFile(coverPath).open(QIODevice::WriteOnly);
QFile(iImagePath).open(QIODevice::WriteOnly);
}
}
}
@ -313,7 +304,7 @@ BooksBook::BooksBook(const BooksStorage& aStorage, QString aRelativePath,
iRef(1),
iStorage(aStorage),
iBook(aBook),
iTaskQueue(BooksTaskQueue::instance())
iTaskQueue(BooksTaskQueue::defaultQueue())
{
init();
HASSERT(!iBook.isNull());
@ -328,8 +319,10 @@ BooksBook::BooksBook(const BooksStorage& aStorage, QString aRelativePath,
iAuthors += QString::fromStdString(authors[i]->name());
}
if (iStorage.isValid()) {
iStateDir = iStorage.configDir().path() + "/" + aRelativePath;
iStateFilePath = iStateDir + "/" + iFileName + BOOKS_STATE_FILE_SUFFIX;
iStateDir = QDir::cleanPath(iStorage.configDir().path() +
QDir::separator() + aRelativePath);
iStateFilePath = QDir::cleanPath(iStateDir +
QDir::separator() + iFileName + BOOKS_STATE_FILE_SUFFIX);
// Load the state
QVariantMap state;
if (HarbourJson::load(iStateFilePath, state)) {
@ -430,11 +423,6 @@ void BooksBook::setCopyingOut(bool aValue)
}
}
QImage BooksBook::coverImage()
{
return iCoverImage;
}
bool BooksBook::hasCoverImage() const
{
return iCoverImage.width() > 0 && iCoverImage.height() > 0;
@ -453,7 +441,8 @@ bool BooksBook::requestCoverImage()
if (!iBook.isNull() && !iFormatPlugin.isNull() &&
!iCoverTasksDone && !iCoverTask) {
HDEBUG(iTitle);
iCoverTask = new LoadCoverTask(iStateDir, iBook, iFormatPlugin);
iCoverTask = new LoadCoverTask(iStateDir, iBook, iFormatPlugin,
cachedImagePath());
connect(iCoverTask, SIGNAL(done()), SLOT(onLoadCoverTaskDone()));
iTaskQueue->submit(iCoverTask);
Q_EMIT loadingCoverChanged();
@ -492,7 +481,7 @@ void BooksBook::onLoadCoverTaskDone()
iCoverTasksDone = true;
Q_EMIT loadingCoverChanged();
} else {
iCoverTask = new GuessCoverTask(iStateDir, iBook);
iCoverTask = new GuessCoverTask(iStateDir, iBook, cachedImagePath());
connect(iCoverTask, SIGNAL(done()), SLOT(onGuessCoverTaskDone()));
iTaskQueue->submit(iCoverTask);
}
@ -501,22 +490,21 @@ void BooksBook::onLoadCoverTaskDone()
void BooksBook::onGuessCoverTaskDone()
{
HDEBUG(iTitle);
if (iCoverTask->iCoverMissing && !iCoverImage.isNull()) {
// This may happen after the book with custom cover has been moved
// between SD-card and the internal storage. Store the custom cover
// so that it doesn't get lost. This is a fairly rare situation.
QString coverPath(iCoverTask->cachedImagePath());
if (!coverPath.isEmpty() && iCoverImage.save(coverPath)) {
HDEBUG("saved custom cover to" << qPrintable(coverPath));
}
}
coverTaskDone();
iCoverTasksDone = true;
Q_EMIT loadingCoverChanged();
}
QString BooksBook::cachedImagePath() const
{
if (!iStateDir.isEmpty() && !iBook.isNull()) {
return QDir::cleanPath(iStateDir + QDir::separator() +
QString::fromStdString(iBook->file().name(false)) +
BOOK_COVER_SUFFIX "jpg");
}
return QString();
}
void BooksBook::saveState()
{
if (!iStateFilePath.isEmpty()) {
@ -551,6 +539,21 @@ void BooksBook::deleteFiles()
}
}
BooksBook* BooksBook::newBook(const BooksStorage& aStorage, QString aRelPath,
QString aFileName)
{
shared_ptr<Book> ref = BooksUtil::bookFromFile(
QFileInfo(QDir(aStorage.fullPath(aRelPath)), aFileName).
absoluteFilePath());
if (!ref.isNull()) {
BooksBook* book = new BooksBook(aStorage, aRelPath, ref);
book->moveToThread(qApp->thread());
return book;
} else {
return NULL;
}
}
// NOTE: below methods are invoked on the worker thread
bool BooksBook::makeLink(QString aDestPath)
{
@ -574,21 +577,24 @@ bool BooksBook::makeLink(QString aDestPath)
return false;
}
bool BooksBook::copyTo(QDir aDestDir, CopyOperation* aOperation)
BooksItem* BooksBook::copyTo(const BooksStorage& aStorage, QString aRelPath,
CopyOperation* aOperation)
{
QString destPath(QFileInfo(aDestDir, iFileName).absoluteFilePath());
aDestDir.mkpath(aDestDir.path());
if (!isCanceled(aOperation) && makeLink(destPath)) {
return true;
QDir destDir(aStorage.fullPath(aRelPath));
destDir.mkpath(destDir.path());
const QString absDestPath(QFileInfo(QDir(aStorage.fullPath(aRelPath)),
iFileName).absoluteFilePath());
if (!isCanceled(aOperation) && makeLink(absDestPath)) {
return newBook(aStorage, aRelPath, iFileName);
} else if (isCanceled(aOperation)) {
return true;
return NULL;
} else {
bool success = false;
BooksBook* copy = NULL;
QFile src(iPath);
const qint64 total = src.size();
qint64 copied = 0;
if (src.open(QIODevice::ReadOnly)) {
QFile dest(destPath);
QFile dest(absDestPath);
if (dest.open(QIODevice::WriteOnly)) {
QDateTime lastTime;
const qint64 bufsiz = 0x1000;
@ -614,32 +620,40 @@ bool BooksBook::copyTo(QDir aDestDir, CopyOperation* aOperation)
}
}
}
aOperation->copyProgressChanged(PROGRESS_PRECISION);
delete [] buf;
dest.close();
aOperation->copyProgressChanged(PROGRESS_PRECISION);
if (copied == total) {
dest.setPermissions(BOOKS_FILE_PERMISSIONS);
success = true;
HDEBUG(total << "bytes copied from"<< qPrintable(iPath) <<
"to" << qPrintable(destPath));
"to" << qPrintable(absDestPath));
copy = newBook(aStorage, aRelPath, iFileName);
// Copy cover image too
if (copy && !iCoverImage.isNull()) {
QString cover(copy->cachedImagePath());
if (!cover.isEmpty() && iCoverImage.save(cover)) {
HDEBUG("copied cover to" << qPrintable(cover));
}
}
} else {
if (isCanceled(aOperation)) {
HDEBUG("copy" << qPrintable(iPath) << "to" <<
qPrintable(destPath) << "cancelled");
qPrintable(absDestPath) << "cancelled");
} else {
HWARN(copied << "out of" << total <<
"bytes copied from" << qPrintable(iPath) <<
"to" << qPrintable(destPath));
"to" << qPrintable(absDestPath));
}
dest.remove();
}
} else {
HWARN("failed to open" << qPrintable(destPath));
HWARN("failed to open" << qPrintable(absDestPath));
}
src.close();
} else {
HWARN("failed to open" << qPrintable(iPath));
}
return success;
return copy;
}
}

View file

@ -70,6 +70,9 @@ public:
shared_ptr<Book> aBook);
~BooksBook();
static BooksBook* newBook(const BooksStorage& aStorage, QString aRelPath,
QString aFileName);
QString title() const { return iTitle; }
QString authors() const { return iAuthors; }
BooksPos lastPos() const { return iLastPos; }
@ -82,8 +85,7 @@ public:
bool requestCoverImage();
void cancelCoverRequest();
void setCoverImage(QImage aImage);
QImage coverImage();
QImage coverImage() const;
void setCopyingOut(bool aValue);
// BooksItem
@ -97,7 +99,8 @@ public:
virtual QString path() const;
virtual bool accessible() const;
virtual void deleteFiles();
virtual bool copyTo(QDir aDestDir, CopyOperation* aObserver);
virtual BooksItem* copyTo(const BooksStorage& aStorage, QString aRelPath,
CopyOperation* aObserver);
Q_SIGNALS:
void coverImageChanged();
@ -115,6 +118,7 @@ private:
void init();
bool coverTaskDone();
bool makeLink(QString aDestPath);
QString cachedImagePath() const;
static bool isCanceled(CopyOperation* aOperation);
private:
@ -141,5 +145,7 @@ QML_DECLARE_TYPE(BooksBook)
inline bool BooksBook::isCanceled(CopyOperation* aObserver)
{ return aObserver && aObserver->isCanceled(); }
inline QImage BooksBook::coverImage() const
{ return iCoverImage; }
#endif // BOOKS_BOOK_H

View file

@ -210,7 +210,7 @@ BooksBookModel::BooksBookModel(QObject* aParent) :
iTask(NULL),
iData(NULL),
iData2(NULL),
iTaskQueue(BooksTaskQueue::instance()),
iTaskQueue(BooksTaskQueue::defaultQueue()),
iTextStyle(BooksTextStyle::defaults())
{
HDEBUG("created");

View file

@ -198,7 +198,7 @@ void BooksCoverWidget::DefaultImage::release(QImage* aImage)
BooksCoverWidget::BooksCoverWidget(QQuickItem* aParent) :
QQuickPaintedItem(aParent),
iTaskQueue(BooksTaskQueue::instance()),
iTaskQueue(BooksTaskQueue::scaleQueue()),
iScaleTask(NULL),
iBook(NULL),
iDefaultImage(NULL),
@ -234,7 +234,6 @@ void BooksCoverWidget::setBook(BooksBook* aBook)
if (aBook) {
(iBook = aBook)->retain();
iBook->requestCoverImage();
iBookRef = iBook->bookRef();
iCoverImage = iBook->coverImage();
iTitle = iBook->title();
connect(iBook,
@ -246,7 +245,6 @@ void BooksCoverWidget::setBook(BooksBook* aBook)
HDEBUG(iTitle);
} else {
iBook = NULL;
iBookRef.reset();
iCoverImage = QImage();
iTitle.clear();
HDEBUG("<none>");
@ -333,7 +331,7 @@ void BooksCoverWidget::onSizeChanged()
bool BooksCoverWidget::empty() const
{
return !iBook || !iBook->hasCoverImage() || iScaledImage.isNull();
return iScaledImage.isNull();
}
bool BooksCoverWidget::loading() const
@ -358,6 +356,7 @@ void BooksCoverWidget::scaleImage(bool aWasEmpty)
HWARN("Failed to load" << qPrintable(path));
}
}
if (iCoverImage.isNull()) {
if (!iDefaultImage) iDefaultImage = DefaultImage::retain();
if (iDefaultImage) iCoverImage = *iDefaultImage;
@ -380,6 +379,8 @@ void BooksCoverWidget::scaleImage(bool aWasEmpty)
iScaledImage = QImage();
}
updateCenter();
if (aWasEmpty != empty()) {
Q_EMIT emptyChanged();
}
@ -393,6 +394,7 @@ void BooksCoverWidget::onScaleTaskDone()
iScaleTask->release(this);
iScaleTask = NULL;
update();
updateCenter();
if (wasEmpty != empty()) {
Q_EMIT emptyChanged();
}
@ -404,6 +406,8 @@ void BooksCoverWidget::paint(QPainter* aPainter)
const qreal h = height();
if (w > 0 && h > 0) {
qreal sw, sh;
// This has to be consistent with updateCenter()
if (!iScaledImage.isNull()) {
sw = iScaledImage.width();
sh = iScaledImage.height();
@ -412,7 +416,7 @@ void BooksCoverWidget::paint(QPainter* aPainter)
sh = h;
}
const int x = (w - sw)/2;
const int x = floor((w - sw)/2);
const int y = h - sh;
QPainterPath path;
@ -424,7 +428,7 @@ void BooksCoverWidget::paint(QPainter* aPainter)
const qreal d = 2*iBorderRadius;
w1 = qMin(w, qMax(sw, 2*d)) - iBorderWidth;
h1 = qMin(h, qMax(sh, 3*d)) - iBorderWidth;
x1 = (w - w1)/2;
x1 = floor((w - w1)/2);
y1 = h - h1 - iBorderWidth/2;
const qreal x2 = x1 + w1 - d;
@ -439,7 +443,7 @@ void BooksCoverWidget::paint(QPainter* aPainter)
} else {
w1 = sw - iBorderWidth;
h1 = sh - iBorderWidth;
x1 = (w - w1)/2;
x1 = floor((w - w1)/2);
y1 = h - h1 - iBorderWidth/2;
}
@ -461,3 +465,28 @@ void BooksCoverWidget::paint(QPainter* aPainter)
}
}
}
void BooksCoverWidget::updateCenter()
{
const QPoint oldCenter(iCenter);
const qreal w = width();
const qreal h = height();
// This has to be consistent with paint()
iCenter.setX(floor(w/2));
if (iScaledImage.isNull()) {
iCenter.setY(floor(h/2));
} else {
iCenter.setY(floor(h - iScaledImage.height()/2));
}
if (iCenter != oldCenter) {
Q_EMIT centerChanged();
if (iCenter.x() != oldCenter.x()) {
Q_EMIT centerXChanged();
}
if (iCenter.y() != oldCenter.y()) {
Q_EMIT centerYChanged();
}
}
}

View file

@ -57,6 +57,9 @@ class BooksCoverWidget: public QQuickPaintedItem
Q_PROPERTY(QColor borderColor READ borderColor WRITE setBorderColor NOTIFY borderColorChanged)
Q_PROPERTY(QUrl defaultCover READ defaultCover WRITE setDefaultCover NOTIFY defaultCoverChanged)
Q_PROPERTY(BooksBook* book READ book WRITE setBook NOTIFY bookChanged)
Q_PROPERTY(qreal centerX READ centerX NOTIFY centerXChanged)
Q_PROPERTY(qreal centerY READ centerY NOTIFY centerYChanged)
Q_PROPERTY(QPoint center READ center NOTIFY centerChanged)
public:
BooksCoverWidget(QQuickItem* aParent = NULL);
@ -86,6 +89,10 @@ public:
bool synchronous() const { return iSynchronous; }
void setSynchronous(bool aValue);
qreal centerX() const { return iCenter.x(); }
qreal centerY() const { return iCenter.y(); }
QPoint center() const { return iCenter; }
Q_SIGNALS:
void bookChanged();
void emptyChanged();
@ -96,6 +103,9 @@ Q_SIGNALS:
void borderRadiusChanged();
void borderColorChanged();
void defaultCoverChanged();
void centerXChanged();
void centerYChanged();
void centerChanged();
private Q_SLOTS:
void onCoverImageChanged();
@ -106,6 +116,7 @@ private:
void paint(QPainter *painter);
void scaleImage(bool aWasEmpty);
void scaleImage() { scaleImage(empty()); }
void updateCenter();
private:
class ScaleTask;
@ -114,7 +125,6 @@ private:
ScaleTask* iScaleTask;
QImage iScaledImage;
QImage iCoverImage;
shared_ptr<Book> iBookRef;
BooksBook* iBook;
QImage* iDefaultImage;
qreal iBorderWidth;
@ -122,6 +132,7 @@ private:
QColor iBorderColor;
QUrl iDefaultCover;
QString iTitle;
QPoint iCenter;
bool iStretch;
bool iSynchronous;
};

View file

@ -278,7 +278,7 @@ BooksImportModel::BooksImportModel(QObject* aParent) :
iProgress(0),
iSelectedCount(0),
iAutoRefresh(false),
iTaskQueue(BooksTaskQueue::instance()),
iTaskQueue(BooksTaskQueue::defaultQueue()),
iTask(NULL)
{
iSelectedRole.append(BooksImportRoleSelected);

View file

@ -35,6 +35,7 @@
#define BOOKS_ITEM_H
#include "BooksTypes.h"
#include "BooksStorage.h"
#include <QDir>
@ -65,7 +66,8 @@ public:
virtual QString path() const = 0;
virtual bool accessible() const = 0;
virtual void deleteFiles() = 0;
virtual bool copyTo(QDir aDestDir, CopyOperation* aOperation = NULL) = 0;
virtual BooksItem* copyTo(const BooksStorage& aStorage, QString aRelPath,
CopyOperation* aOperation = NULL) = 0;
};
#endif // BOOKS_ITEM_H

View file

@ -158,7 +158,7 @@ void BooksPageWidget::RenderTask::performTask()
BooksPageWidget::BooksPageWidget(QQuickItem* aParent) :
QQuickPaintedItem(aParent),
iTaskQueue(BooksTaskQueue::instance()),
iTaskQueue(BooksTaskQueue::defaultQueue()),
iTextStyle(BooksTextStyle::defaults()),
iResizeTimer(new QTimer(this)),
iModel(NULL),

View file

@ -77,9 +77,12 @@ Q_SIGNALS:
public:
BooksShelf::Data* iDestData;
BooksStorage iDestStorage;
QString iDestRelPath;
QString iDestAbsPath;
BooksItem* iSrcItem;
BooksItem* iDestItem;
int iCopyProgress;
bool iSuccess;
};
// ==========================================================================
@ -323,9 +326,12 @@ inline bool BooksShelf::Data::copyingOut()
BooksShelf::CopyTask::CopyTask(BooksShelf::Data* aDestData, BooksItem* aSrcItem) :
iDestData(aDestData),
iDestStorage(aDestData->iShelf->storage()),
iDestRelPath(aDestData->iShelf->relativePath()),
iDestAbsPath(iDestStorage.fullPath(iDestRelPath + "/" + aSrcItem->fileName())),
iSrcItem(aSrcItem->retain()),
iCopyProgress(0),
iSuccess(false)
iDestItem(NULL),
iCopyProgress(0)
{
if (iDestData->iCopyTask) {
iDestData->iCopyTask->release(iDestData->iShelf);
@ -341,6 +347,7 @@ BooksShelf::CopyTask::~CopyTask()
{
HASSERT(!iDestData);
iSrcItem->release();
if (iDestItem) iDestItem->release();
}
inline QString BooksShelf::CopyTask::srcPath() const
@ -350,13 +357,12 @@ inline QString BooksShelf::CopyTask::srcPath() const
inline QString BooksShelf::CopyTask::destPath() const
{
return QFileInfo(iDestData->iShelf->path(),
iSrcItem->fileName()).absoluteFilePath();
return iDestAbsPath;
}
void BooksShelf::CopyTask::performTask()
{
iSuccess = iSrcItem->copyTo(QDir(iDestData->iShelf->path()), this);
iDestItem = iSrcItem->copyTo(iDestStorage, iDestRelPath, this);
}
bool BooksShelf::CopyTask::isCanceled() const
@ -470,7 +476,7 @@ BooksShelf::BooksShelf(QObject* aParent) :
iEditMode(false),
iRef(-1),
iSaveTimer(new BooksSaveTimer(this)),
iTaskQueue(BooksTaskQueue::instance())
iTaskQueue(BooksTaskQueue::defaultQueue())
{
init();
connect(iSaveTimer, SIGNAL(save()), SLOT(saveState()));
@ -485,7 +491,7 @@ BooksShelf::BooksShelf(BooksStorage aStorage, QString aRelativePath) :
iEditMode(false),
iRef(1),
iSaveTimer(NULL),
iTaskQueue(BooksTaskQueue::instance())
iTaskQueue(BooksTaskQueue::defaultQueue())
{
init();
// Refcounted BooksShelf objects are managed by C++ code
@ -1088,7 +1094,7 @@ void BooksShelf::onCopyTaskDone()
if (task) {
QString dest = task->destPath();
HDEBUG(qPrintable(task->srcPath()) << "->" << qPrintable(dest) <<
"copy" << (task->iSuccess ? "done" : "FAILED"));
"copy" << (task->iDestItem ? "done" : "FAILED"));
Data* data = task->iDestData;
const int row = iList.indexOf(data);
@ -1099,15 +1105,15 @@ void BooksShelf::onCopyTaskDone()
HASSERT(src);
if (src) {
src->retain();
if (task->iSuccess) {
shared_ptr<Book> book = BooksUtil::bookFromFile(dest);
if (!book.isNull()) {
copy = new BooksBook(iStorage, iRelativePath, book);
if (task->iDestItem) {
copy = task->iDestItem->book();
if (copy) {
copy->retain();
copy->setLastPos(src->lastPos());
copy->setCoverImage(src->coverImage());
copy->requestCoverImage();
} else {
HWARN("can't open copied book" << qPrintable(dest));
HWARN("not a book:" << qPrintable(dest));
}
}
}
@ -1167,10 +1173,11 @@ void BooksShelf::deleteFiles()
}
}
bool BooksShelf::copyTo(QDir aDestDir, CopyOperation* aOperation)
BooksItem* BooksShelf::copyTo(const BooksStorage& aStorage, QString aRelPath,
CopyOperation* aObserver)
{
HWARN("copying folders is not implemented!!");
return false;
return NULL;
}
QHash<int,QByteArray> BooksShelf::roleNames() const

View file

@ -65,7 +65,7 @@ class BooksShelf: public QAbstractListModel, public BooksItem, public BooksLoadi
Q_PROPERTY(int dummyItemIndex READ dummyItemIndex WRITE setDummyItemIndex NOTIFY dummyItemIndexChanged)
Q_PROPERTY(BooksBook* book READ book CONSTANT)
Q_PROPERTY(BooksShelf* shelf READ shelf CONSTANT)
Q_PROPERTY(QObject* storage READ storage CONSTANT)
Q_PROPERTY(QObject* storage READ storageObject CONSTANT)
public:
explicit BooksShelf(QObject* aParent = NULL);
@ -89,7 +89,8 @@ public:
QString relativePath() const { return iRelativePath; }
void setRelativePath(QString aPath);
BooksBook* bookAt(int aIndex) const;
QObject* storage() { return &iStorage; }
QObject* storageObject() { return &iStorage; }
const BooksStorage& storage() const { return iStorage; }
void setName(QString aName);
bool editMode() const { return iEditMode; }
@ -120,7 +121,8 @@ public:
virtual QString path() const;
virtual bool accessible() const;
virtual void deleteFiles();
virtual bool copyTo(QDir aDestDir, CopyOperation* aOperation);
virtual BooksItem* copyTo(const BooksStorage& aStorage, QString aRelPath,
CopyOperation* aObserver);
Q_SIGNALS:
void loadingChanged();

View file

@ -36,32 +36,61 @@
#include "HarbourDebug.h"
static weak_ptr<BooksTaskQueue> booksTaskQueueInstance;
class BooksTaskQueue::Private {
public:
static weak_ptr<BooksTaskQueue> gDefaultQueue;
static weak_ptr<BooksTaskQueue> gScaleQueue;
shared_ptr<BooksTaskQueue> BooksTaskQueue::instance()
{
shared_ptr<BooksTaskQueue> worker;
if (booksTaskQueueInstance.isNull()) {
booksTaskQueueInstance = (worker = new BooksTaskQueue());
} else {
worker = booksTaskQueueInstance;
static BooksTaskQueue* newDefaultQueue() { return new BooksTaskQueue(1); }
static BooksTaskQueue* newScaleQueue() { return new BooksTaskQueue(2); }
static void waitForDone(shared_ptr<BooksTaskQueue> aQueue, int aMsecs) {
if (!aQueue.isNull()) {
aQueue->iPool->waitForDone(aMsecs);
}
}
return worker;
static void waitForDone(int aMsecs) {
waitForDone(gDefaultQueue, aMsecs);
waitForDone(gScaleQueue, aMsecs);
}
static shared_ptr<BooksTaskQueue> get(weak_ptr<BooksTaskQueue>* aQueue,
BooksTaskQueue* (*aNewFunc)())
{
shared_ptr<BooksTaskQueue> queue;
if (aQueue->isNull()) {
*aQueue = (queue = aNewFunc());
} else {
queue = *aQueue;
}
return queue;
}
};
weak_ptr<BooksTaskQueue> BooksTaskQueue::Private::gDefaultQueue;
weak_ptr<BooksTaskQueue> BooksTaskQueue::Private::gScaleQueue;
shared_ptr<BooksTaskQueue> BooksTaskQueue::defaultQueue()
{
return Private::get(&Private::gDefaultQueue, Private::newDefaultQueue);
}
BooksTaskQueue::BooksTaskQueue() :
iPool(new QThreadPool)
shared_ptr<BooksTaskQueue> BooksTaskQueue::scaleQueue()
{
HDEBUG("created");
iPool->setMaxThreadCount(1);
return Private::get(&Private::gScaleQueue, Private::newScaleQueue);
}
void BooksTaskQueue::waitForDone(int aMsecs)
{
shared_ptr<BooksTaskQueue> worker = booksTaskQueueInstance;
if (!worker.isNull()) {
worker->iPool->waitForDone(aMsecs);
}
Private::waitForDone(aMsecs);
}
BooksTaskQueue::BooksTaskQueue(int aMaxThreadCount) :
iPool(new QThreadPool)
{
HDEBUG("created");
iPool->setMaxThreadCount(aMaxThreadCount);
}
BooksTaskQueue::~BooksTaskQueue()

View file

@ -45,17 +45,20 @@ class BooksTaskQueue
friend class shared_ptr_storage<BooksTaskQueue>;
public:
static shared_ptr<BooksTaskQueue> instance();
static shared_ptr<BooksTaskQueue> defaultQueue();
static shared_ptr<BooksTaskQueue> scaleQueue();
static void waitForDone(int aMsecs = -1);
void submit(BooksTask* aTask);
void submit(BooksTask* aTask, QObject* aTarget, const char* aSlot);
private:
BooksTaskQueue();
BooksTaskQueue(int aMaxThreadCount);
~BooksTaskQueue();
private:
class Private;
friend class Private;
QThreadPool* iPool;
};