Fix the number of displayed items in progress display for removes.

This fixes mirall#1132

A variable that counts the affected items of the propagator operation
done on a item was added to SyncFileItem. Usually that is 1 because
most operations affect only the item itself. But for removes, the
number can be higher for directories (one remove removes a whole tree).

Some rearrangements were needed.
This commit is contained in:
Klaas Freitag 2014-12-06 12:27:50 +01:00
parent a43173fa90
commit 1d6661e7e4
5 changed files with 89 additions and 61 deletions

View file

@ -248,13 +248,23 @@ void OwncloudPropagator::start(const SyncFileItemVector& items)
if (!removedDirectory.isEmpty() && item._file.startsWith(removedDirectory)) {
// this is an item in a directory which is going to be removed.
PropagateDirectory *delDirJob = dynamic_cast<PropagateDirectory*>(directoriesToRemove.last());
if (item._instruction == CSYNC_INSTRUCTION_REMOVE) {
//already taken care of. (by the removal of the parent directory)
// increase the number of subjobs that would be there.
if( delDirJob ) {
delDirJob->increaseAffectedCount();
}
continue;
} else if (item._instruction == CSYNC_INSTRUCTION_NEW && item._isDirectory) {
// create a new directory within a deleted directory? That can happen if the directory
// etag were not fetched properly on the previous sync because the sync was aborted
// while uploading this directory (which is now removed). We can ignore it.
if( delDirJob ) {
delDirJob->increaseAffectedCount();
}
continue;
} else if (item._instruction == CSYNC_INSTRUCTION_IGNORE) {
continue;

View file

@ -71,59 +71,6 @@ signals:
};
/*
* Propagate a directory, and all its sub entries.
*/
class PropagateDirectory : public PropagatorJob {
Q_OBJECT
public:
// e.g: create the directory
QScopedPointer<PropagatorJob>_firstJob;
// all the sub files or sub directories.
QVector<PropagatorJob *> _subJobs;
SyncFileItem _item;
int _current; // index of the current running job
int _runningNow; // number of subJob running now
SyncFileItem::Status _hasError; // NoStatus, or NormalError / SoftError if there was an error
explicit PropagateDirectory(OwncloudPropagator *propagator, const SyncFileItem &item = SyncFileItem())
: PropagatorJob(propagator)
, _firstJob(0), _item(item), _current(-1), _runningNow(0), _hasError(SyncFileItem::NoStatus) { }
virtual ~PropagateDirectory() {
qDeleteAll(_subJobs);
}
void append(PropagatorJob *subJob) {
_subJobs.append(subJob);
}
virtual void start() Q_DECL_OVERRIDE;
virtual void abort() Q_DECL_OVERRIDE {
if (_firstJob)
_firstJob->abort();
foreach (PropagatorJob *j, _subJobs)
j->abort();
}
private slots:
void startJob(PropagatorJob *next) {
connect(next, SIGNAL(finished(SyncFileItem::Status)), this, SLOT(slotSubJobFinished(SyncFileItem::Status)), Qt::QueuedConnection);
connect(next, SIGNAL(completed(SyncFileItem)), this, SIGNAL(completed(SyncFileItem)));
connect(next, SIGNAL(progress(SyncFileItem,quint64)), this, SIGNAL(progress(SyncFileItem,quint64)));
connect(next, SIGNAL(ready()), this, SLOT(slotSubJobReady()));
_runningNow++;
QMetaObject::invokeMethod(next, "start", Qt::QueuedConnection);
}
void slotSubJobFinished(SyncFileItem::Status status);
void slotSubJobReady();
};
/*
* Abstract class to propagate a single item
@ -148,8 +95,6 @@ protected:
_item._errorString = msg;
}
SyncFileItem _item;
protected slots:
void slotRestoreJobCompleted(const SyncFileItem& );
@ -160,8 +105,69 @@ public:
PropagateItemJob(OwncloudPropagator* propagator, const SyncFileItem &item)
: PropagatorJob(propagator), _item(item) {}
SyncFileItem _item;
};
/*
* Propagate a directory, and all its sub entries.
*/
class PropagateDirectory : public PropagatorJob {
Q_OBJECT
public:
// e.g: create the directory
QScopedPointer<PropagateItemJob>_firstJob;
// all the sub files or sub directories.
QVector<PropagatorJob *> _subJobs;
SyncFileItem _item;
int _current; // index of the current running job
int _runningNow; // number of subJob running now
SyncFileItem::Status _hasError; // NoStatus, or NormalError / SoftError if there was an error
explicit PropagateDirectory(OwncloudPropagator *propagator, const SyncFileItem &item = SyncFileItem())
: PropagatorJob(propagator)
, _firstJob(0), _item(item), _current(-1), _runningNow(0), _hasError(SyncFileItem::NoStatus)
{ }
virtual ~PropagateDirectory() {
qDeleteAll(_subJobs);
}
void append(PropagatorJob *subJob) {
_subJobs.append(subJob);
}
virtual void start() Q_DECL_OVERRIDE;
virtual void abort() Q_DECL_OVERRIDE {
if (_firstJob)
_firstJob->abort();
foreach (PropagatorJob *j, _subJobs)
j->abort();
}
void increaseAffectedCount() {
_firstJob->_item._affectedItems++;
}
private slots:
void startJob(PropagatorJob *next) {
connect(next, SIGNAL(finished(SyncFileItem::Status)), this, SLOT(slotSubJobFinished(SyncFileItem::Status)), Qt::QueuedConnection);
connect(next, SIGNAL(completed(SyncFileItem)), this, SIGNAL(completed(SyncFileItem)));
connect(next, SIGNAL(progress(SyncFileItem,quint64)), this, SIGNAL(progress(SyncFileItem,quint64)));
connect(next, SIGNAL(ready()), this, SLOT(slotSubJobReady()));
_runningNow++;
QMetaObject::invokeMethod(next, "start", Qt::QueuedConnection);
}
void slotSubJobFinished(SyncFileItem::Status status);
void slotSubJobReady();
};
// Dummy job that just mark it as completed and ignored.
class PropagateIgnoreJob : public PropagateItemJob {
Q_OBJECT

View file

@ -20,6 +20,8 @@
#include <QTime>
#include <QQueue>
#include <QElapsedTimer>
#include <QDebug>
#include "syncfileitem.h"
namespace Mirall {
@ -112,11 +114,13 @@ namespace Progress
void setProgressComplete(const SyncFileItem &item) {
_currentItems.remove(item._file);
_completedFileCount += item._affectedItems;
if (!item._isDirectory) {
_completedFileCount++;
if (Progress::isSizeDependent(item._instruction)) {
_completedSize += item._size;
}
if (Progress::isSizeDependent(item._instruction)) {
_completedSize += item._size;
}
} else {
qDebug() << "Also reached for directories!";
}
_lastCompletedItem = item;
this->updateEstimation();

View file

@ -380,7 +380,11 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote )
Q_ASSERT("Non handled error-status");
/* No error string */
}
item._isDirectory = file->type == CSYNC_FTW_TYPE_DIR;
if(item._isDirectory) {
item._affectedItems = 0; // defaults to 1 for normal items.
}
// The etag is already set in the previous sync phases somewhere. Maybe we should remove it there
// and do it here so we have a consistent state about which tree stores information from which source.

View file

@ -53,7 +53,10 @@ public:
SyncFileItem() : _type(UnknownType), _direction(None), _isDirectory(false),
_instruction(CSYNC_INSTRUCTION_NONE), _modtime(0),
_size(0), _inode(0), _should_update_etag(false), _hasBlacklistEntry(false),
_status(NoStatus), _httpErrorCode(0), _requestDuration(0), _isRestoration(false) {}
_status(NoStatus), _httpErrorCode(0), _requestDuration(0), _isRestoration(false),
_affectedItems(1)
{
}
friend bool operator==(const SyncFileItem& item1, const SyncFileItem& item2) {
return item1._file == item2._file;
@ -111,7 +114,8 @@ public:
QString _responseTimeStamp;
quint64 _requestDuration;
bool _isRestoration; // The original operation was forbidden, and this is a restoration
int _affectedItems; // the number of affected items by the operation on this item.
// usually this value is 1, but for removes on dirs, it might be much higher.
struct {
quint64 _size;
time_t _modtime;