mirror of
https://github.com/nextcloud/desktop.git
synced 2024-11-24 05:55:59 +03:00
Show sync progress in main dialog
Fixes #3662 Signed-off-by: Felix Weilbach <felix.weilbach@nextcloud.com>
This commit is contained in:
parent
375dc92454
commit
4c11f6763e
12 changed files with 568 additions and 19 deletions
|
@ -7,6 +7,7 @@
|
|||
<file>src/gui/tray/Window.qml</file>
|
||||
<file>src/gui/tray/UserLine.qml</file>
|
||||
<file>src/gui/tray/HeaderButton.qml</file>
|
||||
<file>src/gui/tray/SyncStatus.qml</file>
|
||||
<file>theme/Style/Style.qml</file>
|
||||
<file>theme/Style/qmldir</file>
|
||||
<file>src/gui/tray/ActivityActionButton.qml</file>
|
||||
|
|
|
@ -113,6 +113,7 @@ set(client_SRCS
|
|||
userstatusselectormodel.cpp
|
||||
emojimodel.cpp
|
||||
fileactivitylistmodel.cpp
|
||||
tray/syncstatussummary.cpp
|
||||
tray/ActivityData.cpp
|
||||
tray/ActivityListModel.cpp
|
||||
tray/UserModel.cpp
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "cocoainitializer.h"
|
||||
#include "userstatusselectormodel.h"
|
||||
#include "emojimodel.h"
|
||||
#include "tray/syncstatussummary.h"
|
||||
|
||||
#if defined(BUILD_UPDATER)
|
||||
#include "updater/updater.h"
|
||||
|
@ -59,6 +60,7 @@ int main(int argc, char **argv)
|
|||
Q_INIT_RESOURCE(resources);
|
||||
Q_INIT_RESOURCE(theme);
|
||||
|
||||
qmlRegisterType<SyncStatusSummary>("com.nextcloud.desktopclient", 1, 0, "SyncStatusSummary");
|
||||
qmlRegisterType<EmojiModel>("com.nextcloud.desktopclient", 1, 0, "EmojiModel");
|
||||
qmlRegisterType<UserStatusSelectorModel>("com.nextcloud.desktopclient", 1, 0, "UserStatusSelectorModel");
|
||||
qmlRegisterType<OCC::ActivityListModel>("com.nextcloud.desktopclient", 1, 0, "ActivityListModel");
|
||||
|
|
|
@ -18,7 +18,6 @@ MouseArea {
|
|||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 2
|
||||
color: (parent.containsMouse ? Style.lightHover : "transparent")
|
||||
}
|
||||
|
||||
|
@ -41,7 +40,7 @@ MouseArea {
|
|||
Image {
|
||||
id: activityIcon
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
|
||||
Layout.leftMargin: 8
|
||||
Layout.leftMargin: 20
|
||||
Layout.preferredWidth: shareButton.icon.width
|
||||
Layout.preferredHeight: shareButton.icon.height
|
||||
verticalAlignment: Qt.AlignCenter
|
||||
|
@ -53,13 +52,12 @@ MouseArea {
|
|||
|
||||
Column {
|
||||
id: activityTextColumn
|
||||
Layout.leftMargin: 8
|
||||
Layout.leftMargin: 14
|
||||
Layout.topMargin: 4
|
||||
Layout.bottomMargin: 4
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
spacing: 4
|
||||
Layout.alignment: Qt.AlignLeft
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
|
||||
|
||||
Text {
|
||||
id: activityTextTitle
|
||||
|
|
89
src/gui/tray/SyncStatus.qml
Normal file
89
src/gui/tray/SyncStatus.qml
Normal file
|
@ -0,0 +1,89 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import Style 1.0
|
||||
|
||||
import com.nextcloud.desktopclient 1.0 as NC
|
||||
|
||||
RowLayout {
|
||||
id: layout
|
||||
|
||||
property alias model: syncStatus
|
||||
|
||||
spacing: 0
|
||||
|
||||
NC.SyncStatusSummary {
|
||||
id: syncStatus
|
||||
}
|
||||
|
||||
Image {
|
||||
id: syncIcon
|
||||
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
|
||||
Layout.topMargin: 16
|
||||
Layout.bottomMargin: 16
|
||||
Layout.leftMargin: 16
|
||||
|
||||
source: syncStatus.syncIcon
|
||||
sourceSize.width: 32
|
||||
sourceSize.height: 32
|
||||
rotation: syncStatus.syncing ? 0 : 0
|
||||
}
|
||||
|
||||
RotationAnimator {
|
||||
target: syncIcon
|
||||
running: syncStatus.syncing
|
||||
from: 0
|
||||
to: 360
|
||||
loops: Animation.Infinite
|
||||
duration: 3000
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: syncProgressLayout
|
||||
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.topMargin: 8
|
||||
Layout.rightMargin: 16
|
||||
Layout.leftMargin: 10
|
||||
Layout.bottomMargin: 8
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
Text {
|
||||
id: syncProgressText
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: syncStatus.syncStatusString
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
font.pixelSize: Style.topLinePixelSize
|
||||
font.bold: true
|
||||
}
|
||||
|
||||
Loader {
|
||||
Layout.fillWidth: true
|
||||
|
||||
active: syncStatus.syncing;
|
||||
visible: syncStatus.syncing
|
||||
|
||||
sourceComponent: ProgressBar {
|
||||
id: syncProgressBar
|
||||
|
||||
value: syncStatus.syncProgress
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
id: syncProgressDetailText
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: syncStatus.syncStatusDetailString
|
||||
visible: syncStatus.syncStatusDetailString !== ""
|
||||
color: "#808080"
|
||||
font.pixelSize: Style.subLinePixelSize
|
||||
}
|
||||
}
|
||||
}
|
|
@ -563,6 +563,11 @@ AccountPtr User::account() const
|
|||
return _account->account();
|
||||
}
|
||||
|
||||
AccountStatePtr User::accountState() const
|
||||
{
|
||||
return _account;
|
||||
}
|
||||
|
||||
void User::setCurrentUser(const bool &isCurrent)
|
||||
{
|
||||
_isCurrentUser = isCurrent;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <QHash>
|
||||
|
||||
#include "ActivityListModel.h"
|
||||
#include "accountfwd.h"
|
||||
#include "accountmanager.h"
|
||||
#include "folderman.h"
|
||||
#include "NotificationCache.h"
|
||||
|
@ -36,6 +37,7 @@ public:
|
|||
User(AccountStatePtr &account, const bool &isCurrent = false, QObject *parent = nullptr);
|
||||
|
||||
AccountPtr account() const;
|
||||
AccountStatePtr accountState() const;
|
||||
|
||||
bool isConnected() const;
|
||||
bool isCurrentUser() const;
|
||||
|
|
|
@ -50,12 +50,14 @@ Window {
|
|||
// see also id:accountMenu below
|
||||
userLineInstantiator.active = false;
|
||||
userLineInstantiator.active = true;
|
||||
syncStatus.model.load();
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: UserModel
|
||||
function onNewUserSelected() {
|
||||
accountMenu.close();
|
||||
syncStatus.model.load();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -564,20 +566,28 @@ Window {
|
|||
}
|
||||
} // Rectangle trayWindowHeaderBackground
|
||||
|
||||
ActivityList {
|
||||
anchors.top: trayWindowHeaderBackground.bottom
|
||||
anchors.left: trayWindowBackground.left
|
||||
anchors.right: trayWindowBackground.right
|
||||
anchors.bottom: trayWindowBackground.bottom
|
||||
SyncStatus {
|
||||
id: syncStatus
|
||||
|
||||
anchors.top: trayWindowHeaderBackground.bottom
|
||||
anchors.left: trayWindowBackground.left
|
||||
anchors.right: trayWindowBackground.right
|
||||
}
|
||||
|
||||
ActivityList {
|
||||
anchors.top: syncStatus.bottom
|
||||
anchors.left: trayWindowBackground.left
|
||||
anchors.right: trayWindowBackground.right
|
||||
anchors.bottom: trayWindowBackground.bottom
|
||||
|
||||
model: activityModel
|
||||
onShowFileActivity: {
|
||||
openFileActivityDialog(displayPath, absolutePath)
|
||||
}
|
||||
onActivityItemClicked: {
|
||||
model.triggerDefaultAction(index)
|
||||
}
|
||||
}
|
||||
model: activityModel
|
||||
onShowFileActivity: {
|
||||
openFileActivityDialog(displayPath, absolutePath)
|
||||
}
|
||||
onActivityItemClicked: {
|
||||
model.triggerDefaultAction(index)
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: fileActivityDialogLoader
|
||||
|
|
314
src/gui/tray/syncstatussummary.cpp
Normal file
314
src/gui/tray/syncstatussummary.cpp
Normal file
|
@ -0,0 +1,314 @@
|
|||
/*
|
||||
* Copyright (C) by Felix Weilbach <felix.weilbach@nextcloud.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include "syncstatussummary.h"
|
||||
#include "folderman.h"
|
||||
#include "navigationpanehelper.h"
|
||||
#include "networkjobs.h"
|
||||
#include "syncresult.h"
|
||||
#include "tray/UserModel.h"
|
||||
|
||||
#include <theme.h>
|
||||
|
||||
namespace {
|
||||
|
||||
OCC::SyncResult::Status determineSyncStatus(const OCC::SyncResult &syncResult)
|
||||
{
|
||||
const auto status = syncResult.status();
|
||||
|
||||
if (status == OCC::SyncResult::Success || status == OCC::SyncResult::Problem) {
|
||||
if (syncResult.hasUnresolvedConflicts()) {
|
||||
return OCC::SyncResult::Problem;
|
||||
}
|
||||
return OCC::SyncResult::Success;
|
||||
} else if (status == OCC::SyncResult::SyncPrepare || status == OCC::SyncResult::Undefined) {
|
||||
return OCC::SyncResult::SyncRunning;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
namespace OCC {
|
||||
|
||||
Q_LOGGING_CATEGORY(lcSyncStatusModel, "nextcloud.gui.syncstatusmodel", QtInfoMsg)
|
||||
|
||||
SyncStatusSummary::SyncStatusSummary(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
const auto folderMan = FolderMan::instance();
|
||||
connect(folderMan, &FolderMan::folderListChanged, this, &SyncStatusSummary::onFolderListChanged);
|
||||
connect(folderMan, &FolderMan::folderSyncStateChange, this, &SyncStatusSummary::onFolderSyncStateChanged);
|
||||
}
|
||||
|
||||
void SyncStatusSummary::load()
|
||||
{
|
||||
auto accountState = UserModel::instance()->currentUser()->accountState();
|
||||
|
||||
if (_accountState.data() == accountState.data()) {
|
||||
return;
|
||||
}
|
||||
|
||||
_accountState = accountState;
|
||||
clearFolderErrors();
|
||||
connectToFoldersProgress(FolderMan::instance()->map());
|
||||
auto syncStateFallbackNeeded = true;
|
||||
for (const auto &folder : FolderMan::instance()->map()) {
|
||||
if (_accountState.data() != folder->accountState()) {
|
||||
continue;
|
||||
}
|
||||
onFolderSyncStateChanged(folder);
|
||||
syncStateFallbackNeeded = false;
|
||||
}
|
||||
|
||||
if (syncStateFallbackNeeded) {
|
||||
setSyncing(false);
|
||||
setSyncStatusDetailString("");
|
||||
if (_accountState && !_accountState->isConnected()) {
|
||||
setSyncStatusString(tr("Offline"));
|
||||
setSyncIcon(Theme::instance()->folderOffline());
|
||||
} else {
|
||||
setSyncStatusString(tr("All synced!"));
|
||||
setSyncIcon(Theme::instance()->syncStatusOk());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double SyncStatusSummary::syncProgress() const
|
||||
{
|
||||
return _progress;
|
||||
}
|
||||
|
||||
QUrl SyncStatusSummary::syncIcon() const
|
||||
{
|
||||
return _syncIcon;
|
||||
}
|
||||
|
||||
bool SyncStatusSummary::syncing() const
|
||||
{
|
||||
return _isSyncing;
|
||||
}
|
||||
|
||||
void SyncStatusSummary::onFolderListChanged(const OCC::Folder::Map &folderMap)
|
||||
{
|
||||
connectToFoldersProgress(folderMap);
|
||||
}
|
||||
|
||||
void SyncStatusSummary::markFolderAsError(const Folder *folder)
|
||||
{
|
||||
_foldersWithErrors.insert(folder->alias());
|
||||
}
|
||||
|
||||
void SyncStatusSummary::markFolderAsSuccess(const Folder *folder)
|
||||
{
|
||||
_foldersWithErrors.erase(folder->alias());
|
||||
}
|
||||
|
||||
bool SyncStatusSummary::folderErrors() const
|
||||
{
|
||||
return _foldersWithErrors.size() != 0;
|
||||
}
|
||||
|
||||
bool SyncStatusSummary::folderError(const Folder *folder) const
|
||||
{
|
||||
return _foldersWithErrors.find(folder->alias()) != _foldersWithErrors.end();
|
||||
}
|
||||
|
||||
void SyncStatusSummary::clearFolderErrors()
|
||||
{
|
||||
_foldersWithErrors.clear();
|
||||
}
|
||||
|
||||
void SyncStatusSummary::setSyncStateForFolder(const Folder *folder)
|
||||
{
|
||||
if (_accountState && !_accountState->isConnected()) {
|
||||
setSyncing(false);
|
||||
setSyncStatusString(tr("Offline"));
|
||||
setSyncStatusDetailString("");
|
||||
setSyncIcon(Theme::instance()->folderOffline());
|
||||
return;
|
||||
}
|
||||
|
||||
const auto state = determineSyncStatus(folder->syncResult());
|
||||
|
||||
switch (state) {
|
||||
case SyncResult::Success:
|
||||
case SyncResult::SyncPrepare:
|
||||
// Success should only be shown if all folders were fine
|
||||
if (!folderErrors() || folderError(folder)) {
|
||||
setSyncing(false);
|
||||
setSyncStatusString(tr("All synced!"));
|
||||
setSyncStatusDetailString("");
|
||||
setSyncIcon(Theme::instance()->syncStatusOk());
|
||||
markFolderAsSuccess(folder);
|
||||
}
|
||||
break;
|
||||
case SyncResult::Error:
|
||||
case SyncResult::SetupError:
|
||||
setSyncing(false);
|
||||
setSyncStatusString(tr("Some files couldn't be synced!"));
|
||||
setSyncStatusDetailString(tr("See below for errors"));
|
||||
setSyncIcon(Theme::instance()->syncStatusError());
|
||||
markFolderAsError(folder);
|
||||
break;
|
||||
case SyncResult::SyncRunning:
|
||||
case SyncResult::NotYetStarted:
|
||||
setSyncing(true);
|
||||
setSyncStatusString(tr("Syncing"));
|
||||
setSyncStatusDetailString("");
|
||||
setSyncIcon(Theme::instance()->syncStatusRunning());
|
||||
break;
|
||||
case SyncResult::Paused:
|
||||
case SyncResult::SyncAbortRequested:
|
||||
setSyncing(false);
|
||||
setSyncStatusString(tr("Sync paused"));
|
||||
setSyncStatusDetailString("");
|
||||
setSyncIcon(Theme::instance()->syncStatusPause());
|
||||
break;
|
||||
case SyncResult::Problem:
|
||||
case SyncResult::Undefined:
|
||||
setSyncing(false);
|
||||
setSyncStatusString(tr("Some files had problems during the sync!"));
|
||||
setSyncStatusDetailString(tr("See below for warnings"));
|
||||
setSyncIcon(Theme::instance()->syncStatusWarning());
|
||||
markFolderAsError(folder);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SyncStatusSummary::onFolderSyncStateChanged(const Folder *folder)
|
||||
{
|
||||
if (!folder) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_accountState || folder->accountState() != _accountState.data()) {
|
||||
return;
|
||||
}
|
||||
|
||||
setSyncStateForFolder(folder);
|
||||
}
|
||||
|
||||
constexpr double calculateOverallPercent(
|
||||
qint64 totalFileCount, qint64 completedFile, qint64 totalSize, qint64 completedSize)
|
||||
{
|
||||
int overallPercent = 0;
|
||||
if (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);
|
||||
}
|
||||
overallPercent = qBound(0, overallPercent, 100);
|
||||
return overallPercent / 100.0;
|
||||
}
|
||||
|
||||
void SyncStatusSummary::onFolderProgressInfo(const ProgressInfo &progress)
|
||||
{
|
||||
const qint64 completedSize = progress.completedSize();
|
||||
const qint64 currentFile = progress.currentFile();
|
||||
const qint64 completedFile = progress.completedFiles();
|
||||
const qint64 totalSize = qMax(completedSize, progress.totalSize());
|
||||
const qint64 totalFileCount = qMax(currentFile, progress.totalFiles());
|
||||
|
||||
setSyncProgress(calculateOverallPercent(totalFileCount, completedFile, totalSize, completedSize));
|
||||
|
||||
if (totalSize > 0) {
|
||||
const auto completedSizeString = Utility::octetsToString(completedSize);
|
||||
const auto totalSizeString = Utility::octetsToString(totalSize);
|
||||
|
||||
if (progress.trustEta()) {
|
||||
setSyncStatusDetailString(
|
||||
tr("%1 of %2 · %3 left")
|
||||
.arg(completedSizeString, totalSizeString)
|
||||
.arg(Utility::durationToDescriptiveString1(progress.totalProgress().estimatedEta)));
|
||||
} else {
|
||||
setSyncStatusDetailString(tr("%1 of %2").arg(completedSizeString, totalSizeString));
|
||||
}
|
||||
}
|
||||
|
||||
if (totalFileCount > 0) {
|
||||
setSyncStatusString(tr("Syncing file %1 of %2").arg(currentFile).arg(totalFileCount));
|
||||
}
|
||||
}
|
||||
|
||||
void SyncStatusSummary::setSyncing(bool value)
|
||||
{
|
||||
if (value == _isSyncing) {
|
||||
return;
|
||||
}
|
||||
|
||||
_isSyncing = value;
|
||||
emit syncingChanged();
|
||||
}
|
||||
|
||||
void SyncStatusSummary::setSyncProgress(double value)
|
||||
{
|
||||
if (_progress == value) {
|
||||
return;
|
||||
}
|
||||
|
||||
_progress = value;
|
||||
emit syncProgressChanged();
|
||||
}
|
||||
|
||||
void SyncStatusSummary::setSyncStatusString(const QString &value)
|
||||
{
|
||||
if (_syncStatusString == value) {
|
||||
return;
|
||||
}
|
||||
|
||||
_syncStatusString = value;
|
||||
emit syncStatusStringChanged();
|
||||
}
|
||||
|
||||
QString SyncStatusSummary::syncStatusString() const
|
||||
{
|
||||
return _syncStatusString;
|
||||
}
|
||||
|
||||
QString SyncStatusSummary::syncStatusDetailString() const
|
||||
{
|
||||
return _syncStatusDetailString;
|
||||
}
|
||||
|
||||
void SyncStatusSummary::setSyncIcon(const QUrl &value)
|
||||
{
|
||||
if (_syncIcon == value) {
|
||||
return;
|
||||
}
|
||||
|
||||
_syncIcon = value;
|
||||
emit syncIconChanged();
|
||||
}
|
||||
|
||||
void SyncStatusSummary::setSyncStatusDetailString(const QString &value)
|
||||
{
|
||||
if (_syncStatusDetailString == value) {
|
||||
return;
|
||||
}
|
||||
|
||||
_syncStatusDetailString = value;
|
||||
emit syncStatusDetailStringChanged();
|
||||
}
|
||||
|
||||
void SyncStatusSummary::connectToFoldersProgress(const Folder::Map &folderMap)
|
||||
{
|
||||
for (const auto &folder : folderMap) {
|
||||
if (folder->accountState() == _accountState.data()) {
|
||||
connect(
|
||||
folder, &Folder::progressInfo, this, &SyncStatusSummary::onFolderProgressInfo, Qt::UniqueConnection);
|
||||
} else {
|
||||
disconnect(folder, &Folder::progressInfo, this, &SyncStatusSummary::onFolderProgressInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
85
src/gui/tray/syncstatussummary.h
Normal file
85
src/gui/tray/syncstatussummary.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright (C) by Felix Weilbach <felix.weilbach@nextcloud.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "accountstate.h"
|
||||
#include "folderman.h"
|
||||
|
||||
#include <theme.h>
|
||||
#include <folder.h>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace OCC {
|
||||
|
||||
class SyncStatusSummary : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(double syncProgress READ syncProgress NOTIFY syncProgressChanged)
|
||||
Q_PROPERTY(QUrl syncIcon READ syncIcon NOTIFY syncIconChanged)
|
||||
Q_PROPERTY(bool syncing READ syncing NOTIFY syncingChanged)
|
||||
Q_PROPERTY(QString syncStatusString READ syncStatusString NOTIFY syncStatusStringChanged)
|
||||
Q_PROPERTY(QString syncStatusDetailString READ syncStatusDetailString NOTIFY syncStatusDetailStringChanged)
|
||||
|
||||
public:
|
||||
explicit SyncStatusSummary(QObject *parent = nullptr);
|
||||
|
||||
double syncProgress() const;
|
||||
QUrl syncIcon() const;
|
||||
bool syncing() const;
|
||||
QString syncStatusString() const;
|
||||
QString syncStatusDetailString() const;
|
||||
|
||||
signals:
|
||||
void syncProgressChanged();
|
||||
void syncIconChanged();
|
||||
void syncingChanged();
|
||||
void syncStatusStringChanged();
|
||||
void syncStatusDetailStringChanged();
|
||||
|
||||
public slots:
|
||||
void load();
|
||||
|
||||
private:
|
||||
void connectToFoldersProgress(const Folder::Map &map);
|
||||
|
||||
void onFolderListChanged(const OCC::Folder::Map &folderMap);
|
||||
void onFolderProgressInfo(const ProgressInfo &progress);
|
||||
void onFolderSyncStateChanged(const Folder *folder);
|
||||
|
||||
void setSyncStateForFolder(const Folder *folder);
|
||||
void markFolderAsError(const Folder *folder);
|
||||
void markFolderAsSuccess(const Folder *folder);
|
||||
bool folderErrors() const;
|
||||
bool folderError(const Folder *folder) const;
|
||||
void clearFolderErrors();
|
||||
|
||||
void setSyncProgress(double value);
|
||||
void setSyncing(bool value);
|
||||
void setSyncStatusString(const QString &value);
|
||||
void setSyncStatusDetailString(const QString &value);
|
||||
void setSyncIcon(const QUrl &value);
|
||||
|
||||
AccountStatePtr _accountState;
|
||||
std::set<QString> _foldersWithErrors;
|
||||
|
||||
QUrl _syncIcon = Theme::instance()->syncStatusOk();
|
||||
double _progress = 1.0;
|
||||
bool _isSyncing = false;
|
||||
QString _syncStatusString = tr("All synced!");
|
||||
QString _syncStatusDetailString;
|
||||
};
|
||||
}
|
|
@ -156,7 +156,37 @@ QUrl Theme::statusAwayImageSource() const
|
|||
|
||||
QUrl Theme::statusInvisibleImageSource() const
|
||||
{
|
||||
return imagePathToUrl(themeImagePath("user-status-invisible", 16));
|
||||
return imagePathToUrl(themeImagePath("user-status-invisible", 64));
|
||||
}
|
||||
|
||||
QUrl Theme::syncStatusOk() const
|
||||
{
|
||||
return imagePathToUrl(themeImagePath("state-ok", 16));
|
||||
}
|
||||
|
||||
QUrl Theme::syncStatusError() const
|
||||
{
|
||||
return imagePathToUrl(themeImagePath("state-error", 16));
|
||||
}
|
||||
|
||||
QUrl Theme::syncStatusRunning() const
|
||||
{
|
||||
return imagePathToUrl(themeImagePath("state-sync", 16));
|
||||
}
|
||||
|
||||
QUrl Theme::syncStatusPause() const
|
||||
{
|
||||
return imagePathToUrl(themeImagePath("state-pause", 16));
|
||||
}
|
||||
|
||||
QUrl Theme::syncStatusWarning() const
|
||||
{
|
||||
return imagePathToUrl(themeImagePath("state-warning", 16));
|
||||
}
|
||||
|
||||
QUrl Theme::folderOffline() const
|
||||
{
|
||||
return imagePathToUrl(themeImagePath("state-offline"));
|
||||
}
|
||||
|
||||
QString Theme::version() const
|
||||
|
|
|
@ -151,6 +151,18 @@ public:
|
|||
*/
|
||||
QUrl statusInvisibleImageSource() const;
|
||||
|
||||
QUrl syncStatusOk() const;
|
||||
|
||||
QUrl syncStatusError() const;
|
||||
|
||||
QUrl syncStatusRunning() const;
|
||||
|
||||
QUrl syncStatusPause() const;
|
||||
|
||||
QUrl syncStatusWarning() const;
|
||||
|
||||
QUrl folderOffline() const;
|
||||
|
||||
/**
|
||||
* @brief configFileName
|
||||
* @return the name of the config file.
|
||||
|
|
Loading…
Reference in a new issue