Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/desktop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--resources.qrc1
-rw-r--r--src/gui/CMakeLists.txt1
-rw-r--r--src/gui/main.cpp2
-rw-r--r--src/gui/tray/ActivityItem.qml8
-rw-r--r--src/gui/tray/SyncStatus.qml89
-rw-r--r--src/gui/tray/UserModel.cpp5
-rw-r--r--src/gui/tray/UserModel.h2
-rw-r--r--src/gui/tray/Window.qml36
-rw-r--r--src/gui/tray/syncstatussummary.cpp314
-rw-r--r--src/gui/tray/syncstatussummary.h85
-rw-r--r--src/libsync/theme.cpp32
-rw-r--r--src/libsync/theme.h12
12 files changed, 568 insertions, 19 deletions
diff --git a/resources.qrc b/resources.qrc
index 0b95c4274..134c11cc9 100644
--- a/resources.qrc
+++ b/resources.qrc
@@ -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>
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt
index 59713e6d6..bbc666374 100644
--- a/src/gui/CMakeLists.txt
+++ b/src/gui/CMakeLists.txt
@@ -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
diff --git a/src/gui/main.cpp b/src/gui/main.cpp
index 71e53abbe..47421220b 100644
--- a/src/gui/main.cpp
+++ b/src/gui/main.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");
diff --git a/src/gui/tray/ActivityItem.qml b/src/gui/tray/ActivityItem.qml
index e84976e62..ed85ed9ea 100644
--- a/src/gui/tray/ActivityItem.qml
+++ b/src/gui/tray/ActivityItem.qml
@@ -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
diff --git a/src/gui/tray/SyncStatus.qml b/src/gui/tray/SyncStatus.qml
new file mode 100644
index 000000000..7bf9a2d55
--- /dev/null
+++ b/src/gui/tray/SyncStatus.qml
@@ -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
+ }
+ }
+}
diff --git a/src/gui/tray/UserModel.cpp b/src/gui/tray/UserModel.cpp
index 56a387aa5..c9e3d92b5 100644
--- a/src/gui/tray/UserModel.cpp
+++ b/src/gui/tray/UserModel.cpp
@@ -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;
diff --git a/src/gui/tray/UserModel.h b/src/gui/tray/UserModel.h
index c11b2c476..eb3be9136 100644
--- a/src/gui/tray/UserModel.h
+++ b/src/gui/tray/UserModel.h
@@ -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;
diff --git a/src/gui/tray/Window.qml b/src/gui/tray/Window.qml
index 57a019341..5bda9242d 100644
--- a/src/gui/tray/Window.qml
+++ b/src/gui/tray/Window.qml
@@ -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
diff --git a/src/gui/tray/syncstatussummary.cpp b/src/gui/tray/syncstatussummary.cpp
new file mode 100644
index 000000000..a66a5d9d9
--- /dev/null
+++ b/src/gui/tray/syncstatussummary.cpp
@@ -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);
+ }
+ }
+}
+}
diff --git a/src/gui/tray/syncstatussummary.h b/src/gui/tray/syncstatussummary.h
new file mode 100644
index 000000000..f4abec198
--- /dev/null
+++ b/src/gui/tray/syncstatussummary.h
@@ -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;
+};
+}
diff --git a/src/libsync/theme.cpp b/src/libsync/theme.cpp
index c4e6e83b7..699951130 100644
--- a/src/libsync/theme.cpp
+++ b/src/libsync/theme.cpp
@@ -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
diff --git a/src/libsync/theme.h b/src/libsync/theme.h
index c0e2433e5..37e3c52c1 100644
--- a/src/libsync/theme.h
+++ b/src/libsync/theme.h
@@ -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.