Reworked progress display for more performance.

Moved most of the logic to the dialog class to be able to only update
the GUI if there are really changes rather than doing it whenever a
change happens.
This commit is contained in:
Klaas Freitag 2013-07-24 14:40:34 +02:00
parent de7bcca5fe
commit 810024f4c9
4 changed files with 122 additions and 99 deletions

View file

@ -40,7 +40,8 @@ namespace Mirall {
AccountSettings::AccountSettings(QWidget *parent) : AccountSettings::AccountSettings(QWidget *parent) :
QWidget(parent), QWidget(parent),
ui(new Ui::AccountSettings), ui(new Ui::AccountSettings),
_item(0) _item(0),
_overallProgressBase(0)
{ {
ui->setupUi(this); ui->setupUi(this);
@ -469,43 +470,89 @@ QStandardItem* AccountSettings::itemForFolder(const QString& folder)
return item; return item;
} }
void AccountSettings::slotSetOverallProgress( const QString& folder, const QString& file, int fileNo, int fileCnt, void AccountSettings::slotSetOverallProgress(const QString& folder, const QString& file, int fileNo, int fileCnt,
qlonglong p1, qlonglong p2) qint64 p1, qint64 p2)
{ {
QStandardItem *item = itemForFolder(folder); QStandardItem *item = itemForFolder(folder);
if( item ) { _overallFolder = folder;
item->setData( p1, FolderStatusDelegate::OverallProgress1); _overallFile = file;
item->setData( p2, FolderStatusDelegate::OverallProgress2); _overallFileNo = fileNo;
item->setData( fileNo, FolderStatusDelegate::OverallFileNo); _overallFileCnt = fileCnt;
item->setData( fileCnt, FolderStatusDelegate::OverallFileCount); _overallFileSize = p2;
item->setData( file, FolderStatusDelegate::OverallCurrentFile);
if( p1 == 0 ) {
// begin of a sequence of up- and downloads.
_overallProgressBase = 0;
_lastProgress = 0;
}
if( item ) {
QString s1 = Utility::octetsToString( p1 );
QString s2 = Utility::octetsToString( p2 );
QString overallSyncString = tr("%1 of %2, file %3 of %4").arg(s1).arg(s2).arg(fileNo).arg(fileCnt);
item->setData( overallSyncString, FolderStatusDelegate::SyncProgressOverallString );
int overallPercent = 0;
if( p2 > 0 ) overallPercent = qRound(double(p1)/double(p2) * 100.0);
item->setData( overallPercent, FolderStatusDelegate::SyncProgressOverallPercent);
} }
_lastOverallProgress = p1;
} }
void AccountSettings::slotSetProgress( Progress::Kind kind, const QString& folder, const QString& file, long p1, long p2 ) QString AccountSettings::shortenFilename( const QString& folder, const QString& file ) const
{
// strip off the server prefix from the file name
QString shortFile(file);
if( shortFile.isEmpty() ) {
return QString::null;
}
if(shortFile.startsWith(QLatin1String("ownclouds://")) ||
shortFile.startsWith(QLatin1String("owncloud://")) ) {
// rip off the whole ownCloud URL.
Folder *f = FolderMan::instance()->folder(folder);
if( f ) {
QString regexp = QString("^owncloud[s]*://.*/remote.php/webdav/%1/").arg(f->secondPath());
QRegExp re( regexp );
re.setMinimal(true);
shortFile.remove(re);
}
}
return shortFile;
}
void AccountSettings::slotSetProgress( Progress::Kind kind, const QString& folder, const QString& file, qint64 p1, qint64 p2 )
{ {
// qDebug() << "================================> Progress for folder " << folder << " file " << file << ": "<< p1; // qDebug() << "================================> Progress for folder " << folder << " file " << file << ": "<< p1;
QStandardItem *item = itemForFolder( folder ); QStandardItem *item = itemForFolder( folder );
qint64 prog1 = p1;
qint64 prog2 = p2;
if( item == NULL ) { if( item == NULL ) {
return; return;
} }
QString itemFileName = shortenFilename(folder, file);
QString syncFileProgressString;
// Set the verb if up- or download // Set the verb if up- or download
if( kind != Progress::Context ) { if( kind != Progress::Context ) {
_kindContext = Progress::asString(kind); _kindContext = Progress::asString(kind);
} }
QString kindString = _kindContext; QString kindString = _kindContext;
item->setData( kindString, FolderStatusDelegate::SyncFileKind );
if( kind == Progress::EndDownload || if( kind == Progress::StartDownload || kind == Progress::StartUpload ) { // File upload starts.
kind == Progress::EndUpload ) { // File upload/download finished. if( _hideProgressTimers.contains(item) ) {
item->setData( 100, FolderStatusDelegate::SyncProgressPercent1); // The timer is still running.
item->setData( 100, FolderStatusDelegate::SyncProgressPercent2); QTimer *t = _hideProgressTimers.take(item);
item->setData( (qlonglong) _lastSyncProgress, FolderStatusDelegate::SyncProgressBytes1); t->stop();
item->setData( (qlonglong) _lastSyncProgress, FolderStatusDelegate::SyncProgressBytes2); t->deleteLater();
item->setData( tr("Finished"), FolderStatusDelegate::SyncFileProgressString); }
item->setData( QVariant(true), FolderStatusDelegate::AddProgressSpace );
syncFileProgressString = tr("Start");
} else if( kind == Progress::EndDownload || kind == Progress::EndUpload ) {
syncFileProgressString = tr("Finished");
// start a timer to stop the progress display // start a timer to stop the progress display
QTimer *timer; QTimer *timer;
@ -519,63 +566,56 @@ void AccountSettings::slotSetProgress( Progress::Kind kind, const QString& folde
_hideProgressTimers.insert(item, timer); _hideProgressTimers.insert(item, timer);
} }
timer->start(5000); timer->start(5000);
} else if( kind == Progress::StartDownload ||
kind == Progress::StartUpload ) { // File upload starts.
if( _hideProgressTimers.contains(item) ) { prog1 = prog2 = _lastProgress;
// The timer is still running. } else if( kind == Progress::Context ) { // File progress
QTimer *t = _hideProgressTimers.take(item);
t->stop();
t->deleteLater();
}
item->setData( QVariant(true), FolderStatusDelegate::AddProgressSpace ); item->setData( QVariant(true), FolderStatusDelegate::AddProgressSpace );
item->setData( 0, FolderStatusDelegate::SyncProgressPercent1); _lastProgress = prog1;
item->setData( 100, FolderStatusDelegate::SyncProgressPercent2); syncFileProgressString = tr("Currently");
item->setData( (qlonglong) 0, FolderStatusDelegate::SyncProgressBytes1);
item->setData( (qlonglong) p2, FolderStatusDelegate::SyncProgressBytes2);
// strip off the server prefix from the file name
QString shortFile(file);
if(shortFile.startsWith(QLatin1String("ownclouds://")) ||
shortFile.startsWith(QLatin1String("owncloud://")) ) {
// rip off the whole ownCloud URL.
Folder *f = FolderMan::instance()->folder(folder);
if( f ) {
QString regexp = QString("^owncloud[s]*://.*/remote.php/webdav/%1/").arg(f->secondPath());
QRegExp re( regexp );
re.setMinimal(true);
shortFile.remove(re);
} }
} QString fileProgressString;
item->setData( shortFile, FolderStatusDelegate::SyncFileName ); QString s1 = Utility::octetsToString( prog1 );
item->setData( tr("Start"), FolderStatusDelegate::SyncFileProgressString); QString s2 = Utility::octetsToString( prog2 );
} else { // File progress
item->setData( (qlonglong) p1, FolderStatusDelegate::SyncProgressBytes1);
item->setData( (qlonglong) p2, FolderStatusDelegate::SyncProgressBytes2);
item->setData( (qlonglong) _lastOverallProgress+p1, FolderStatusDelegate::OverallProgress1 );
item->setData( tr("Currently"), FolderStatusDelegate::SyncFileProgressString);
_lastSyncProgress = p1; // Example text: "Currently uploading foobar.png (1MB of 2MB)"
} fileProgressString = tr("%1 %2 %3 (%4 of %5)").arg(syncFileProgressString).arg(kindString).
arg(itemFileName).arg(s1).arg(s2);
// only publish to item if there really is a change
if( fileProgressString != _previousFileProgressString ) {
item->setData( fileProgressString,FolderStatusDelegate::SyncProgressItemString);
slotSetOverallProgress(folder, itemFileName, _overallFileNo, _overallFileCnt,
_overallProgressBase + prog1, _overallFileSize);
ui->_folderList->repaint(); ui->_folderList->repaint();
}
_previousFileProgressString = fileProgressString;
// move the overall progress on. Don't do before it was set in the item.
if( kind == Progress::EndDownload || kind == Progress::EndUpload ) {
_overallProgressBase += _lastProgress;
}
} }
void AccountSettings::slotHideProgress() void AccountSettings::slotHideProgress()
{ {
QTimer *t_send = qobject_cast<QTimer*>(this->sender()); QTimer *send_timer = qobject_cast<QTimer*>(this->sender());
QHash<QStandardItem*, QTimer*>::const_iterator i = _hideProgressTimers.constBegin(); QHash<QStandardItem*, QTimer*>::const_iterator i = _hideProgressTimers.constBegin();
while (i != _hideProgressTimers.constEnd()) { while (i != _hideProgressTimers.constEnd()) {
if( i.value() == t_send ) { if( i.value() == send_timer ) {
QStandardItem *item = i.key(); QStandardItem *item = i.key();
item->setData( QVariant(false), FolderStatusDelegate::AddProgressSpace ); item->setData( QVariant(false), FolderStatusDelegate::AddProgressSpace );
item->setData( QVariant(QString::null), FolderStatusDelegate::SyncFileName ); item->setData( QVariant(QString::null), FolderStatusDelegate::SyncProgressOverallString );
item->setData( QVariant(QString::null), FolderStatusDelegate::SyncProgressItemString );
item->setData( 0, FolderStatusDelegate::SyncProgressOverallPercent );
ui->_folderList->repaint(); ui->_folderList->repaint();
_hideProgressTimers.remove(item); _hideProgressTimers.remove(item);
break; break;
} }
++i; ++i;
} }
t_send->deleteLater(); send_timer->deleteLater();
} }
void AccountSettings::slotUpdateQuota(qint64 total, qint64 used) void AccountSettings::slotUpdateQuota(qint64 total, qint64 used)

View file

@ -84,6 +84,7 @@ protected slots:
void slotHideProgress(); void slotHideProgress();
private: private:
QString shortenFilename( const QString& folder, const QString& file ) const;
void folderToModelItem( QStandardItem *, Folder * ); void folderToModelItem( QStandardItem *, Folder * );
QStandardItem* itemForFolder(const QString& ); QStandardItem* itemForFolder(const QString& );
@ -96,9 +97,16 @@ private:
double _progressFactor; double _progressFactor;
QHash<QStandardItem*, QTimer*> _hideProgressTimers; QHash<QStandardItem*, QTimer*> _hideProgressTimers;
QTimer *_timer; QTimer *_timer;
long _lastSyncProgress;
QString _previousFileProgressString;
QString _kindContext; QString _kindContext;
qlonglong _lastOverallProgress; QString _overallFolder;
QString _overallFile;
int _overallFileNo;
int _overallFileCnt;
qint64 _overallFileSize;
qint64 _overallProgressBase;
qint64 _lastProgress;
}; };
} // namespace Mirall } // namespace Mirall

View file

@ -123,16 +123,10 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
QString pathText = qvariant_cast<QString>(index.data(FolderPathRole)); QString pathText = qvariant_cast<QString>(index.data(FolderPathRole));
QString remotePath = qvariant_cast<QString>(index.data(FolderSecondPathRole)); QString remotePath = qvariant_cast<QString>(index.data(FolderSecondPathRole));
QString errorText = qvariant_cast<QString>(index.data(FolderErrorMsg)); QString errorText = qvariant_cast<QString>(index.data(FolderErrorMsg));
QString syncFile = qvariant_cast<QString>(index.data(SyncFileName));
QString syncFileKind = qvariant_cast<QString>(index.data(SyncFileKind));
QString syncFileProgress = qvariant_cast<QString>(index.data(SyncFileProgressString));
qlonglong fileBytes1 = qvariant_cast<qlonglong>(index.data(SyncProgressBytes1));
qlonglong fileBytes2 = qvariant_cast<qlonglong>(index.data(SyncProgressBytes2));
qlonglong overallBytes1 = qvariant_cast<qlonglong>(index.data(OverallProgress1)); int overallPercent = qvariant_cast<int>(index.data(SyncProgressOverallPercent));
qlonglong overallBytes2 = qvariant_cast<qlonglong>(index.data(OverallProgress2)); QString overallString = qvariant_cast<QString>(index.data(SyncProgressOverallString));
int currentFileCount = qvariant_cast<int>(index.data(OverallFileNo)); QString itemString = qvariant_cast<QString>(index.data(SyncProgressItemString));
int overallFileCount = qvariant_cast<int>(index.data(OverallFileCount));
// QString statusText = qvariant_cast<QString>(index.data(FolderStatus)); // QString statusText = qvariant_cast<QString>(index.data(FolderStatus));
bool syncEnabled = index.data(FolderSyncEnabled).toBool(); bool syncEnabled = index.data(FolderSyncEnabled).toBool();
@ -235,7 +229,7 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
h += aliasMargin; h += aliasMargin;
// Sync File Progress Bar: Show it if syncFile is not empty. // Sync File Progress Bar: Show it if syncFile is not empty.
if( !syncFile.isEmpty()) { if( !overallString.isEmpty()) {
int fileNameTextHeight = subFm.boundingRect(tr("File")).height(); int fileNameTextHeight = subFm.boundingRect(tr("File")).height();
int barHeight = fileNameTextHeight; int barHeight = fileNameTextHeight;
int overallWidth = option.rect.width()-2*aliasMargin; int overallWidth = option.rect.width()-2*aliasMargin;
@ -243,11 +237,7 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
painter->save(); painter->save();
// Sizes-Text // Sizes-Text
QString s1 = Utility::octetsToString( overallBytes1 ); QRect octetRect = subFm.boundingRect( overallString );
QString s2 = Utility::octetsToString( overallBytes2 );
QString overallSyncString = tr("%1 of %2, file %3 of %4").arg(s1).arg(s2).arg(currentFileCount).arg(overallFileCount);
QRect octetRect = subFm.boundingRect( overallSyncString );
int progressTextWidth = octetRect.width(); int progressTextWidth = octetRect.width();
// Overall Progress Bar. // Overall Progress Bar.
@ -257,7 +247,6 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
pBRect.setHeight(barHeight); pBRect.setHeight(barHeight);
pBRect.setWidth( overallWidth - progressTextWidth - margin ); pBRect.setWidth( overallWidth - progressTextWidth - margin );
int overallPercent = (overallBytes1) *100.0/overallBytes2;
QStyleOptionProgressBarV2 pBarOpt; QStyleOptionProgressBarV2 pBarOpt;
pBarOpt.state = option.state | QStyle::State_Horizontal; pBarOpt.state = option.state | QStyle::State_Horizontal;
pBarOpt.minimum = 0; pBarOpt.minimum = 0;
@ -276,25 +265,20 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
overallProgressRect.setLeft( pBRect.right()+margin); overallProgressRect.setLeft( pBRect.right()+margin);
overallProgressRect.setWidth( progressTextWidth ); overallProgressRect.setWidth( progressTextWidth );
painter->setFont(progressFont); painter->setFont(progressFont);
painter->drawText( overallProgressRect, Qt::AlignRight+Qt::AlignVCenter, overallSyncString); painter->drawText( overallProgressRect, Qt::AlignRight+Qt::AlignVCenter, overallString);
// Individual File Progress // Individual File Progress
s1 = Utility::octetsToString( fileBytes1);
s2 = Utility::octetsToString( fileBytes2);
QRect fileRect; QRect fileRect;
fileRect.setTop( pBRect.bottom() + margin); fileRect.setTop( pBRect.bottom() + margin);
fileRect.setLeft( iconRect.left()); fileRect.setLeft( iconRect.left());
fileRect.setWidth(overallWidth); fileRect.setWidth(overallWidth);
fileRect.setHeight(fileNameTextHeight); fileRect.setHeight(fileNameTextHeight);
QString fileProgressString = tr("%1 %2 %3 (%4 of %5)").arg(syncFileProgress).arg(syncFileKind).arg(syncFile).arg(s1).arg(s2); painter->drawText( fileRect, Qt::AlignLeft+Qt::AlignVCenter, itemString);
QString elidedProgress = progressFm.elidedText(fileProgressString, Qt::ElideLeft, fileRect.width());
painter->drawText( fileRect, Qt::AlignLeft+Qt::AlignVCenter, elidedProgress);
painter->restore(); painter->restore();
} }
painter->restore();
} }
bool FolderStatusDelegate::editorEvent ( QEvent * event, QAbstractItemModel * model, const QStyleOptionViewItem & option, const QModelIndex & index ) bool FolderStatusDelegate::editorEvent ( QEvent * event, QAbstractItemModel * model, const QStyleOptionViewItem & option, const QModelIndex & index )

View file

@ -44,20 +44,11 @@ class FolderStatusDelegate : public QStyledItemDelegate
FolderErrorMsg, FolderErrorMsg,
FolderSyncEnabled, FolderSyncEnabled,
FolderStatusIconRole, FolderStatusIconRole,
SyncFileName,
SyncFileKind, SyncProgressOverallPercent,
SyncFileProgressString, // stuff like Currently ... or Finished... SyncProgressOverallString,
SyncProgressPercent1, SyncProgressItemString,
SyncProgressPercent2, AddProgressSpace
SyncProgressBytes1,
SyncProgressBytes2,
AddProgressSpace,
OverallProgress1,
OverallProgress2,
OverallPercent,
OverallFileNo,
OverallFileCount,
OverallCurrentFile
}; };
void paint( QPainter*, const QStyleOptionViewItem&, const QModelIndex& ) const; void paint( QPainter*, const QStyleOptionViewItem&, const QModelIndex& ) const;
QSize sizeHint( const QStyleOptionViewItem&, const QModelIndex& ) const; QSize sizeHint( const QStyleOptionViewItem&, const QModelIndex& ) const;