mirror of
https://github.com/nextcloud/desktop.git
synced 2024-10-27 15:05:19 +03:00
Time estimate: Refactor remaining time guess. #2328
This commit is contained in:
parent
7d68c628db
commit
96ecdb866d
15 changed files with 396 additions and 200 deletions
|
@ -471,7 +471,7 @@ restart_sync:
|
||||||
|
|
||||||
SyncEngine engine(account, _csync_ctx, options.source_dir, QUrl(options.target_url).path(), folder, &db);
|
SyncEngine engine(account, _csync_ctx, options.source_dir, QUrl(options.target_url).path(), folder, &db);
|
||||||
QObject::connect(&engine, SIGNAL(finished()), &app, SLOT(quit()));
|
QObject::connect(&engine, SIGNAL(finished()), &app, SLOT(quit()));
|
||||||
QObject::connect(&engine, SIGNAL(transmissionProgress(Progress::Info)), &cmd, SLOT(transmissionProgressSlot()));
|
QObject::connect(&engine, SIGNAL(transmissionProgress(ProgressInfo)), &cmd, SLOT(transmissionProgressSlot()));
|
||||||
|
|
||||||
engine.setSelectiveSyncBlackList(selectiveSyncList);
|
engine.setSelectiveSyncBlackList(selectiveSyncList);
|
||||||
|
|
||||||
|
|
|
@ -593,7 +593,7 @@ QString AccountSettings::shortenFilename( const QString& folder, const QString&
|
||||||
return shortFile;
|
return shortFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountSettings::slotSetProgress(const QString& folder, const Progress::Info &progress )
|
void AccountSettings::slotSetProgress(const QString& folder, const ProgressInfo &progress )
|
||||||
{
|
{
|
||||||
if (!isVisible()) {
|
if (!isVisible()) {
|
||||||
return; // for https://github.com/owncloud/client/issues/2648#issuecomment-71377909
|
return; // for https://github.com/owncloud/client/issues/2648#issuecomment-71377909
|
||||||
|
@ -630,10 +630,10 @@ void AccountSettings::slotSetProgress(const QString& folder, const Progress::Inf
|
||||||
SyncFileItem curItem = progress._lastCompletedItem;
|
SyncFileItem curItem = progress._lastCompletedItem;
|
||||||
qint64 curItemProgress = -1; // -1 means finished
|
qint64 curItemProgress = -1; // -1 means finished
|
||||||
quint64 biggerItemSize = -1;
|
quint64 biggerItemSize = -1;
|
||||||
foreach(const Progress::Info::ProgressItem &citm, progress._currentItems) {
|
foreach(const ProgressInfo::ProgressItem &citm, progress._currentItems) {
|
||||||
if (curItemProgress == -1 || (Progress::isSizeDependent(citm._item)
|
if (curItemProgress == -1 || (ProgressInfo::isSizeDependent(citm._item)
|
||||||
&& biggerItemSize < citm._item._size)) {
|
&& biggerItemSize < citm._item._size)) {
|
||||||
curItemProgress = citm._completedSize;
|
curItemProgress = citm._progress.completed();
|
||||||
curItem = citm._item;
|
curItem = citm._item;
|
||||||
biggerItemSize = citm._item._size;
|
biggerItemSize = citm._item._size;
|
||||||
}
|
}
|
||||||
|
@ -648,15 +648,15 @@ void AccountSettings::slotSetProgress(const QString& folder, const Progress::Inf
|
||||||
|
|
||||||
|
|
||||||
QString fileProgressString;
|
QString fileProgressString;
|
||||||
if (Progress::isSizeDependent(curItem)) {
|
if (ProgressInfo::isSizeDependent(curItem)) {
|
||||||
QString s1 = Utility::octetsToString( curItemProgress );
|
QString s1 = Utility::octetsToString( curItemProgress );
|
||||||
QString s2 = Utility::octetsToString( curItem._size );
|
QString s2 = Utility::octetsToString( curItem._size );
|
||||||
quint64 estimatedBw = progress.getFileEstimate(curItem).getEstimatedBandwidth();
|
quint64 estimatedBw = progress.fileProgress(curItem).estimatedBandwidth;
|
||||||
if (estimatedBw) {
|
if (estimatedBw) {
|
||||||
//: Example text: "uploading foobar.png (1MB of 2MB) time left 2 minutes at a rate of 24Kb/s"
|
//: Example text: "uploading foobar.png (1MB of 2MB) time left 2 minutes at a rate of 24Kb/s"
|
||||||
fileProgressString = tr("%1 %2 (%3 of %4) %5 left at a rate of %6/s")
|
fileProgressString = tr("%1 %2 (%3 of %4) %5 left at a rate of %6/s")
|
||||||
.arg(kindString, itemFileName, s1, s2,
|
.arg(kindString, itemFileName, s1, s2,
|
||||||
Utility::timeToDescriptiveString(progress.getFileEstimate(curItem).getEtaEstimate(), 3, " ", true),
|
Utility::timeToDescriptiveString(progress.fileProgress(curItem).estimatedEta, 3, " ", true),
|
||||||
Utility::octetsToString(estimatedBw) );
|
Utility::octetsToString(estimatedBw) );
|
||||||
} else {
|
} else {
|
||||||
//: Example text: "uploading foobar.png (2MB of 2MB)"
|
//: Example text: "uploading foobar.png (2MB of 2MB)"
|
||||||
|
@ -670,11 +670,12 @@ void AccountSettings::slotSetProgress(const QString& folder, const Progress::Inf
|
||||||
|
|
||||||
// overall progress
|
// overall progress
|
||||||
quint64 completedSize = progress.completedSize();
|
quint64 completedSize = progress.completedSize();
|
||||||
quint64 currentFile = progress._completedFileCount + progress._currentItems.count();
|
quint64 completedFile = progress.completedFiles();
|
||||||
|
quint64 currentFile = progress.currentFile();
|
||||||
if (currentFile == ULLONG_MAX)
|
if (currentFile == ULLONG_MAX)
|
||||||
currentFile = 0;
|
currentFile = 0;
|
||||||
quint64 totalSize = qMax(completedSize, progress._totalSize);
|
quint64 totalSize = qMax(completedSize, progress.totalSize());
|
||||||
quint64 totalFileCount = qMax(currentFile, progress._totalFileCount);
|
quint64 totalFileCount = qMax(currentFile, progress.totalFiles());
|
||||||
QString overallSyncString;
|
QString overallSyncString;
|
||||||
if (totalSize > 0) {
|
if (totalSize > 0) {
|
||||||
QString s1 = Utility::octetsToString( completedSize );
|
QString s1 = Utility::octetsToString( completedSize );
|
||||||
|
@ -682,7 +683,7 @@ void AccountSettings::slotSetProgress(const QString& folder, const Progress::Inf
|
||||||
overallSyncString = tr("%1 of %2, file %3 of %4\nTotal time left %5")
|
overallSyncString = tr("%1 of %2, file %3 of %4\nTotal time left %5")
|
||||||
.arg(s1, s2)
|
.arg(s1, s2)
|
||||||
.arg(currentFile).arg(totalFileCount)
|
.arg(currentFile).arg(totalFileCount)
|
||||||
.arg( Utility::timeToDescriptiveString(progress.totalEstimate().getEtaEstimate(), 3, " ", true) );
|
.arg( Utility::timeToDescriptiveString(progress.totalProgress().estimatedEta, 3, " ", true) );
|
||||||
} else if (totalFileCount > 0) {
|
} else if (totalFileCount > 0) {
|
||||||
// Don't attemt to estimate the time left if there is no kb to transfer.
|
// Don't attemt to estimate the time left if there is no kb to transfer.
|
||||||
overallSyncString = tr("file %1 of %2") .arg(currentFile).arg(totalFileCount);
|
overallSyncString = tr("file %1 of %2") .arg(currentFile).arg(totalFileCount);
|
||||||
|
@ -693,7 +694,7 @@ void AccountSettings::slotSetProgress(const QString& folder, const Progress::Inf
|
||||||
int overallPercent = 0;
|
int overallPercent = 0;
|
||||||
if( totalFileCount > 0 ) {
|
if( totalFileCount > 0 ) {
|
||||||
// Add one 'byte' for each files so the percentage is moving when deleting or renaming files
|
// Add one 'byte' for each files so the percentage is moving when deleting or renaming files
|
||||||
overallPercent = qRound(double(completedSize + progress._completedFileCount)/double(totalSize + totalFileCount) * 100.0);
|
overallPercent = qRound(double(completedSize + completedFile)/double(totalSize + totalFileCount) * 100.0);
|
||||||
}
|
}
|
||||||
overallPercent = qBound(0, overallPercent, 100);
|
overallPercent = qBound(0, overallPercent, 100);
|
||||||
item->setData( overallPercent, FolderStatusDelegate::SyncProgressOverallPercent);
|
item->setData( overallPercent, FolderStatusDelegate::SyncProgressOverallPercent);
|
||||||
|
|
|
@ -61,7 +61,7 @@ public slots:
|
||||||
void slotOpenOC();
|
void slotOpenOC();
|
||||||
void slotUpdateFolderState( Folder* );
|
void slotUpdateFolderState( Folder* );
|
||||||
void slotDoubleClicked( const QModelIndex& );
|
void slotDoubleClicked( const QModelIndex& );
|
||||||
void slotSetProgress(const QString& folder, const Progress::Info& progress);
|
void slotSetProgress(const QString& folder, const ProgressInfo& progress);
|
||||||
void slotButtonsSetEnabled();
|
void slotButtonsSetEnabled();
|
||||||
|
|
||||||
void slotUpdateQuota( qint64,qint64 );
|
void slotUpdateQuota( qint64,qint64 );
|
||||||
|
|
|
@ -136,8 +136,6 @@ Application::Application(int &argc, char **argv) :
|
||||||
|
|
||||||
setQuitOnLastWindowClosed(false);
|
setQuitOnLastWindowClosed(false);
|
||||||
|
|
||||||
qRegisterMetaType<Progress::Info>("Progress::Info");
|
|
||||||
|
|
||||||
ConfigFile cfg;
|
ConfigFile cfg;
|
||||||
_theme->setSystrayUseMonoIcons(cfg.monoIcons());
|
_theme->setSystrayUseMonoIcons(cfg.monoIcons());
|
||||||
connect (_theme, SIGNAL(systrayUseMonoIconsChanged(bool)), SLOT(slotUseMonoIconsChanged(bool)));
|
connect (_theme, SIGNAL(systrayUseMonoIconsChanged(bool)), SLOT(slotUseMonoIconsChanged(bool)));
|
||||||
|
|
|
@ -804,7 +804,7 @@ void Folder::startSync(const QStringList &pathList)
|
||||||
connect(_engine.data(), SIGNAL(aboutToRemoveAllFiles(SyncFileItem::Direction,bool*)),
|
connect(_engine.data(), SIGNAL(aboutToRemoveAllFiles(SyncFileItem::Direction,bool*)),
|
||||||
SLOT(slotAboutToRemoveAllFiles(SyncFileItem::Direction,bool*)));
|
SLOT(slotAboutToRemoveAllFiles(SyncFileItem::Direction,bool*)));
|
||||||
connect(_engine.data(), SIGNAL(folderDiscovered(bool,QString)), this, SLOT(slotFolderDiscovered(bool,QString)));
|
connect(_engine.data(), SIGNAL(folderDiscovered(bool,QString)), this, SLOT(slotFolderDiscovered(bool,QString)));
|
||||||
connect(_engine.data(), SIGNAL(transmissionProgress(Progress::Info)), this, SLOT(slotTransmissionProgress(Progress::Info)));
|
connect(_engine.data(), SIGNAL(transmissionProgress(ProgressInfo)), this, SLOT(slotTransmissionProgress(ProgressInfo)));
|
||||||
connect(_engine.data(), SIGNAL(jobCompleted(const SyncFileItem &)), this, SLOT(slotJobCompleted(const SyncFileItem &)));
|
connect(_engine.data(), SIGNAL(jobCompleted(const SyncFileItem &)), this, SLOT(slotJobCompleted(const SyncFileItem &)));
|
||||||
connect(_engine.data(), SIGNAL(syncItemDiscovered(const SyncFileItem &)), this, SLOT(slotSyncItemDiscovered(const SyncFileItem &)));
|
connect(_engine.data(), SIGNAL(syncItemDiscovered(const SyncFileItem &)), this, SLOT(slotSyncItemDiscovered(const SyncFileItem &)));
|
||||||
|
|
||||||
|
@ -959,7 +959,7 @@ void Folder::slotEmitFinishedDelayed()
|
||||||
|
|
||||||
void Folder::slotFolderDiscovered(bool, QString folderName)
|
void Folder::slotFolderDiscovered(bool, QString folderName)
|
||||||
{
|
{
|
||||||
Progress::Info pi;
|
ProgressInfo pi;
|
||||||
pi._currentDiscoveredFolder = folderName;
|
pi._currentDiscoveredFolder = folderName;
|
||||||
ProgressDispatcher::instance()->setProgressInfo(alias(), pi);
|
ProgressDispatcher::instance()->setProgressInfo(alias(), pi);
|
||||||
}
|
}
|
||||||
|
@ -967,10 +967,10 @@ void Folder::slotFolderDiscovered(bool, QString folderName)
|
||||||
|
|
||||||
// the progress comes without a folder and the valid path set. Add that here
|
// the progress comes without a folder and the valid path set. Add that here
|
||||||
// and hand the result over to the progress dispatcher.
|
// and hand the result over to the progress dispatcher.
|
||||||
void Folder::slotTransmissionProgress(const Progress::Info &pi)
|
void Folder::slotTransmissionProgress(const ProgressInfo &pi)
|
||||||
{
|
{
|
||||||
if( pi._completedFileCount ) {
|
if( !pi.hasStarted() ) {
|
||||||
// No job completed yet, this is the beginning of a sync, set the warning level to 0
|
// this is the beginning of a sync, set the warning level to 0
|
||||||
_syncResult.setWarnCount(0);
|
_syncResult.setWarnCount(0);
|
||||||
}
|
}
|
||||||
ProgressDispatcher::instance()->setProgressInfo(alias(), pi);
|
ProgressDispatcher::instance()->setProgressInfo(alias(), pi);
|
||||||
|
|
|
@ -181,7 +181,7 @@ private slots:
|
||||||
void slotSyncFinished();
|
void slotSyncFinished();
|
||||||
|
|
||||||
void slotFolderDiscovered(bool local, QString folderName);
|
void slotFolderDiscovered(bool local, QString folderName);
|
||||||
void slotTransmissionProgress(const Progress::Info& pi);
|
void slotTransmissionProgress(const ProgressInfo& pi);
|
||||||
void slotJobCompleted(const SyncFileItem&);
|
void slotJobCompleted(const SyncFileItem&);
|
||||||
void slotSyncItemDiscovered(const SyncFileItem & item);
|
void slotSyncItemDiscovered(const SyncFileItem & item);
|
||||||
|
|
||||||
|
|
|
@ -79,8 +79,8 @@ ownCloudGui::ownCloudGui(Application *parent) :
|
||||||
this, SLOT(slotOpenPath(QString)));
|
this, SLOT(slotOpenPath(QString)));
|
||||||
|
|
||||||
ProgressDispatcher *pd = ProgressDispatcher::instance();
|
ProgressDispatcher *pd = ProgressDispatcher::instance();
|
||||||
connect( pd, SIGNAL(progressInfo(QString,Progress::Info)), this,
|
connect( pd, SIGNAL(progressInfo(QString,ProgressInfo)), this,
|
||||||
SLOT(slotUpdateProgress(QString,Progress::Info)) );
|
SLOT(slotUpdateProgress(QString,ProgressInfo)) );
|
||||||
|
|
||||||
FolderMan *folderMan = FolderMan::instance();
|
FolderMan *folderMan = FolderMan::instance();
|
||||||
connect( folderMan, SIGNAL(folderSyncStateChange(QString)),
|
connect( folderMan, SIGNAL(folderSyncStateChange(QString)),
|
||||||
|
@ -469,24 +469,24 @@ void ownCloudGui::slotRebuildRecentMenus()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ownCloudGui::slotUpdateProgress(const QString &folder, const Progress::Info& progress)
|
void ownCloudGui::slotUpdateProgress(const QString &folder, const ProgressInfo& progress)
|
||||||
{
|
{
|
||||||
Q_UNUSED(folder);
|
Q_UNUSED(folder);
|
||||||
|
|
||||||
if (!progress._currentDiscoveredFolder.isEmpty()) {
|
if (!progress._currentDiscoveredFolder.isEmpty()) {
|
||||||
_actionStatus->setText( tr("Discovering '%1'")
|
_actionStatus->setText( tr("Discovering '%1'")
|
||||||
.arg( progress._currentDiscoveredFolder ));
|
.arg( progress._currentDiscoveredFolder ));
|
||||||
} else if (progress._totalSize == 0 ) {
|
} else if (progress.totalSize() == 0 ) {
|
||||||
quint64 currentFile = progress._completedFileCount + progress._currentItems.count();
|
quint64 currentFile = progress.currentFile();
|
||||||
quint64 totalFileCount = qMax(progress._totalFileCount, currentFile);
|
quint64 totalFileCount = qMax(progress.totalFiles(), currentFile);
|
||||||
_actionStatus->setText( tr("Syncing %1 of %2 (%3 left)")
|
_actionStatus->setText( tr("Syncing %1 of %2 (%3 left)")
|
||||||
.arg( currentFile ).arg( totalFileCount )
|
.arg( currentFile ).arg( totalFileCount )
|
||||||
.arg( Utility::timeToDescriptiveString(progress.totalEstimate().getEtaEstimate(), 2, " ",true) ) );
|
.arg( Utility::timeToDescriptiveString(progress.totalProgress().estimatedEta, 2, " ",true) ) );
|
||||||
} else {
|
} else {
|
||||||
QString totalSizeStr = Utility::octetsToString( progress._totalSize );
|
QString totalSizeStr = Utility::octetsToString( progress.totalSize() );
|
||||||
_actionStatus->setText( tr("Syncing %1 (%2 left)")
|
_actionStatus->setText( tr("Syncing %1 (%2 left)")
|
||||||
.arg( totalSizeStr )
|
.arg( totalSizeStr )
|
||||||
.arg( Utility::timeToDescriptiveString(progress.totalEstimate().getEtaEstimate(), 2, " ",true) ) );
|
.arg( Utility::timeToDescriptiveString(progress.totalProgress().estimatedEta, 2, " ",true) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -524,8 +524,8 @@ void ownCloudGui::slotUpdateProgress(const QString &folder, const Progress::Info
|
||||||
slotRebuildRecentMenus();
|
slotRebuildRecentMenus();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (progress._completedFileCount != ULLONG_MAX
|
if (progress.hasStarted()
|
||||||
&& progress._completedFileCount >= progress._totalFileCount
|
&& progress.completedFiles() >= progress.totalFiles()
|
||||||
&& progress._currentDiscoveredFolder.isEmpty()) {
|
&& progress._currentDiscoveredFolder.isEmpty()) {
|
||||||
QTimer::singleShot(2000, this, SLOT(slotDisplayIdle()));
|
QTimer::singleShot(2000, this, SLOT(slotDisplayIdle()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ public slots:
|
||||||
void slotFolderOpenAction( const QString& alias );
|
void slotFolderOpenAction( const QString& alias );
|
||||||
void slotRefreshQuotaDisplay( qint64 total, qint64 used );
|
void slotRefreshQuotaDisplay( qint64 total, qint64 used );
|
||||||
void slotRebuildRecentMenus();
|
void slotRebuildRecentMenus();
|
||||||
void slotUpdateProgress(const QString &folder, const Progress::Info& progress);
|
void slotUpdateProgress(const QString &folder, const ProgressInfo& progress);
|
||||||
void slotShowGuiMessage(const QString &title, const QString &message);
|
void slotShowGuiMessage(const QString &title, const QString &message);
|
||||||
void slotFoldersChanged();
|
void slotFoldersChanged();
|
||||||
void slotShowSettings();
|
void slotShowSettings();
|
||||||
|
|
|
@ -40,8 +40,8 @@ ProtocolWidget::ProtocolWidget(QWidget *parent) :
|
||||||
{
|
{
|
||||||
_ui->setupUi(this);
|
_ui->setupUi(this);
|
||||||
|
|
||||||
connect(ProgressDispatcher::instance(), SIGNAL(progressInfo(QString,Progress::Info)),
|
connect(ProgressDispatcher::instance(), SIGNAL(progressInfo(QString,ProgressInfo)),
|
||||||
this, SLOT(slotProgressInfo(QString,Progress::Info)));
|
this, SLOT(slotProgressInfo(QString,ProgressInfo)));
|
||||||
|
|
||||||
connect(_ui->_treeWidget, SIGNAL(itemActivated(QTreeWidgetItem*,int)), SLOT(slotOpenFile(QTreeWidgetItem*,int)));
|
connect(_ui->_treeWidget, SIGNAL(itemActivated(QTreeWidgetItem*,int)), SLOT(slotOpenFile(QTreeWidgetItem*,int)));
|
||||||
|
|
||||||
|
@ -224,7 +224,7 @@ QTreeWidgetItem* ProtocolWidget::createCompletedTreewidgetItem(const QString& fo
|
||||||
icon = Theme::instance()->syncStateIcon(SyncResult::Problem);
|
icon = Theme::instance()->syncStateIcon(SyncResult::Problem);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Progress::isSizeDependent(item)) {
|
if (ProgressInfo::isSizeDependent(item)) {
|
||||||
columns << Utility::octetsToString( item._size );
|
columns << Utility::octetsToString( item._size );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,13 +266,13 @@ void ProtocolWidget::computeResyncButtonEnabled()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProtocolWidget::slotProgressInfo( const QString& folder, const Progress::Info& progress )
|
void ProtocolWidget::slotProgressInfo( const QString& folder, const ProgressInfo& progress )
|
||||||
{
|
{
|
||||||
if( progress._completedFileCount == ULLONG_MAX ) {
|
if( !progress.hasStarted() ) {
|
||||||
// The sync is restarting, clean the old items
|
// The sync is restarting, clean the old items
|
||||||
cleanIgnoreItems(folder);
|
cleanIgnoreItems(folder);
|
||||||
computeResyncButtonEnabled();
|
computeResyncButtonEnabled();
|
||||||
} else if (progress._completedFileCount >= progress._totalFileCount) {
|
} else if (progress.completedFiles() >= progress.totalFiles()) {
|
||||||
//Sync completed
|
//Sync completed
|
||||||
computeResyncButtonEnabled();
|
computeResyncButtonEnabled();
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ public:
|
||||||
~ProtocolWidget();
|
~ProtocolWidget();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void slotProgressInfo( const QString& folder, const Progress::Info& progress );
|
void slotProgressInfo( const QString& folder, const ProgressInfo& progress );
|
||||||
void slotOpenFile( QTreeWidgetItem* item, int );
|
void slotOpenFile( QTreeWidgetItem* item, int );
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
|
|
|
@ -112,8 +112,8 @@ SettingsDialog::SettingsDialog(ownCloudGui *gui, QWidget *parent) :
|
||||||
connect( _accountSettings, SIGNAL(openFolderAlias(const QString&)),
|
connect( _accountSettings, SIGNAL(openFolderAlias(const QString&)),
|
||||||
gui, SLOT(slotFolderOpenAction(QString)));
|
gui, SLOT(slotFolderOpenAction(QString)));
|
||||||
|
|
||||||
connect( ProgressDispatcher::instance(), SIGNAL(progressInfo(QString, Progress::Info)),
|
connect( ProgressDispatcher::instance(), SIGNAL(progressInfo(QString, ProgressInfo)),
|
||||||
_accountSettings, SLOT(slotSetProgress(QString, Progress::Info)) );
|
_accountSettings, SLOT(slotSetProgress(QString, ProgressInfo)) );
|
||||||
|
|
||||||
|
|
||||||
// default to Account
|
// default to Account
|
||||||
|
|
|
@ -113,7 +113,7 @@ ProgressDispatcher::~ProgressDispatcher()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProgressDispatcher::setProgressInfo(const QString& folder, const Progress::Info& progress)
|
void ProgressDispatcher::setProgressInfo(const QString& folder, const ProgressInfo& progress)
|
||||||
{
|
{
|
||||||
if( folder.isEmpty())
|
if( folder.isEmpty())
|
||||||
// The update phase now also has progress
|
// The update phase now also has progress
|
||||||
|
@ -125,5 +125,194 @@ void ProgressDispatcher::setProgressInfo(const QString& folder, const Progress::
|
||||||
emit progressInfo( folder, progress );
|
emit progressInfo( folder, progress );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ProgressInfo::start()
|
||||||
|
{
|
||||||
|
connect(&_updateEstimatesTimer, SIGNAL(timeout()), SLOT(updateEstimates()));
|
||||||
|
_updateEstimatesTimer.start(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProgressInfo::hasStarted() const
|
||||||
|
{
|
||||||
|
return _updateEstimatesTimer.isActive();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProgressInfo::adjustTotalsForFile(const SyncFileItem &item)
|
||||||
|
{
|
||||||
|
if (!item._isDirectory) {
|
||||||
|
_fileProgress._total++;
|
||||||
|
if (isSizeDependent(item)) {
|
||||||
|
_sizeProgress._total += item._size;
|
||||||
|
}
|
||||||
|
} else if (item._instruction != CSYNC_INSTRUCTION_NONE) {
|
||||||
|
// Added or removed directories certainly count.
|
||||||
|
_fileProgress._total++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProgressInfo::adjustTotalSize(qint64 change)
|
||||||
|
{
|
||||||
|
_sizeProgress._total += change;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint64 ProgressInfo::totalFiles() const
|
||||||
|
{
|
||||||
|
return _fileProgress._total;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint64 ProgressInfo::completedFiles() const
|
||||||
|
{
|
||||||
|
return _fileProgress._completed;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint64 ProgressInfo::currentFile() const
|
||||||
|
{
|
||||||
|
return completedFiles() + _currentItems.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
quint64 ProgressInfo::totalSize() const
|
||||||
|
{
|
||||||
|
return _sizeProgress._total;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint64 ProgressInfo::completedSize() const
|
||||||
|
{
|
||||||
|
return _sizeProgress._completed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProgressInfo::setProgressComplete(const SyncFileItem &item)
|
||||||
|
{
|
||||||
|
_currentItems.remove(item._file);
|
||||||
|
_fileProgress._completed += item._affectedItems;
|
||||||
|
if (ProgressInfo::isSizeDependent(item)) {
|
||||||
|
_totalSizeOfCompletedJobs += item._size;
|
||||||
|
}
|
||||||
|
recomputeCompletedSize();
|
||||||
|
_lastCompletedItem = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProgressInfo::setProgressItem(const SyncFileItem &item, quint64 size)
|
||||||
|
{
|
||||||
|
_currentItems[item._file]._item = item;
|
||||||
|
_currentItems[item._file]._progress._completed = size;
|
||||||
|
_currentItems[item._file]._progress._total = item._size;
|
||||||
|
recomputeCompletedSize();
|
||||||
|
|
||||||
|
// This seems dubious!
|
||||||
|
_lastCompletedItem = SyncFileItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgressInfo::Estimates ProgressInfo::totalProgress() const
|
||||||
|
{
|
||||||
|
Estimates file = _fileProgress.estimates();
|
||||||
|
if (_sizeProgress._total == 0) {
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
Estimates size = _sizeProgress.estimates();
|
||||||
|
|
||||||
|
// Ideally the remaining time would be modeled as:
|
||||||
|
// remaning_file_sizes / transfer_speed
|
||||||
|
// + remaining_file_count * per_file_overhead
|
||||||
|
// + remaining_chunked_file_sizes / chunked_reassembly_speed
|
||||||
|
// with us estimating the three parameters in conjunction.
|
||||||
|
//
|
||||||
|
// But we currently only model the bandwidth and the files per
|
||||||
|
// second independently, which leads to incorrect values. To slightly
|
||||||
|
// mitigate this problem, we combine the two models depending on
|
||||||
|
// which factor dominates (essentially big-file-upload vs.
|
||||||
|
// many-small-files)
|
||||||
|
//
|
||||||
|
// If we have size information, we prefer an estimate based
|
||||||
|
// on the upload speed. That's particularly relevant for large file
|
||||||
|
// up/downloads, where files per second will be close to 0.
|
||||||
|
//
|
||||||
|
// However, when many *small* files are transfered, the estimate
|
||||||
|
// can become very pessimistic as the transfered amount per second
|
||||||
|
// drops significantly.
|
||||||
|
//
|
||||||
|
// So, if we detect a high rate of files per second, we gradually prefer
|
||||||
|
// a file-per-second estimate and assume the remaining transfer will
|
||||||
|
// be done with the highest speed we've seen.
|
||||||
|
quint64 combinedEta = file.estimatedEta + _sizeProgress.remaining() / _maxBytesPerSecond * 1000;
|
||||||
|
if (combinedEta < size.estimatedEta) {
|
||||||
|
double filesPerSec = _fileProgress._progressPerSec;
|
||||||
|
// value between 0 (fps==5) and 1 (fps==20)
|
||||||
|
double scale = qBound(0.0, (filesPerSec - 5.0) / 15.0, 1.0);
|
||||||
|
size.estimatedEta = (1.0 - scale) * size.estimatedEta + scale * combinedEta;
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgressInfo::Estimates ProgressInfo::fileProgress(const SyncFileItem &item) const
|
||||||
|
{
|
||||||
|
return _currentItems[item._file]._progress.estimates();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProgressInfo::updateEstimates()
|
||||||
|
{
|
||||||
|
_sizeProgress.update();
|
||||||
|
_fileProgress.update();
|
||||||
|
|
||||||
|
// Update progress of all running items.
|
||||||
|
QMutableHashIterator<QString, ProgressItem> it(_currentItems);
|
||||||
|
while (it.hasNext()) {
|
||||||
|
it.next();
|
||||||
|
it.value()._progress.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
_maxFilesPerSecond = qMax(_fileProgress._progressPerSec,
|
||||||
|
_maxFilesPerSecond);
|
||||||
|
_maxBytesPerSecond = qMax(_sizeProgress._progressPerSec,
|
||||||
|
_maxBytesPerSecond);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProgressInfo::recomputeCompletedSize()
|
||||||
|
{
|
||||||
|
quint64 r = _totalSizeOfCompletedJobs;
|
||||||
|
foreach(const ProgressItem &i, _currentItems) {
|
||||||
|
if (isSizeDependent(i._item))
|
||||||
|
r += i._progress._completed;
|
||||||
|
}
|
||||||
|
_sizeProgress._completed = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgressInfo::Estimates ProgressInfo::Progress::estimates() const
|
||||||
|
{
|
||||||
|
Estimates est;
|
||||||
|
est.estimatedBandwidth = _progressPerSec;
|
||||||
|
if (_progressPerSec != 0) {
|
||||||
|
est.estimatedEta = (_total - _completed) / _progressPerSec * 1000.0;
|
||||||
|
} else {
|
||||||
|
est.estimatedEta = 0; // looks better than quint64 max
|
||||||
|
}
|
||||||
|
return est;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint64 ProgressInfo::Progress::completed() const
|
||||||
|
{
|
||||||
|
return _completed;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint64 ProgressInfo::Progress::remaining() const
|
||||||
|
{
|
||||||
|
return _total - _completed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProgressInfo::Progress::update()
|
||||||
|
{
|
||||||
|
// A good way to think about the smoothing factor:
|
||||||
|
// If we make progress P per sec and then stop making progress at all,
|
||||||
|
// after N calls to this function (and thus seconds) the _progressPerSec
|
||||||
|
// will have reduced to P*smoothing^N.
|
||||||
|
// With a value of 0.9, only 4% of the original value is left after 30s
|
||||||
|
//
|
||||||
|
// In the first few updates we want to go to the correct value quickly.
|
||||||
|
// Therefore, smoothing starts at 0 and ramps up to its final value over time.
|
||||||
|
const double smoothing = 0.9 * (1.0 - _initialSmoothing);
|
||||||
|
_initialSmoothing *= 0.7; // goes from 1 to 0.03 in 10s
|
||||||
|
_progressPerSec = smoothing * _progressPerSec + (1.0 - smoothing) * (_completed - _prevCompleted);
|
||||||
|
_prevCompleted = _completed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,17 +20,60 @@
|
||||||
#include <QTime>
|
#include <QTime>
|
||||||
#include <QQueue>
|
#include <QQueue>
|
||||||
#include <QElapsedTimer>
|
#include <QElapsedTimer>
|
||||||
|
#include <QTimer>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
#include "syncfileitem.h"
|
#include "syncfileitem.h"
|
||||||
|
|
||||||
namespace OCC {
|
namespace OCC {
|
||||||
|
|
||||||
/**
|
class ProgressInfo : public QObject
|
||||||
* @brief The FolderScheduler class schedules folders for sync
|
|
||||||
*/
|
|
||||||
namespace Progress
|
|
||||||
{
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
ProgressInfo()
|
||||||
|
: _totalSizeOfCompletedJobs(0)
|
||||||
|
, _maxFilesPerSecond(2.0)
|
||||||
|
, _maxBytesPerSecond(100000.0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when propagation starts.
|
||||||
|
*
|
||||||
|
* hasStarted() will return true afterwards.
|
||||||
|
*/
|
||||||
|
void start();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true when propagation has started (start() was called).
|
||||||
|
*
|
||||||
|
* This is used when the SyncEngine wants to indicate a new sync
|
||||||
|
* is about to start via the transmissionProgress() signal. The
|
||||||
|
* first ProgressInfo will have hasStarted() == false.
|
||||||
|
*/
|
||||||
|
bool hasStarted() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increase the file and size totals by the amount indicated in item.
|
||||||
|
*/
|
||||||
|
void adjustTotalsForFile(const SyncFileItem & item);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adjust the total size by some value.
|
||||||
|
*
|
||||||
|
* Deprecated. Used only in the legacy propagator.
|
||||||
|
*/
|
||||||
|
void adjustTotalSize(qint64 change);
|
||||||
|
|
||||||
|
quint64 totalFiles() const;
|
||||||
|
quint64 completedFiles() const;
|
||||||
|
|
||||||
|
quint64 totalSize() const;
|
||||||
|
quint64 completedSize() const;
|
||||||
|
|
||||||
|
/** Number of a file that is currently in progress. */
|
||||||
|
quint64 currentFile() const;
|
||||||
|
|
||||||
/** Return true is the size need to be taken in account in the total amount of time */
|
/** Return true is the size need to be taken in account in the total amount of time */
|
||||||
static inline bool isSizeDependent(const SyncFileItem & item)
|
static inline bool isSizeDependent(const SyncFileItem & item)
|
||||||
{
|
{
|
||||||
|
@ -40,137 +83,111 @@ namespace Progress
|
||||||
|| item._instruction == CSYNC_INSTRUCTION_NEW);
|
|| item._instruction == CSYNC_INSTRUCTION_NEW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds estimates about progress, returned to the user.
|
||||||
|
*/
|
||||||
|
struct Estimates
|
||||||
|
{
|
||||||
|
/// Estimated completion amount per second. (of bytes or files)
|
||||||
|
quint64 estimatedBandwidth;
|
||||||
|
|
||||||
struct Info {
|
/// Estimated eta in milliseconds.
|
||||||
Info() : _totalFileCount(0), _totalSize(0), _completedFileCount(0), _completedSize(0) {}
|
quint64 estimatedEta;
|
||||||
|
|
||||||
// Used during local and remote update phase
|
|
||||||
QString _currentDiscoveredFolder;
|
|
||||||
|
|
||||||
quint64 _totalFileCount;
|
|
||||||
quint64 _totalSize;
|
|
||||||
quint64 _completedFileCount;
|
|
||||||
quint64 _completedSize;
|
|
||||||
// Should this be in a separate file?
|
|
||||||
struct EtaEstimate {
|
|
||||||
EtaEstimate()
|
|
||||||
: _startedTime(QDateTime::currentMSecsSinceEpoch())
|
|
||||||
, _agvEtaMSecs(0)
|
|
||||||
, _effectivProgressPerSec(0)
|
|
||||||
, _sampleCount(1)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static const int MAX_AVG_DIVIDER=60;
|
|
||||||
static const int INITAL_WAIT_TIME=5;
|
|
||||||
|
|
||||||
quint64 _startedTime ;
|
|
||||||
quint64 _agvEtaMSecs;
|
|
||||||
quint64 _effectivProgressPerSec;
|
|
||||||
float _sampleCount;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* reset the estiamte.
|
|
||||||
*/
|
|
||||||
void reset() {
|
|
||||||
_startedTime = QDateTime::currentMSecsSinceEpoch();
|
|
||||||
_sampleCount =1;
|
|
||||||
_effectivProgressPerSec = _agvEtaMSecs = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* update the estimated eta time with more current data.
|
|
||||||
* @param quint64 completed the amount the was completed.
|
|
||||||
* @param quint64 total the total amout that should be completed.
|
|
||||||
*/
|
|
||||||
void updateTime(quint64 completed, quint64 total) {
|
|
||||||
quint64 elapsedTime = QDateTime::currentMSecsSinceEpoch() - this->_startedTime ;
|
|
||||||
//don't start until you have some good data to process, prevents jittring estiamtes at the start of the syncing process
|
|
||||||
if(total != 0 && completed != 0 && elapsedTime > INITAL_WAIT_TIME ) {
|
|
||||||
if(_sampleCount < MAX_AVG_DIVIDER) { _sampleCount+=0.01f; }
|
|
||||||
// (elapsedTime-1) is an hack to avoid float "rounding" issue (ie. 0.99999999999999999999....)
|
|
||||||
_agvEtaMSecs = _agvEtaMSecs + (((static_cast<float>(total) / completed) * elapsedTime) - (elapsedTime-1)) - this->getEtaEstimate();
|
|
||||||
_effectivProgressPerSec = ( total - completed ) / (1+this->getEtaEstimate()/1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the eta estimate in milliseconds
|
|
||||||
* @return quint64 the estimate amount of milliseconds to end the process.
|
|
||||||
*/
|
|
||||||
quint64 getEtaEstimate() const {
|
|
||||||
return _agvEtaMSecs / _sampleCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the estimated average bandwidth usage.
|
|
||||||
* @return quint64 the estimated bandwidth usage in bytes.
|
|
||||||
*/
|
|
||||||
quint64 getEstimatedBandwidth() const {
|
|
||||||
return _effectivProgressPerSec;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
EtaEstimate _totalEtaEstimate;
|
|
||||||
|
|
||||||
struct ProgressItem {
|
|
||||||
ProgressItem() : _completedSize(0) {}
|
|
||||||
SyncFileItem _item;
|
|
||||||
quint64 _completedSize;
|
|
||||||
EtaEstimate _etaEstimate;
|
|
||||||
};
|
|
||||||
QHash<QString, ProgressItem> _currentItems;
|
|
||||||
SyncFileItem _lastCompletedItem;
|
|
||||||
|
|
||||||
void setProgressComplete(const SyncFileItem &item) {
|
|
||||||
_currentItems.remove(item._file);
|
|
||||||
_completedFileCount += item._affectedItems;
|
|
||||||
if (Progress::isSizeDependent(item)) {
|
|
||||||
_completedSize += item._size;
|
|
||||||
}
|
|
||||||
_lastCompletedItem = item;
|
|
||||||
this->updateEstimation();
|
|
||||||
}
|
|
||||||
void setProgressItem(const SyncFileItem &item, quint64 size) {
|
|
||||||
_currentItems[item._file]._item = item;
|
|
||||||
_currentItems[item._file]._completedSize = size;
|
|
||||||
_lastCompletedItem = SyncFileItem();
|
|
||||||
this->updateEstimation();
|
|
||||||
_currentItems[item._file]._etaEstimate.updateTime(size,item._size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void updateEstimation() {
|
|
||||||
if(this->_totalSize > 0) {
|
|
||||||
_totalEtaEstimate.updateTime(this->completedSize(),this->_totalSize);
|
|
||||||
} else {
|
|
||||||
_totalEtaEstimate.updateTime(this->_completedFileCount,this->_totalFileCount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
quint64 completedSize() const {
|
|
||||||
quint64 r = _completedSize;
|
|
||||||
foreach(const ProgressItem &i, _currentItems) {
|
|
||||||
if (Progress::isSizeDependent(i._item))
|
|
||||||
r += i._completedSize;
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Get the total completion estimate structure
|
|
||||||
* @return EtaEstimate a structure containing the total completion information.
|
|
||||||
*/
|
|
||||||
EtaEstimate totalEstimate() const {
|
|
||||||
return _totalEtaEstimate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the current file completion estimate structure
|
|
||||||
* @return EtaEstimate a structure containing the current file completion information.
|
|
||||||
*/
|
|
||||||
EtaEstimate getFileEstimate(const SyncFileItem &item) const {
|
|
||||||
return _currentItems[item._file]._etaEstimate;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds the current state of something making progress and maintains an
|
||||||
|
* estimate of the current progress per second.
|
||||||
|
*/
|
||||||
|
struct Progress
|
||||||
|
{
|
||||||
|
Progress()
|
||||||
|
: _progressPerSec(0)
|
||||||
|
, _completed(0)
|
||||||
|
, _prevCompleted(0)
|
||||||
|
, _total(0)
|
||||||
|
, _initialSmoothing(1.0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the estimates about progress per second and eta. */
|
||||||
|
Estimates estimates() const;
|
||||||
|
|
||||||
|
quint64 completed() const;
|
||||||
|
quint64 remaining() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Update the exponential moving average estimate of _progressPerSec.
|
||||||
|
*/
|
||||||
|
void update();
|
||||||
|
|
||||||
|
double _progressPerSec;
|
||||||
|
quint64 _completed;
|
||||||
|
quint64 _prevCompleted;
|
||||||
|
quint64 _total;
|
||||||
|
|
||||||
|
// Used to get to a good value faster when
|
||||||
|
// progress measurement stats. See update().
|
||||||
|
double _initialSmoothing;
|
||||||
|
|
||||||
|
friend class ProgressInfo;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ProgressItem
|
||||||
|
{
|
||||||
|
SyncFileItem _item;
|
||||||
|
Progress _progress;
|
||||||
|
};
|
||||||
|
QHash<QString, ProgressItem> _currentItems;
|
||||||
|
|
||||||
|
SyncFileItem _lastCompletedItem;
|
||||||
|
|
||||||
|
// Used during local and remote update phase
|
||||||
|
QString _currentDiscoveredFolder;
|
||||||
|
|
||||||
|
void setProgressComplete(const SyncFileItem &item);
|
||||||
|
|
||||||
|
void setProgressItem(const SyncFileItem &item, quint64 size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the total completion estimate
|
||||||
|
*/
|
||||||
|
Estimates totalProgress() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current file completion estimate structure
|
||||||
|
*/
|
||||||
|
Estimates fileProgress(const SyncFileItem &item) const;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
/**
|
||||||
|
* Called every second once started, this function updates the
|
||||||
|
* estimates.
|
||||||
|
*/
|
||||||
|
void updateEstimates();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Sets the completed size by summing finished jobs with the progress
|
||||||
|
// of active ones.
|
||||||
|
void recomputeCompletedSize();
|
||||||
|
|
||||||
|
// Triggers the update() slot every second once propagation started.
|
||||||
|
QTimer _updateEstimatesTimer;
|
||||||
|
|
||||||
|
Progress _sizeProgress;
|
||||||
|
Progress _fileProgress;
|
||||||
|
|
||||||
|
// All size from completed jobs only.
|
||||||
|
quint64 _totalSizeOfCompletedJobs;
|
||||||
|
|
||||||
|
// The fastest observed rate of files per second in this sync.
|
||||||
|
double _maxFilesPerSecond;
|
||||||
|
double _maxBytesPerSecond;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace Progress {
|
||||||
|
|
||||||
OWNCLOUDSYNC_EXPORT QString asActionString( const SyncFileItem& item );
|
OWNCLOUDSYNC_EXPORT QString asActionString( const SyncFileItem& item );
|
||||||
OWNCLOUDSYNC_EXPORT QString asResultString( const SyncFileItem& item );
|
OWNCLOUDSYNC_EXPORT QString asResultString( const SyncFileItem& item );
|
||||||
|
|
||||||
|
@ -205,7 +222,7 @@ signals:
|
||||||
@param[out] progress A struct with all progress info.
|
@param[out] progress A struct with all progress info.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
void progressInfo( const QString& folder, const Progress::Info& progress );
|
void progressInfo( const QString& folder, const ProgressInfo& progress );
|
||||||
/**
|
/**
|
||||||
* @brief: the item's job is completed
|
* @brief: the item's job is completed
|
||||||
*/
|
*/
|
||||||
|
@ -214,7 +231,7 @@ signals:
|
||||||
void syncItemDiscovered(const QString &folder, const SyncFileItem & item);
|
void syncItemDiscovered(const QString &folder, const SyncFileItem & item);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void setProgressInfo(const QString& folder, const Progress::Info& progress);
|
void setProgressInfo(const QString& folder, const ProgressInfo& progress);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ProgressDispatcher(QObject* parent = 0);
|
ProgressDispatcher(QObject* parent = 0);
|
||||||
|
|
|
@ -65,6 +65,7 @@ SyncEngine::SyncEngine(AccountPtr account, CSYNC *ctx, const QString& localPath,
|
||||||
, _remoteUrl(remoteURL)
|
, _remoteUrl(remoteURL)
|
||||||
, _remotePath(remotePath)
|
, _remotePath(remotePath)
|
||||||
, _journal(journal)
|
, _journal(journal)
|
||||||
|
, _progressInfo(new ProgressInfo)
|
||||||
, _hasNoneFiles(false)
|
, _hasNoneFiles(false)
|
||||||
, _hasRemoveFile(false)
|
, _hasRemoveFile(false)
|
||||||
, _uploadLimit(0)
|
, _uploadLimit(0)
|
||||||
|
@ -73,7 +74,6 @@ SyncEngine::SyncEngine(AccountPtr account, CSYNC *ctx, const QString& localPath,
|
||||||
{
|
{
|
||||||
qRegisterMetaType<SyncFileItem>("SyncFileItem");
|
qRegisterMetaType<SyncFileItem>("SyncFileItem");
|
||||||
qRegisterMetaType<SyncFileItem::Status>("SyncFileItem::Status");
|
qRegisterMetaType<SyncFileItem::Status>("SyncFileItem::Status");
|
||||||
qRegisterMetaType<Progress::Info>("Progress::Info");
|
|
||||||
|
|
||||||
_thread.setObjectName("CSync_Neon_Thread");
|
_thread.setObjectName("CSync_Neon_Thread");
|
||||||
_thread.start();
|
_thread.start();
|
||||||
|
@ -494,15 +494,8 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote )
|
||||||
checkErrorBlacklisting( *item );
|
checkErrorBlacklisting( *item );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!item->_isDirectory) {
|
_progressInfo->adjustTotalsForFile(*item);
|
||||||
_progressInfo._totalFileCount++;
|
|
||||||
if (Progress::isSizeDependent(item)) {
|
|
||||||
_progressInfo._totalSize += file->size;
|
|
||||||
}
|
|
||||||
} else if (file->instruction != CSYNC_INSTRUCTION_NONE) {
|
|
||||||
// Added or removed directories certainly count.
|
|
||||||
_progressInfo._totalFileCount++;
|
|
||||||
}
|
|
||||||
_needsUpdate = true;
|
_needsUpdate = true;
|
||||||
|
|
||||||
item->log._etag = file->etag;
|
item->log._etag = file->etag;
|
||||||
|
@ -702,8 +695,6 @@ void SyncEngine::slotDiscoveryJobFinished(int discoveryResult)
|
||||||
|
|
||||||
qDebug() << "<<#### Reconcile end #################################################### " << _stopWatch.addLapTime(QLatin1String("Reconcile Finished"));
|
qDebug() << "<<#### Reconcile end #################################################### " << _stopWatch.addLapTime(QLatin1String("Reconcile Finished"));
|
||||||
|
|
||||||
_progressInfo = Progress::Info();
|
|
||||||
|
|
||||||
_hasNoneFiles = false;
|
_hasNoneFiles = false;
|
||||||
_hasRemoveFile = false;
|
_hasRemoveFile = false;
|
||||||
bool walkOk = true;
|
bool walkOk = true;
|
||||||
|
@ -744,9 +735,9 @@ void SyncEngine::slotDiscoveryJobFinished(int discoveryResult)
|
||||||
|
|
||||||
// To announce the beginning of the sync
|
// To announce the beginning of the sync
|
||||||
emit aboutToPropagate(_syncedItems);
|
emit aboutToPropagate(_syncedItems);
|
||||||
_progressInfo._completedFileCount = ULLONG_MAX; // indicate the start with max
|
// it's important to do this before ProgressInfo::start(), to announce start of new sync
|
||||||
emit transmissionProgress(_progressInfo);
|
emit transmissionProgress(*_progressInfo);
|
||||||
_progressInfo._completedFileCount = 0;
|
_progressInfo->start();
|
||||||
|
|
||||||
if (!_hasNoneFiles && _hasRemoveFile) {
|
if (!_hasNoneFiles && _hasRemoveFile) {
|
||||||
qDebug() << Q_FUNC_INFO << "All the files are going to be changed, asking the user";
|
qDebug() << Q_FUNC_INFO << "All the files are going to be changed, asking the user";
|
||||||
|
@ -843,13 +834,13 @@ void SyncEngine::slotJobCompleted(const SyncFileItem &item)
|
||||||
const char * instruction_str = csync_instruction_str(item._instruction);
|
const char * instruction_str = csync_instruction_str(item._instruction);
|
||||||
qDebug() << Q_FUNC_INFO << item._file << instruction_str << item._status << item._errorString;
|
qDebug() << Q_FUNC_INFO << item._file << instruction_str << item._status << item._errorString;
|
||||||
|
|
||||||
_progressInfo.setProgressComplete(item);
|
_progressInfo->setProgressComplete(item);
|
||||||
|
|
||||||
if (item._status == SyncFileItem::FatalError) {
|
if (item._status == SyncFileItem::FatalError) {
|
||||||
emit csyncError(item._errorString);
|
emit csyncError(item._errorString);
|
||||||
}
|
}
|
||||||
|
|
||||||
emit transmissionProgress(_progressInfo);
|
emit transmissionProgress(*_progressInfo);
|
||||||
emit jobCompleted(item);
|
emit jobCompleted(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -891,14 +882,14 @@ void SyncEngine::finalize()
|
||||||
|
|
||||||
void SyncEngine::slotProgress(const SyncFileItem& item, quint64 current)
|
void SyncEngine::slotProgress(const SyncFileItem& item, quint64 current)
|
||||||
{
|
{
|
||||||
_progressInfo.setProgressItem(item, current);
|
_progressInfo->setProgressItem(item, current);
|
||||||
emit transmissionProgress(_progressInfo);
|
emit transmissionProgress(*_progressInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SyncEngine::slotAdjustTotalTransmissionSize(qint64 change)
|
void SyncEngine::slotAdjustTotalTransmissionSize(qint64 change)
|
||||||
{
|
{
|
||||||
_progressInfo._totalSize += change;
|
_progressInfo->adjustTotalSize(change);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Given a path on the remote, give the path as it is when the rename is done */
|
/* Given a path on the remote, give the path as it is when the rename is done */
|
||||||
|
|
|
@ -99,7 +99,7 @@ signals:
|
||||||
// after sync is done
|
// after sync is done
|
||||||
void treeWalkResult(const SyncFileItemVector&);
|
void treeWalkResult(const SyncFileItemVector&);
|
||||||
|
|
||||||
void transmissionProgress( const Progress::Info& progress );
|
void transmissionProgress( const ProgressInfo& progress );
|
||||||
|
|
||||||
void csyncStateDbFile( const QString& );
|
void csyncStateDbFile( const QString& );
|
||||||
void wipeDb();
|
void wipeDb();
|
||||||
|
@ -176,7 +176,7 @@ private:
|
||||||
|
|
||||||
QThread _thread;
|
QThread _thread;
|
||||||
|
|
||||||
Progress::Info _progressInfo;
|
QScopedPointer<ProgressInfo> _progressInfo;
|
||||||
|
|
||||||
Utility::StopWatch _stopWatch;
|
Utility::StopWatch _stopWatch;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue