Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve the syncing status text displayed to the user #6882

Merged
merged 5 commits into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions src/gui/folderstatusdelegate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,15 +320,18 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOpt, painter, option.widget);
#endif

// Overall Progress Text
QRect overallProgressRect;
overallProgressRect.setTop(progressBarRect.bottom() + margin);
overallProgressRect.setHeight(fileNameTextHeight);
overallProgressRect.setLeft(progressBarRect.left());
overallProgressRect.setWidth(progressBarRect.width());
// itemString is e.g. Syncing fileName1, filename2
// syncText is Synchronizing files in local folders or Synchronizing virtual files in local folder
const auto generalSyncStatus = !itemString.isEmpty() ? itemString : syncText;
QRect generalSyncStatusRect;
generalSyncStatusRect.setTop(progressBarRect.bottom() + margin);
generalSyncStatusRect.setHeight(fileNameTextHeight);
generalSyncStatusRect.setLeft(progressBarRect.left());
generalSyncStatusRect.setWidth(progressBarRect.width());
painter->setFont(progressFont);

painter->drawText(QStyle::visualRect(option.direction, option.rect, overallProgressRect), Qt::AlignLeft | Qt::AlignVCenter, overallString);
painter->drawText(QStyle::visualRect(option.direction, option.rect, generalSyncStatusRect), Qt::AlignLeft | Qt::AlignVCenter, generalSyncStatus);

painter->restore();
}

Expand Down
137 changes: 64 additions & 73 deletions src/gui/folderstatusmodel.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*

Check notice on line 1 in src/gui/folderstatusmodel.cpp

View workflow job for this annotation

GitHub Actions / build

Run clang-format on src/gui/folderstatusmodel.cpp

File src/gui/folderstatusmodel.cpp does not conform to Custom style guidelines. (lines 993, 994, 1029, 1083, 1084, 1104, 1105, 1111, 1125, 1136)
* Copyright (C) by Klaas Freitag <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
Expand Down Expand Up @@ -270,7 +270,8 @@
return accountConnected;
case Qt::ToolTipRole: {
if (!progress.isNull()) {
return progress._progressString;
// e.g. 13 seconds left, 500 MB of 1 GB, file 3 of 6
return progress._overallSyncString;
}
auto toolTip = accountConnected
? Theme::instance()->statusHeaderText(folder->syncResult().status())
Expand Down Expand Up @@ -307,18 +308,20 @@
return Theme::instance()->folderOfflineIcon();
}
case FolderStatusDelegate::SyncProgressItemString:
// e.g. Syncing fileName1, filename2
return progress._progressString;
case FolderStatusDelegate::WarningCount:
return progress._warningCount;
case FolderStatusDelegate::SyncProgressOverallPercent:
return progress._overallPercent;
case FolderStatusDelegate::SyncProgressOverallString:
// 13 seconds left, 500 MB of 1 GB, file 3 of 6
return progress._overallSyncString;
case FolderStatusDelegate::FolderSyncText:
if (folder->virtualFilesEnabled()) {
return tr("Synchronizing VirtualFiles with local folder");
return tr("Synchronizing virtual files in local folder");
} else {
return tr("Synchronizing with local folder");
return tr("Synchronizing files in local folder");
}
}
return {};
Expand Down Expand Up @@ -896,7 +899,7 @@
if (!folder) {
return;
}

for (auto i = 0; i < _folders.count(); ++i) {
if (_folders.at(i)._folder == folder) {
emit dataChanged(index(i), index(i));
Expand Down Expand Up @@ -981,69 +984,64 @@
return;
}

auto *pi = &_folders[folderIndex]._progress;
auto *const subFolderProgress = &_folders[folderIndex]._progress;

if (progress.status() == ProgressInfo::Starting) {
_isSyncRunningForAwhile = false;
}

QVector<int> roles;
roles << FolderStatusDelegate::SyncProgressItemString
<< FolderStatusDelegate::WarningCount
<< Qt::ToolTipRole;
const QVector<int> roles{ FolderStatusDelegate::SyncProgressItemString, FolderStatusDelegate::WarningCount,
Qt::ToolTipRole };

if (progress.status() == ProgressInfo::Discovery) {
if (!progress._currentDiscoveredRemoteFolder.isEmpty()) {
pi->_overallSyncString = tr("Checking for changes in remote \"%1\"").arg(progress._currentDiscoveredRemoteFolder);
subFolderProgress->_overallSyncString = tr("Checking for changes in remote \"%1\"").arg(progress._currentDiscoveredRemoteFolder);
emit dataChanged(index(folderIndex), index(folderIndex), roles);
return;
} else if (!progress._currentDiscoveredLocalFolder.isEmpty()) {
pi->_overallSyncString = tr("Checking for changes in local \"%1\"").arg(progress._currentDiscoveredLocalFolder);
subFolderProgress->_overallSyncString = tr("Checking for changes in local \"%1\"").arg(progress._currentDiscoveredLocalFolder);
emit dataChanged(index(folderIndex), index(folderIndex), roles);
return;
}
}

if (progress.status() == ProgressInfo::Reconcile) {
pi->_overallSyncString = tr("Reconciling changes");
subFolderProgress->_overallSyncString = tr("Syncing local and remote changes");
emit dataChanged(index(folderIndex), index(folderIndex), roles);
return;
}

// Status is Starting, Propagation or Done

if (!progress._lastCompletedItem.isEmpty()
&& Progress::isWarningKind(progress._lastCompletedItem._status)) {
pi->_warningCount++;
subFolderProgress->_warningCount++;
}

// find the single item to display: This is going to be the bigger item, or the last completed
// item if no items are in progress.
auto curItem = progress._lastCompletedItem;
qint64 curItemProgress = -1; // -1 means finished
qint64 biggerItemSize = 0;
quint64 estimatedUpBw = 0;
quint64 estimatedDownBw = 0;
QString allFilenames;
for (const auto &citm : progress._currentItems) {
if (curItemProgress == -1 || (ProgressInfo::isSizeDependent(citm._item)
&& biggerItemSize < citm._item._size)) {
curItemProgress = citm._progress.completed();
curItem = citm._item;
biggerItemSize = citm._item._size;
auto curItemProgress = -1; // -1 means finished
auto biggerItemSize = 0;
auto estimatedUpBw = 0;
auto estimatedDownBw = 0;
QStringList filenamesList;
for (const auto &syncFile : progress._currentItems) {
if (curItemProgress == -1 || (ProgressInfo::isSizeDependent(syncFile._item)
&& biggerItemSize < syncFile._item._size)) {
curItemProgress = syncFile._progress.completed();
curItem = syncFile._item;
biggerItemSize = syncFile._item._size;
}
if (citm._item._direction != SyncFileItem::Up) {
estimatedDownBw += progress.fileProgress(citm._item).estimatedBandwidth;

if (syncFile._item._direction != SyncFileItem::Up) {
estimatedDownBw += progress.fileProgress(syncFile._item).estimatedBandwidth;
} else {
estimatedUpBw += progress.fileProgress(citm._item).estimatedBandwidth;
estimatedUpBw += progress.fileProgress(syncFile._item).estimatedBandwidth;
}
auto fileName = QFileInfo(citm._item._file).fileName();
if (allFilenames.length() > 0) {
//: Build a list of file names
allFilenames.append(QStringLiteral(", \"%1\"").arg(fileName));
} else {
//: Argument is a file name
allFilenames.append(QStringLiteral("\"%1\"").arg(fileName));

const auto fileName = QFileInfo(syncFile._item._file).fileName();
if (filenamesList.length() < 2) {
filenamesList.append(QStringLiteral("\"%1\"").arg(fileName));
}
}
if (curItemProgress == -1) {
Expand All @@ -1052,28 +1050,19 @@

const auto itemFileName = curItem._file;
const auto kindString = Progress::asActionString(curItem);

const auto allFilenames = filenamesList.join(", ");
QString fileProgressString;
if (ProgressInfo::isSizeDependent(curItem)) {
const auto s1 = Utility::octetsToString(curItemProgress);
const auto s2 = Utility::octetsToString(curItem._size);
//quint64 estimatedBw = progress.fileProgress(curItem).estimatedBandwidth;
if (estimatedUpBw || estimatedDownBw) {
/*
//: 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")
.arg(kindString, itemFileName, s1, s2,
Utility::durationToDescriptiveString(progress.fileProgress(curItem).estimatedEta),
Utility::octetsToString(estimatedBw) );
*/
//: Example text: "Uploading foobar.png (1MB of 2MB) time left 2 minutes at a rate of 24Kb/s"
//: Example text: "Syncing 'foo.txt', 'bar.txt'"
fileProgressString = tr("Syncing %1").arg(allFilenames);
fileProgressString = tr("%1 %2 …").arg(kindString, allFilenames);
if (estimatedDownBw > 0) {
fileProgressString.append(tr(", "));
// ifdefs: https://github.com/owncloud/client/issues/3095#issuecomment-128409294
#ifdef Q_OS_WIN
//: Example text: "download 24Kb/s" (%1 is replaced by 24Kb (translated))
fileProgressString.append(tr("download %1/s").arg(Utility::octetsToString(estimatedDownBw)));
//: Example text: "Download 24Kb/s" (%1 is replaced by 24Kb (translated))
fileProgressString.append(tr("Download %1/s").arg(Utility::octetsToString(estimatedDownBw)));
#else
fileProgressString.append(tr("\u2193 %1/s")
.arg(Utility::octetsToString(estimatedDownBw)));
Expand All @@ -1082,47 +1071,49 @@
if (estimatedUpBw > 0) {
fileProgressString.append(tr(", "));
#ifdef Q_OS_WIN
//: Example text: "upload 24Kb/s" (%1 is replaced by 24Kb (translated))
fileProgressString.append(tr("upload %1/s").arg(Utility::octetsToString(estimatedUpBw)));
//: Example text: "Upload 24Kb/s" (%1 is replaced by 24Kb (translated))
fileProgressString.append(tr("Upload %1/s").arg(Utility::octetsToString(estimatedUpBw)));
#else
fileProgressString.append(tr("\u2191 %1/s")
.arg(Utility::octetsToString(estimatedUpBw)));
#endif
}
} else {
//: Example text: "uploading foobar.png (2MB of 2MB)"
fileProgressString = tr("%1 %2 (%3 of %4)").arg(kindString, itemFileName, s1, s2);
//: Example text: "Uploading foobar.png (2MB of 2MB)"
fileProgressString = tr("%1 %2 (%3 of %4)").arg(kindString, itemFileName,
Utility::octetsToString(curItemProgress),
Utility::octetsToString(curItem._size));
}
} else if (!kindString.isEmpty()) {
//: Example text: "uploading foobar.png"
//: Example text: "Uploading foobar.png"
fileProgressString = tr("%1 %2").arg(kindString, itemFileName);
}
pi->_progressString = fileProgressString;
subFolderProgress->_progressString = fileProgressString;

// overall progress
const auto completedSize = progress.completedSize();
const auto completedFile = progress.completedFiles();
const auto currentFile = progress.currentFile();
const auto totalSize = qMax(completedSize, progress.totalSize());
const auto totalFileCount = qMax(currentFile, progress.totalFiles());
const auto totalSize = qMax(completedSize, progress.totalSize());

QString overallSyncString;
if (totalSize > 0) {
const auto s1 = Utility::octetsToString(completedSize);
const auto s2 = Utility::octetsToString(totalSize);
if (totalSize > 0 && completedSize > 0) {
const auto completedSizeString = Utility::octetsToString(completedSize);
const auto totalSizeString = Utility::octetsToString(totalSize);

const auto estimatedEta = progress.totalProgress().estimatedEta;
if (const auto estimatedEta = progress.totalProgress().estimatedEta;
progress.trustEta() && (estimatedEta > 0 || _isSyncRunningForAwhile)) {

if (progress.trustEta() && (estimatedEta > 0 || _isSyncRunningForAwhile)) {
_isSyncRunningForAwhile = true;
//: Example text: "5 minutes left, 12 MB of 345 MB, file 6 of 7"
if (estimatedEta == 0) {
overallSyncString = tr("A few seconds left, %1 of %2, file %3 of %4")
.arg(s1, s2)
.arg(completedSizeString, totalSizeString)
.arg(currentFile)
.arg(totalFileCount);
} else {
overallSyncString = tr("%5 left, %1 of %2, file %3 of %4")
.arg(s1, s2)
.arg(completedSizeString, totalSizeString)
.arg(currentFile)
.arg(totalFileCount)
.arg(Utility::durationToDescriptiveString1(estimatedEta));
Expand All @@ -1131,23 +1122,22 @@
} else {
//: Example text: "12 MB of 345 MB, file 6 of 7"
overallSyncString = tr("%1 of %2, file %3 of %4")
.arg(s1, s2)
.arg(completedSizeString, totalSizeString)
.arg(currentFile)
.arg(totalFileCount);
}
} else if (totalFileCount > 0) {
} else if (totalFileCount > 0 && currentFile > 0) {
// Don't attempt 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);
}

pi->_overallSyncString = overallSyncString;
subFolderProgress->_overallSyncString = overallSyncString;

auto overallPercent = 0;
if (totalFileCount > 0) {
if (const auto completedFile = progress.completedFiles();totalFileCount > 0) {
// Add one 'byte' for each file so the percentage is moving when deleting or renaming files
overallPercent = qRound(double(completedSize + completedFile) / double(totalSize + totalFileCount) * 100.0);
}
pi->_overallPercent = qBound(0, overallPercent, 100);
subFolderProgress->_overallPercent = qBound(0, overallPercent, 100);
emit dataChanged(index(folderIndex), index(folderIndex), roles);
}

Expand Down Expand Up @@ -1187,10 +1177,11 @@
const auto folderMan = FolderMan::instance();
auto pos = folderMan->scheduleQueue().indexOf(folder);
for (auto other : folderMan->map()) {
if (other != folder && other->isSyncRunning())
if (other != folder && other->isSyncRunning()) {
pos += 1;
}
}
const auto message = pos <= 0 ? tr("Waiting …") : tr("Waiting for %n other folder(s) …", "", pos);
const auto message = pos <= 0 ? tr("About to start syncing") : tr("Waiting for %n other folder(s) …", "", pos);
pi = SubFolderInfo::Progress();
pi._overallSyncString = message;
} else if (state == SyncResult::SyncPrepare) {
Expand Down
4 changes: 2 additions & 2 deletions src/gui/tray/syncstatussummary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,10 @@
case SyncResult::SyncRunning:
case SyncResult::NotYetStarted:
setSyncing(true);
if (totalFiles() <= 0) {

Check warning on line 158 in src/gui/tray/syncstatussummary.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/tray/syncstatussummary.cpp:158:9 [bugprone-branch-clone]

if with identical then and else branches
setSyncStatusString(tr("Preparing sync"));
setSyncStatusString(tr("Checking folder changes"));
} else {
setSyncStatusString(tr("Syncing"));
setSyncStatusString(tr("Syncing changes"));
}
setSyncStatusDetailString("");
setSyncIcon(Theme::instance()->syncStatusRunning());
Expand Down
2 changes: 1 addition & 1 deletion src/gui/updater/ocupdater.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
* for more details.
*/

#include "theme.h"

Check failure on line 15 in src/gui/updater/ocupdater.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/updater/ocupdater.cpp:15:10 [clang-diagnostic-error]

'theme.h' file not found
#include "configfile.h"
#include "common/utility.h"
#include "accessmanager.h"
Expand Down Expand Up @@ -149,7 +149,7 @@

switch (downloadState()) {
case Downloading:
return tr("Downloading %1. Please wait …").arg(updateVersion);
return tr("Downloading %1 …").arg(updateVersion);
case DownloadComplete:
return tr("%1 available. Restart application to start the update.").arg(updateVersion);
case DownloadFailed: {
Expand Down
16 changes: 8 additions & 8 deletions src/libsync/progressdispatcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,23 +74,23 @@ QString Progress::asActionString(const SyncFileItem &item)
case CSYNC_INSTRUCTION_NEW:
case CSYNC_INSTRUCTION_TYPE_CHANGE:
if (item._direction != SyncFileItem::Up)
return QCoreApplication::translate("progress", "downloading");
return QCoreApplication::translate("progress", "Downloading");
else
return QCoreApplication::translate("progress", "uploading");
return QCoreApplication::translate("progress", "Uploading");
case CSYNC_INSTRUCTION_REMOVE:
return QCoreApplication::translate("progress", "deleting");
return QCoreApplication::translate("progress", "Deleting");
case CSYNC_INSTRUCTION_EVAL_RENAME:
case CSYNC_INSTRUCTION_RENAME:
return QCoreApplication::translate("progress", "moving");
return QCoreApplication::translate("progress", "Moving");
case CSYNC_INSTRUCTION_IGNORE:
return QCoreApplication::translate("progress", "ignoring");
return QCoreApplication::translate("progress", "Ignoring");
case CSYNC_INSTRUCTION_STAT_ERROR:
case CSYNC_INSTRUCTION_ERROR:
return QCoreApplication::translate("progress", "error");
return QCoreApplication::translate("progress", "Error");
case CSYNC_INSTRUCTION_UPDATE_METADATA:
return QCoreApplication::translate("progress", "updating local metadata");
return QCoreApplication::translate("progress", "Updating local metadata");
case CSYNC_INSTRUCTION_UPDATE_VFS_METADATA:
return QCoreApplication::translate("progress", "updating local virtual files metadata");
return QCoreApplication::translate("progress", "Updating local virtual files metadata");
case CSYNC_INSTRUCTION_NONE:
case CSYNC_INSTRUCTION_EVAL:
break;
Expand Down
Loading
Loading