mirror of
https://github.com/nextcloud/desktop.git
synced 2024-10-24 05:15:40 +03:00
More sophisticated progress, add Recent Changes Menu to tray.
ProgressDispatcher now stores a queue of events as well as sync problems, better known as soft errors. The tray menu displays a sub menu with 5 recent changes and adds a more... button that shows a warning icon if soft errors had happend. More to implement.
This commit is contained in:
parent
a0d9d41455
commit
a64724be0e
8 changed files with 154 additions and 34 deletions
|
@ -492,7 +492,7 @@ QString AccountSettings::shortenFilename( const QString& folder, const QString&
|
|||
return shortFile;
|
||||
}
|
||||
|
||||
void AccountSettings::slotSetProgress( const QString& folder, Progress::Info progress )
|
||||
void AccountSettings::slotSetProgress(const QString& folder, const Progress::Info &progress )
|
||||
{
|
||||
// qDebug() << "================================> Progress for folder " << folder << " file " << file << ": "<< p1;
|
||||
QStandardItem *item = itemForFolder( folder );
|
||||
|
|
|
@ -99,6 +99,7 @@ Application::Application(int &argc, char **argv) :
|
|||
_networkMgr(new QNetworkConfigurationManager(this)),
|
||||
_sslErrorDialog(0),
|
||||
_contextMenu(0),
|
||||
_recentActionsMenu(0),
|
||||
_theme(Theme::instance()),
|
||||
_logBrowser(0),
|
||||
_logExpire(0),
|
||||
|
@ -125,6 +126,9 @@ Application::Application(int &argc, char **argv) :
|
|||
connect( pd, SIGNAL(progressInfo(QString,Progress::Info)), this,
|
||||
SLOT(slotUpdateProgress(QString,Progress::Info)) );
|
||||
|
||||
connect( pd, SIGNAL(progressSyncProblem(QString,Progress::SyncProblem)),
|
||||
SLOT(slotProgressSyncProblem(QString,Progress::SyncProblem)));
|
||||
|
||||
// create folder manager for sync folder management
|
||||
FolderMan *folderMan = FolderMan::instance();
|
||||
connect( folderMan, SIGNAL(folderSyncStateChange(QString)),
|
||||
|
@ -285,6 +289,10 @@ void Application::setupActions()
|
|||
_actionStatus = new QAction(tr("Unknown status"), this);
|
||||
_actionStatus->setEnabled( false );
|
||||
_actionSettings = new QAction(tr("Settings..."), this);
|
||||
_actionRecent = new QAction(tr("more..."), this);
|
||||
_actionRecent->setEnabled( true );
|
||||
|
||||
QObject::connect(_actionRecent, SIGNAL(triggered(bool)), SLOT(slotShowRecentChanges()));
|
||||
QObject::connect(_actionSettings, SIGNAL(triggered(bool)), SLOT(slotSettings()));
|
||||
_actionHelp = new QAction(tr("Help"), this);
|
||||
QObject::connect(_actionHelp, SIGNAL(triggered(bool)), SLOT(slotHelp()));
|
||||
|
@ -316,8 +324,11 @@ void Application::setupContextMenu()
|
|||
|
||||
if( _contextMenu ) {
|
||||
_contextMenu->clear();
|
||||
_recentActionsMenu->clear();
|
||||
_recentActionsMenu->addAction(tr("None."));
|
||||
} else {
|
||||
_contextMenu = new QMenu();
|
||||
_recentActionsMenu = _contextMenu->addMenu(tr("Recent Changes..."));
|
||||
// this must be called only once after creating the context menu, or
|
||||
// it will trigger a bug in Ubuntu's SNI bridge patch (11.10, 12.04).
|
||||
_tray->setContextMenu(_contextMenu);
|
||||
|
@ -359,6 +370,7 @@ void Application::setupContextMenu()
|
|||
_contextMenu->addAction(_actionQuota);
|
||||
_contextMenu->addSeparator();
|
||||
_contextMenu->addAction(_actionStatus);
|
||||
_contextMenu->addMenu(_recentActionsMenu);
|
||||
_contextMenu->addSeparator();
|
||||
_contextMenu->addAction(_actionSettings);
|
||||
_contextMenu->addAction(_actionHelp);
|
||||
|
@ -484,23 +496,71 @@ void Application::slotUseMonoIconsChanged(bool)
|
|||
computeOverallSyncStatus();
|
||||
}
|
||||
|
||||
void Application::slotUpdateProgress(const QString &folder, Progress::Info progress)
|
||||
void Application::slotProgressSyncProblem(const QString& folder, const Progress::SyncProblem& problem)
|
||||
{
|
||||
Q_UNUSED(folder);
|
||||
Q_UNUSED(problem);
|
||||
|
||||
// display a warn icon if warnings happend.
|
||||
QIcon warnIcon(":/mirall/resources/warning-16");
|
||||
_actionRecent->setIcon(warnIcon);
|
||||
|
||||
rebuildRecentMenus();
|
||||
}
|
||||
|
||||
void Application::rebuildRecentMenus()
|
||||
{
|
||||
_recentActionsMenu->clear();
|
||||
QList<Progress::Info> progressInfoList;
|
||||
progressInfoList = ProgressDispatcher::instance()->recentChangedItems(5);
|
||||
|
||||
if( progressInfoList.size() == 0 ) {
|
||||
_recentActionsMenu->addAction(tr("No items synced recently"));
|
||||
} else {
|
||||
foreach( Progress::Info info, progressInfoList ) {
|
||||
QString kindStr = tr("Upload");
|
||||
if( info.kind == Progress::EndDownload ) {
|
||||
kindStr = tr("Download");
|
||||
}
|
||||
QString timeStr = info.timestamp.toString("hh:mm");
|
||||
|
||||
QString actionText = tr("%1 (%2, %3)").arg(info.current_file).arg(kindStr).arg(timeStr);
|
||||
_recentActionsMenu->addAction( actionText );
|
||||
}
|
||||
}
|
||||
// add a more... entry.
|
||||
_recentActionsMenu->addAction(_actionRecent);
|
||||
}
|
||||
|
||||
void Application::slotUpdateProgress(const QString &folder, const Progress::Info& progress)
|
||||
{
|
||||
Q_UNUSED(folder);
|
||||
|
||||
// shows an entry in the context menu.
|
||||
QString curAmount = Utility::octetsToString(progress.overall_current_bytes);
|
||||
QString totalAmount = Utility::octetsToString(progress.overall_transmission_size);
|
||||
_actionStatus->setText(tr("Syncing %1 of %2 (%3 of %4) ").arg(progress.current_file_no)
|
||||
.arg(progress.overall_file_count).arg(curAmount, totalAmount));
|
||||
|
||||
// wipe the problem list at start of sync.
|
||||
if( progress.kind == Progress::StartSync ) {
|
||||
_actionRecent->setIcon( QIcon() ); // Fixme: Set a "in-progress"-item eventually.
|
||||
}
|
||||
|
||||
// If there was a change in the file list, redo the progress menu.
|
||||
if( progress.kind == Progress::EndDownload || progress.kind == Progress::EndUpload ) {
|
||||
rebuildRecentMenus();
|
||||
}
|
||||
|
||||
if (progress.kind == Progress::EndSync) {
|
||||
rebuildRecentMenus(); // show errors.
|
||||
QTimer::singleShot(2000, this, SLOT(slotDisplayIdle()));
|
||||
}
|
||||
}
|
||||
|
||||
void Application::slotDisplayIdle()
|
||||
{
|
||||
_actionStatus->setText(tr("Idle"));
|
||||
_actionStatus->setText(tr("In Sync"));
|
||||
}
|
||||
|
||||
void Application::slotHelp()
|
||||
|
@ -577,6 +637,11 @@ void Application::slotFoldersChanged()
|
|||
setupContextMenu();
|
||||
}
|
||||
|
||||
void Application::slotShowRecentChanges()
|
||||
{
|
||||
// not yet here.
|
||||
}
|
||||
|
||||
void Application::slotSettings()
|
||||
{
|
||||
if (_settingsDialog.isNull()) {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <QNetworkReply>
|
||||
#include <QSslError>
|
||||
#include <QPointer>
|
||||
#include <QQueue>
|
||||
|
||||
#include "qtsingleapplication.h"
|
||||
|
||||
|
@ -98,18 +99,22 @@ protected slots:
|
|||
void slotSetupProxy();
|
||||
void slotRefreshQuotaDisplay( qint64 total, qint64 used );
|
||||
void slotUseMonoIconsChanged( bool );
|
||||
void slotUpdateProgress(const QString&,Progress::Info);
|
||||
void slotUpdateProgress(const QString&, const Progress::Info&);
|
||||
void slotProgressSyncProblem(const QString& folder, const Progress::SyncProblem &problem);
|
||||
void slotDisplayIdle();
|
||||
void slotHelp();
|
||||
void slotShowRecentChanges();
|
||||
private:
|
||||
void setHelp();
|
||||
void raiseDialog( QWidget* );
|
||||
void rebuildRecentMenus();
|
||||
|
||||
Systray *_tray;
|
||||
QAction *_actionOpenoC;
|
||||
QAction *_actionSettings;
|
||||
QAction *_actionQuota;
|
||||
QAction *_actionStatus;
|
||||
QAction *_actionRecent;
|
||||
QAction *_actionHelp;
|
||||
QAction *_actionQuit;
|
||||
|
||||
|
@ -121,6 +126,7 @@ private:
|
|||
|
||||
// tray's menu
|
||||
QMenu *_contextMenu;
|
||||
QMenu *_recentActionsMenu;
|
||||
|
||||
Theme *_theme;
|
||||
QSignalMapper *_folderOpenActionMapper;
|
||||
|
@ -128,6 +134,7 @@ private:
|
|||
QPointer<SettingsDialog> _settingsDialog;
|
||||
QString _logFile;
|
||||
QString _logDirectory;
|
||||
|
||||
int _logExpire;
|
||||
bool _showLogWindow;
|
||||
bool _logFlush;
|
||||
|
|
|
@ -395,7 +395,7 @@ void CSyncThread::startSync()
|
|||
|
||||
if( walkOk ) {
|
||||
if( csync_walk_local_tree(_csync_ctx, &walkFinalize, 0) < 0 ||
|
||||
csync_walk_remote_tree( _csync_ctx, &walkFinalize, 0 ) < 0 ) {
|
||||
csync_walk_remote_tree(_csync_ctx, &walkFinalize, 0 ) < 0 ) {
|
||||
qDebug() << "Error in finalize treewalk.";
|
||||
} else {
|
||||
// emit the treewalk results.
|
||||
|
@ -466,6 +466,7 @@ void CSyncThread::cb_progress( CSYNC_PROGRESS *progress, void *userdata )
|
|||
pInfo.current_file_no = progress->current_file_no;
|
||||
pInfo.overall_transmission_size = progress->overall_transmission_size;
|
||||
pInfo.overall_current_bytes = progress->current_overall_bytes;
|
||||
pInfo.timestamp = QTime::currentTime();
|
||||
|
||||
// Connect to something in folder!
|
||||
thread->transmissionProgress( pInfo );
|
||||
|
|
|
@ -630,7 +630,19 @@ void Folder::slotCSyncFinished()
|
|||
|
||||
void Folder::slotTransmissionProgress(const Progress::Info& progress)
|
||||
{
|
||||
ProgressDispatcher::instance()->setProgressInfo(alias(), progress);
|
||||
Progress::Info newInfo = progress;
|
||||
newInfo.folder = alias();
|
||||
|
||||
if(newInfo.current_file.startsWith(QLatin1String("ownclouds://")) ||
|
||||
newInfo.current_file.startsWith(QLatin1String("owncloud://")) ) {
|
||||
// rip off the whole ownCloud URL.
|
||||
QString regexp = QString("^owncloud[s]*://.*/remote.php/webdav/%1/").arg(secondPath());
|
||||
QRegExp re( regexp );
|
||||
re.setMinimal(true);
|
||||
newInfo.current_file.remove(re);
|
||||
}
|
||||
|
||||
ProgressDispatcher::instance()->setProgressInfo(alias(), newInfo);
|
||||
}
|
||||
|
||||
ServerActionNotifier::ServerActionNotifier(QObject *parent)
|
||||
|
@ -667,7 +679,10 @@ void ServerActionNotifier::slotSyncFinished(const SyncResult &result)
|
|||
updatedItems++;
|
||||
if (firstItemUpdated.isEmpty())
|
||||
firstItemUpdated = item;
|
||||
break;
|
||||
break;
|
||||
case CSYNC_INSTRUCTION_ERROR:
|
||||
qDebug() << "Got Instruction ERROR. " << result.errorString();
|
||||
break;
|
||||
default:
|
||||
// nothing.
|
||||
break;
|
||||
|
|
|
@ -62,7 +62,7 @@ public slots:
|
|||
void slotSyncFinished(const SyncResult &result);
|
||||
signals:
|
||||
void guiLog(const QString&, const QString&);
|
||||
void sendResults();
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
|
|
|
@ -71,7 +71,8 @@ ProgressDispatcher* ProgressDispatcher::instance() {
|
|||
}
|
||||
|
||||
ProgressDispatcher::ProgressDispatcher(QObject *parent) :
|
||||
QObject(parent)
|
||||
QObject(parent),
|
||||
_problemQueueSize(50)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -81,27 +82,45 @@ ProgressDispatcher::~ProgressDispatcher()
|
|||
|
||||
}
|
||||
|
||||
void ProgressDispatcher::setProgressInfo(const QString& folder, Progress::Info newProgress)
|
||||
QList<Progress::Info> ProgressDispatcher::recentChangedItems(int count)
|
||||
{
|
||||
return _recentChanges.mid(0, count);
|
||||
}
|
||||
|
||||
QList<Progress::SyncProblem> ProgressDispatcher::recentProblems(int count)
|
||||
{
|
||||
return _recentProblems.mid(0, count);
|
||||
}
|
||||
|
||||
void ProgressDispatcher::setProgressInfo(const QString& folder, const Progress::Info& progress)
|
||||
{
|
||||
if( folder.isEmpty() ) {
|
||||
return;
|
||||
}
|
||||
Progress::Info newProgress = progress;
|
||||
|
||||
if( newProgress.kind == Progress::Error ) {
|
||||
const char *msg = (const char*)newProgress.file_size;
|
||||
qDebug() << "Progress-Error:" << QString::fromLocal8Bit(msg);
|
||||
Progress::SyncProblem err;
|
||||
err.folder = folder;
|
||||
err.current_file = newProgress.current_file;
|
||||
err.error_message = QString::fromLocal8Bit( (const char*)newProgress.file_size );
|
||||
err.error_code = newProgress.file_size;
|
||||
|
||||
_recentProblems.enqueue( err );
|
||||
if( _recentProblems.size() > _problemQueueSize ) {
|
||||
_recentProblems.dequeue();
|
||||
}
|
||||
emit progressSyncProblem( folder, err );
|
||||
} else {
|
||||
if( newProgress.kind == Progress::EndSync ) {
|
||||
newProgress.overall_current_bytes = newProgress.overall_transmission_size;
|
||||
newProgress.current_file_no = newProgress.overall_file_count;
|
||||
}
|
||||
if( newProgress.kind == Progress::EndDownload || newProgress.kind == Progress::EndUpload ) {
|
||||
_recentChanges.enqueue(newProgress);
|
||||
}
|
||||
emit progressInfo( folder, newProgress );
|
||||
}
|
||||
if( newProgress.kind == Progress::EndSync ) {
|
||||
newProgress.overall_current_bytes = newProgress.overall_transmission_size;
|
||||
newProgress.current_file_no = newProgress.overall_file_count;
|
||||
}
|
||||
_lastProgressHash[folder] = newProgress;
|
||||
|
||||
emit progressInfo( folder, newProgress );
|
||||
}
|
||||
|
||||
Progress::Info ProgressDispatcher::lastProgressInfo(const QString& folder) {
|
||||
return _lastProgressHash[folder];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
#include <QObject>
|
||||
#include <QHash>
|
||||
#include <QTime>
|
||||
#include <QQueue>
|
||||
|
||||
namespace Mirall {
|
||||
|
||||
|
@ -26,7 +28,7 @@ namespace Mirall {
|
|||
class Progress
|
||||
{
|
||||
public:
|
||||
enum ProgressKind_s {
|
||||
typedef enum {
|
||||
Invalid,
|
||||
StartSync,
|
||||
Download,
|
||||
|
@ -39,11 +41,11 @@ public:
|
|||
EndUpload,
|
||||
EndSync,
|
||||
Error
|
||||
};
|
||||
typedef ProgressKind_s Kind;
|
||||
} Kind;
|
||||
|
||||
struct ProgressInfo_s {
|
||||
typedef struct {
|
||||
Kind kind;
|
||||
QString folder;
|
||||
QString current_file;
|
||||
qint64 file_size;
|
||||
qint64 current_file_bytes;
|
||||
|
@ -53,8 +55,16 @@ public:
|
|||
qint64 overall_transmission_size;
|
||||
qint64 overall_current_bytes;
|
||||
|
||||
};
|
||||
typedef ProgressInfo_s Info;
|
||||
QTime timestamp;
|
||||
|
||||
} Info;
|
||||
|
||||
typedef struct {
|
||||
QString folder;
|
||||
QString current_file;
|
||||
QString error_message;
|
||||
int error_code;
|
||||
} SyncProblem;
|
||||
|
||||
static QString asString( Kind );
|
||||
};
|
||||
|
@ -77,7 +87,8 @@ public:
|
|||
static ProgressDispatcher* instance();
|
||||
~ProgressDispatcher();
|
||||
|
||||
Progress::Info lastProgressInfo(const QString& folder);
|
||||
QList<Progress::Info> recentChangedItems(int count);
|
||||
QList<Progress::SyncProblem> recentProblems(int count);
|
||||
signals:
|
||||
/**
|
||||
@brief Signals the progress of data transmission.
|
||||
|
@ -87,17 +98,19 @@ signals:
|
|||
|
||||
*/
|
||||
|
||||
void progressInfo( const QString& folder, Progress::Info progress );
|
||||
void progressInfo( const QString& folder, const Progress::Info& progress );
|
||||
void progressSyncProblem( const QString& folder, const Progress::SyncProblem& problem );
|
||||
|
||||
protected:
|
||||
void setProgressInfo(const QString &folder, Progress::Info newProgress);
|
||||
void setProgressInfo(const QString &folder, const Progress::Info& progress);
|
||||
|
||||
private:
|
||||
ProgressDispatcher(QObject* parent = 0);
|
||||
const int _problemQueueSize;
|
||||
QQueue<Progress::Info> _recentChanges;
|
||||
QQueue<Progress::SyncProblem> _recentProblems;
|
||||
|
||||
static ProgressDispatcher* _instance;
|
||||
|
||||
QHash<QString, Progress::Info> _lastProgressHash;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue