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) :
QWidget(parent),
ui(new Ui::AccountSettings),
_item(0)
_item(0),
_overallProgressBase(0)
{
ui->setupUi(this);
@ -470,42 +471,88 @@ QStandardItem* AccountSettings::itemForFolder(const QString& folder)
}
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);
if( item ) {
item->setData( p1, FolderStatusDelegate::OverallProgress1);
item->setData( p2, FolderStatusDelegate::OverallProgress2);
item->setData( fileNo, FolderStatusDelegate::OverallFileNo);
item->setData( fileCnt, FolderStatusDelegate::OverallFileCount);
item->setData( file, FolderStatusDelegate::OverallCurrentFile);
}
_lastOverallProgress = p1;
_overallFolder = folder;
_overallFile = file;
_overallFileNo = fileNo;
_overallFileCnt = fileCnt;
_overallFileSize = p2;
if( p1 == 0 ) {
// begin of a sequence of up- and downloads.
_overallProgressBase = 0;
_lastProgress = 0;
}
void AccountSettings::slotSetProgress( Progress::Kind kind, const QString& folder, const QString& file, long p1, long p2 )
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);
}
}
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;
QStandardItem *item = itemForFolder( folder );
qint64 prog1 = p1;
qint64 prog2 = p2;
if( item == NULL ) {
return;
}
QString itemFileName = shortenFilename(folder, file);
QString syncFileProgressString;
// Set the verb if up- or download
if( kind != Progress::Context ) {
_kindContext = Progress::asString(kind);
}
QString kindString = _kindContext;
item->setData( kindString, FolderStatusDelegate::SyncFileKind );
if( kind == Progress::EndDownload ||
kind == Progress::EndUpload ) { // File upload/download finished.
item->setData( 100, FolderStatusDelegate::SyncProgressPercent1);
item->setData( 100, FolderStatusDelegate::SyncProgressPercent2);
item->setData( (qlonglong) _lastSyncProgress, FolderStatusDelegate::SyncProgressBytes1);
item->setData( (qlonglong) _lastSyncProgress, FolderStatusDelegate::SyncProgressBytes2);
item->setData( tr("Finished"), FolderStatusDelegate::SyncFileProgressString);
if( kind == Progress::StartDownload || kind == Progress::StartUpload ) { // File upload starts.
if( _hideProgressTimers.contains(item) ) {
// The timer is still running.
QTimer *t = _hideProgressTimers.take(item);
t->stop();
t->deleteLater();
}
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
QTimer *timer;
@ -519,63 +566,56 @@ void AccountSettings::slotSetProgress( Progress::Kind kind, const QString& folde
_hideProgressTimers.insert(item, timer);
}
timer->start(5000);
} else if( kind == Progress::StartDownload ||
kind == Progress::StartUpload ) { // File upload starts.
if( _hideProgressTimers.contains(item) ) {
// The timer is still running.
QTimer *t = _hideProgressTimers.take(item);
t->stop();
t->deleteLater();
}
prog1 = prog2 = _lastProgress;
} else if( kind == Progress::Context ) { // File progress
item->setData( QVariant(true), FolderStatusDelegate::AddProgressSpace );
item->setData( 0, FolderStatusDelegate::SyncProgressPercent1);
item->setData( 100, FolderStatusDelegate::SyncProgressPercent2);
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);
_lastProgress = prog1;
syncFileProgressString = tr("Currently");
}
}
item->setData( shortFile, FolderStatusDelegate::SyncFileName );
item->setData( tr("Start"), FolderStatusDelegate::SyncFileProgressString);
} 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);
QString fileProgressString;
QString s1 = Utility::octetsToString( prog1 );
QString s2 = Utility::octetsToString( prog2 );
_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();
}
_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()
{
QTimer *t_send = qobject_cast<QTimer*>(this->sender());
QTimer *send_timer = qobject_cast<QTimer*>(this->sender());
QHash<QStandardItem*, QTimer*>::const_iterator i = _hideProgressTimers.constBegin();
while (i != _hideProgressTimers.constEnd()) {
if( i.value() == t_send ) {
if( i.value() == send_timer ) {
QStandardItem *item = i.key();
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();
_hideProgressTimers.remove(item);
break;
}
++i;
}
t_send->deleteLater();
send_timer->deleteLater();
}
void AccountSettings::slotUpdateQuota(qint64 total, qint64 used)

View file

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

View file

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

View file

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