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
path: root/src
diff options
context:
space:
mode:
authorDominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>2020-01-03 15:09:29 +0300
committerDominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>2020-01-03 15:09:29 +0300
commitb32310b8a6b298e7bc96df14205e00d8bd1f8c00 (patch)
tree443eb2248f892062f2df438934af5c4ce9c7b859 /src
parent556a1a5ef2b132e39bd199b96040f41e84286928 (diff)
Gigantic ton of changes and deletions: ActivityListModel, tray GUI, Account logic.
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
Diffstat (limited to 'src')
-rw-r--r--src/gui/CMakeLists.txt10
-rw-r--r--src/gui/accountsettings.ui2
-rw-r--r--src/gui/accountstate.cpp25
-rw-r--r--src/gui/accountstate.h4
-rw-r--r--src/gui/activityitemdelegate.cpp407
-rw-r--r--src/gui/activityitemdelegate.h94
-rw-r--r--src/gui/activitywidget.cpp653
-rw-r--r--src/gui/activitywidget.h165
-rw-r--r--src/gui/activitywidget.ui98
-rw-r--r--src/gui/generalsettings.ui2
-rw-r--r--src/gui/networksettings.ui2
-rw-r--r--src/gui/owncloudgui.cpp11
-rw-r--r--src/gui/servernotificationhandler.cpp165
-rw-r--r--src/gui/servernotificationhandler.h50
-rw-r--r--src/gui/settingsdialog.cpp72
-rw-r--r--src/gui/settingsdialog.h6
-rw-r--r--src/gui/settingsdialog.ui2
-rw-r--r--src/gui/systray.cpp17
-rw-r--r--src/gui/systray.h1
-rw-r--r--src/gui/tray/ActivityData.cpp (renamed from src/gui/activitydata.cpp)0
-rw-r--r--src/gui/tray/ActivityData.h (renamed from src/gui/activitydata.h)0
-rw-r--r--src/gui/tray/ActivityListModel.cpp (renamed from src/gui/activitylistmodel.cpp)37
-rw-r--r--src/gui/tray/ActivityListModel.h (renamed from src/gui/activitylistmodel.h)17
-rw-r--r--src/gui/tray/UserLine.qml7
-rw-r--r--src/gui/tray/UserModel.cpp99
-rw-r--r--src/gui/tray/UserModel.h42
-rw-r--r--src/gui/tray/window.qml26
-rw-r--r--src/libsync/capabilities.cpp3
28 files changed, 139 insertions, 1878 deletions
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt
index 9b0455a6b..af364ca4e 100644
--- a/src/gui/CMakeLists.txt
+++ b/src/gui/CMakeLists.txt
@@ -24,7 +24,6 @@ set(client_UI_SRCS
ignorelisteditor.ui
ignorelisttablewidget.ui
networksettings.ui
- activitywidget.ui
synclogdialog.ui
settingsdialog.ui
sharedialog.ui
@@ -35,7 +34,7 @@ set(client_UI_SRCS
addcertificatedialog.ui
proxyauthdialog.ui
mnemonicdialog.ui
- tray/window.qml
+ tray/Window.qml
tray/UserLine.qml
wizard/flow2authwidget.ui
wizard/owncloudadvancedsetuppage.ui
@@ -75,10 +74,6 @@ set(client_SRCS
openfilemanager.cpp
owncloudgui.cpp
owncloudsetupwizard.cpp
- activitydata.cpp
- activitylistmodel.cpp
- activitywidget.cpp
- activityitemdelegate.cpp
selectivesyncdialog.cpp
settingsdialog.cpp
sharedialog.cpp
@@ -101,12 +96,13 @@ set(client_SRCS
synclogdialog.cpp
tooltipupdater.cpp
notificationconfirmjob.cpp
- servernotificationhandler.cpp
guiutility.cpp
elidedlabel.cpp
headerbanner.cpp
iconjob.cpp
remotewipe.cpp
+ tray/ActivityData.cpp
+ tray/ActivityListModel.cpp
tray/UserModel.cpp
creds/credentialsfactory.cpp
creds/httpcredentialsgui.cpp
diff --git a/src/gui/accountsettings.ui b/src/gui/accountsettings.ui
index f52adf4c7..6249018bd 100644
--- a/src/gui/accountsettings.ui
+++ b/src/gui/accountsettings.ui
@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
- <width>582</width>
+ <width>516</width>
<height>557</height>
</rect>
</property>
diff --git a/src/gui/accountstate.cpp b/src/gui/accountstate.cpp
index 7893a7a3b..9d2fa1830 100644
--- a/src/gui/accountstate.cpp
+++ b/src/gui/accountstate.cpp
@@ -74,6 +74,11 @@ AccountPtr AccountState::account() const
return _account;
}
+bool AccountState::hasTalk() const
+{
+ return _hasTalk;
+}
+
AccountState::ConnectionStatus AccountState::connectionStatus() const
{
return _connectionStatus;
@@ -89,6 +94,23 @@ AccountState::State AccountState::state() const
return _state;
}
+void AccountState::setTalkCapability()
+{
+ QNetworkAccessManager *manager = new QNetworkAccessManager(this);
+ connect(manager, &QNetworkAccessManager::finished,
+ this, [=](QNetworkReply *reply) {
+ if (reply->error()) {
+ return;
+ }
+ //TODO: This is **** dirty, but atm I don't see a capability-way to determine talk integration
+ _hasTalk = (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 303) ? true : false;
+ });
+ QNetworkRequest request;
+ QString url = this->account()->url().toString() + "/apps/spreed";
+ request.setUrl(QUrl(url));
+ manager->get(request);
+}
+
void AccountState::setState(State state)
{
if (_state != state) {
@@ -267,7 +289,7 @@ void AccountState::slotConnectionValidatorResult(ConnectionValidator::Status sta
// Come online gradually from 503 or maintenance mode
if (status == ConnectionValidator::Connected
&& (_connectionStatus == ConnectionValidator::ServiceUnavailable
- || _connectionStatus == ConnectionValidator::MaintenanceMode)) {
+ || _connectionStatus == ConnectionValidator::MaintenanceMode)) {
if (!_timeSinceMaintenanceOver.isValid()) {
qCInfo(lcAccountState) << "AccountState reconnection: delaying for"
<< _maintenanceToConnectedDelay << "ms";
@@ -293,6 +315,7 @@ void AccountState::slotConnectionValidatorResult(ConnectionValidator::Status sta
case ConnectionValidator::Connected:
if (_state != Connected) {
setState(Connected);
+ setTalkCapability();
}
break;
case ConnectionValidator::Undefined:
diff --git a/src/gui/accountstate.h b/src/gui/accountstate.h
index 6ed9aa265..7633bd78d 100644
--- a/src/gui/accountstate.h
+++ b/src/gui/accountstate.h
@@ -101,6 +101,8 @@ public:
bool isSignedOut() const;
+ bool hasTalk() const;
+
/** A user-triggered sign out which disconnects, stops syncs
* for the account and forgets the password. */
void signOutByUi();
@@ -161,6 +163,7 @@ public slots:
private:
void setState(State state);
+ void setTalkCapability();
signals:
void stateChanged(int state);
@@ -182,6 +185,7 @@ private:
ConnectionStatus _connectionStatus;
QStringList _connectionErrors;
bool _waitingForNewCredentials;
+ bool _hasTalk;
QElapsedTimer _timeSinceLastETagCheck;
QPointer<ConnectionValidator> _connectionValidator;
QByteArray _notificationsEtagResponseHeader;
diff --git a/src/gui/activityitemdelegate.cpp b/src/gui/activityitemdelegate.cpp
deleted file mode 100644
index 2b4231e07..000000000
--- a/src/gui/activityitemdelegate.cpp
+++ /dev/null
@@ -1,407 +0,0 @@
-/*
- * Copyright (C) by Klaas Freitag <freitag@owncloud.com>
- * Copyright (C) by Olivier Goffart <ogoffart@woboq.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 "activityitemdelegate.h"
-#include "activitylistmodel.h"
-#include "folderstatusmodel.h"
-#include "folderman.h"
-#include "accountstate.h"
-#include "activitydata.h"
-#include <theme.h>
-#include <account.h>
-
-#include <QFileIconProvider>
-#include <QPainter>
-#include <QApplication>
-
-#define FIXME_USE_HIGH_DPI_RATIO
-#ifdef FIXME_USE_HIGH_DPI_RATIO
- // FIXME: Find a better way to calculate the text width on high-dpi displays (Retina).
- #include <QDesktopWidget>
-#endif
-
-#define HASQT5_11 (QT_VERSION >= QT_VERSION_CHECK(5,11,0))
-
-namespace OCC {
-
-int ActivityItemDelegate::_iconHeight = 0;
-int ActivityItemDelegate::_margin = 0;
-int ActivityItemDelegate::_primaryButtonWidth = 0;
-int ActivityItemDelegate::_secondaryButtonWidth = 0;
-int ActivityItemDelegate::_spaceBetweenButtons = 0;
-int ActivityItemDelegate::_timeWidth = 0;
-int ActivityItemDelegate::_buttonHeight = 0;
-const QString ActivityItemDelegate::_remote_share("remote_share");
-const QString ActivityItemDelegate::_call("call");
-
-ActivityItemDelegate::ActivityItemDelegate()
- : QStyledItemDelegate()
-{
- customizeStyle();
-}
-
-int ActivityItemDelegate::iconHeight()
-{
- if (_iconHeight == 0) {
- QStyleOptionViewItem option;
- QFont font = option.font;
-
- QFontMetrics fm(font);
-
- _iconHeight = qRound(fm.height() / 5.0 * 8.0);
- }
- return _iconHeight;
-}
-
-int ActivityItemDelegate::rowHeight()
-{
- if (_margin == 0) {
- QStyleOptionViewItem opt;
-
- QFont f = opt.font;
- QFontMetrics fm(f);
-
- _margin = fm.height() / 2;
-
-#if defined(Q_OS_WIN)
- _margin += 5;
-#endif
- }
- return iconHeight() + 5 * _margin;
-}
-
-QSize ActivityItemDelegate::sizeHint(const QStyleOptionViewItem &option,
- const QModelIndex & /* index */) const
-{
- QFont font = option.font;
-
- return QSize(0, rowHeight());
-}
-
-void ActivityItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
- const QModelIndex &index) const
-{
- QStyledItemDelegate::paint(painter, option, index);
- QFont font = option.font;
- QFontMetrics fm(font);
- int margin = fm.height() / 2.5;
- painter->save();
- int iconSize = 16;
- int iconOffset = qRound(fm.height() / 4.0 * 7.0);
- int offset = 4;
- const bool isSelected = (option.state & QStyle::State_Selected);
-#ifdef FIXME_USE_HIGH_DPI_RATIO
- // FIXME: Find a better way to calculate the text width on high-dpi displays (Retina).
- const int device_pixel_ration = QApplication::desktop()->devicePixelRatio();
- int pixel_ratio = (device_pixel_ration > 1 ? device_pixel_ration : 1);
-#endif
-
- // get the data
- Activity::Type activityType = qvariant_cast<Activity::Type>(index.data(ActionRole));
- QIcon actionIcon;
- const ActivityListModel::ActionIcon icn = qvariant_cast<ActivityListModel::ActionIcon>(index.data(ActionIconRole));
- switch(icn.iconType) {
- case ActivityListModel::ActivityIconType::iconUseCached: actionIcon = icn.cachedIcon; break;
- case ActivityListModel::ActivityIconType::iconActivity: actionIcon = (isSelected ? _iconActivity_sel : _iconActivity); break;
- case ActivityListModel::ActivityIconType::iconBell: actionIcon = (isSelected ? _iconBell_sel : _iconBell); break;
- case ActivityListModel::ActivityIconType::iconStateError: actionIcon = _iconStateError; break;
- case ActivityListModel::ActivityIconType::iconStateWarning: actionIcon = _iconStateWarning; break;
- case ActivityListModel::ActivityIconType::iconStateInfo: actionIcon = _iconStateInfo; break;
- case ActivityListModel::ActivityIconType::iconStateSync: actionIcon = _iconStateSync; break;
- }
- QString objectType = qvariant_cast<QString>(index.data(ObjectTypeRole));
- QString actionText = qvariant_cast<QString>(index.data(ActionTextRole));
- QString messageText = qvariant_cast<QString>(index.data(MessageRole));
- QList<QVariant> customList = index.data(ActionsLinksRole).toList();
- QString timeText = qvariant_cast<QString>(index.data(PointInTimeRole));
- bool accountOnline = qvariant_cast<bool>(index.data(AccountConnectedRole));
-
- // activity/notification icons
- QRect actionIconRect = option.rect;
- actionIconRect.setLeft(option.rect.left() + iconOffset/3);
- actionIconRect.setRight(option.rect.left() + iconOffset);
- actionIconRect.setTop(option.rect.top() + qRound((option.rect.height() - 16)/3.0));
-
- // subject text rect
- QRect actionTextBox = actionIconRect;
-#if (HASQT5_11)
- int actionTextBoxWidth = fm.horizontalAdvance(actionText);
-#else
- int actionTextBoxWidth = fm.width(actionText);
-#endif
- actionTextBox.setTop(option.rect.top() + margin + offset/2);
- actionTextBox.setHeight(fm.height());
- actionTextBox.setLeft(actionIconRect.right() + margin);
-#ifdef FIXME_USE_HIGH_DPI_RATIO
- // FIXME: Find a better way to calculate the text width on high-dpi displays (Retina).
- actionTextBoxWidth *= pixel_ratio;
-#endif
- actionTextBox.setRight(actionTextBox.left() + actionTextBoxWidth + margin);
-
- // message text rect
- QRect messageTextBox = actionTextBox;
-#if (HASQT5_11)
- int messageTextWidth = fm.horizontalAdvance(messageText);
-#else
- int messageTextWidth = fm.width(messageText);
-#endif
- int messageTextTop = option.rect.top() + fm.height() + margin;
- if(actionText.isEmpty()) messageTextTop = option.rect.top() + margin + offset/2;
- messageTextBox.setTop(messageTextTop);
- messageTextBox.setHeight(fm.height());
- messageTextBox.setBottom(messageTextBox.top() + fm.height());
- messageTextBox.setRight(messageTextBox.left() + messageTextWidth + margin);
- if(messageText.isEmpty()){
- messageTextBox.setHeight(0);
- messageTextBox.setBottom(messageTextBox.top());
- }
-
- // time box rect
- QRect timeBox = messageTextBox;
-#if (HASQT5_11)
- int timeTextWidth = fm.horizontalAdvance(timeText);
-#else
- int timeTextWidth = fm.width(timeText);
-#endif
- int timeTop = option.rect.top() + fm.height() + fm.height() + margin + offset/2;
- if(messageText.isEmpty() || actionText.isEmpty())
- timeTop = option.rect.top() + fm.height() + margin;
- timeBox.setTop(timeTop);
- timeBox.setHeight(fm.height());
- timeBox.setBottom(timeBox.top() + fm.height());
-#ifdef FIXME_USE_HIGH_DPI_RATIO
- // FIXME: Find a better way to calculate the text width on high-dpi displays (Retina).
- timeTextWidth *= pixel_ratio;
-#endif
- timeBox.setRight(timeBox.left() + timeTextWidth + margin);
-
- // buttons - default values
- int rightMargin = margin;
- int leftMargin = margin * offset;
- int top = option.rect.top() + margin;
- int buttonSize = option.rect.height()/2;
- int right = option.rect.right() - rightMargin;
- int left = right - buttonSize;
-
- QStyleOptionButton secondaryButton;
- secondaryButton.rect = option.rect;
- secondaryButton.features |= QStyleOptionButton::Flat;
- secondaryButton.state |= QStyle::State_None;
- secondaryButton.rect.setLeft(left);
- secondaryButton.rect.setRight(right);
- secondaryButton.rect.setTop(top + margin);
- secondaryButton.rect.setHeight(iconSize);
-
- QStyleOptionButton primaryButton;
- primaryButton.rect = option.rect;
- primaryButton.features |= QStyleOptionButton::DefaultButton;
- primaryButton.state |= QStyle::State_Raised;
- primaryButton.rect.setTop(top);
- primaryButton.rect.setHeight(buttonSize);
-
- right = secondaryButton.rect.left() - rightMargin;
- left = secondaryButton.rect.left() - leftMargin;
-
- primaryButton.rect.setRight(right);
-
- if(activityType == Activity::Type::NotificationType){
-
- // Secondary will be 'Dismiss' or '...' multiple options button
- secondaryButton.icon = (isSelected ? _iconClose_sel : _iconClose);
- if(customList.size() > 1)
- secondaryButton.icon = (isSelected ? _iconMore_sel : _iconMore);
- secondaryButton.iconSize = QSize(iconSize, iconSize);
-
- // Primary button will be 'More Information' or 'Accept'
- primaryButton.text = tr("More information");
- if(objectType == _remote_share) primaryButton.text = tr("Accept");
- if(objectType == _call) primaryButton.text = tr("Join");
-
-#if (HASQT5_11)
- primaryButton.rect.setLeft(left - margin * 2 - fm.horizontalAdvance(primaryButton.text));
-#else
- primaryButton.rect.setLeft(left - margin * 2 - fm.width(primaryButton.text));
-#endif
-
- // save info to be able to filter mouse clicks
- _buttonHeight = buttonSize;
- _primaryButtonWidth = primaryButton.rect.size().width();
- _secondaryButtonWidth = secondaryButton.rect.size().width();
- _spaceBetweenButtons = secondaryButton.rect.left() - primaryButton.rect.right();
-
- } else if(activityType == Activity::SyncResultType){
-
- // Secondary will be 'open file manager' with the folder icon
- secondaryButton.icon = _iconFolder;
- secondaryButton.iconSize = QSize(iconSize, iconSize);
-
- // Primary button will be 'open browser'
- primaryButton.text = tr("Open Browser");
-
-#if (HASQT5_11)
- primaryButton.rect.setLeft(left - margin * 2 - fm.horizontalAdvance(primaryButton.text));
-#else
- primaryButton.rect.setLeft(left - margin * 2 - fm.width(primaryButton.text));
-#endif
-
- // save info to be able to filter mouse clicks
- _buttonHeight = buttonSize;
- _primaryButtonWidth = primaryButton.rect.size().width();
- _secondaryButtonWidth = secondaryButton.rect.size().width();
- _spaceBetweenButtons = secondaryButton.rect.left() - primaryButton.rect.right();
-
- } else if(activityType == Activity::SyncFileItemType){
-
- // Secondary will be 'open file manager' with the folder icon
- secondaryButton.icon = _iconFolder;
- secondaryButton.iconSize = QSize(iconSize, iconSize);
-
- // No primary button on this case
- // Whatever error we have at this case it is local, there is no point on opening the browser
- _primaryButtonWidth = 0;
- _secondaryButtonWidth = secondaryButton.rect.size().width();
- _spaceBetweenButtons = secondaryButton.rect.left() - primaryButton.rect.right();
-
- } else {
- _spaceBetweenButtons = leftMargin;
- _primaryButtonWidth = 0;
- _secondaryButtonWidth = 0;
- }
-
- // draw the icon
- QPixmap pm = actionIcon.pixmap(iconSize, iconSize, QIcon::Normal);
- painter->drawPixmap(QPoint(actionIconRect.left(), actionIconRect.top()), pm);
-
- // change pen color if use is not online
- QPalette p = option.palette;
- if(!accountOnline)
- p.setCurrentColorGroup(QPalette::Disabled);
-
- // change pen color if the line is selected
- if (isSelected)
- painter->setPen(p.color(QPalette::HighlightedText));
- else
- painter->setPen(p.color(QPalette::Text));
-
- // calculate space for text - use the max possible before using the elipses
- int spaceLeftForText = option.rect.width() - (actionIconRect.width() + margin + rightMargin + leftMargin) -
- (_primaryButtonWidth + _secondaryButtonWidth + _spaceBetweenButtons);
-
- // draw the subject
- const QString elidedAction = fm.elidedText(actionText, Qt::ElideRight, spaceLeftForText);
- painter->drawText(actionTextBox, elidedAction);
-
- // draw the buttons
- if(activityType == Activity::Type::NotificationType || activityType == Activity::Type::SyncResultType) {
- primaryButton.palette = p;
- if (isSelected)
- primaryButton.palette.setColor(QPalette::ButtonText, p.color(QPalette::HighlightedText));
- else
- primaryButton.palette.setColor(QPalette::ButtonText, p.color(QPalette::Text));
-
- QApplication::style()->drawControl(QStyle::CE_PushButton, &primaryButton, painter);
- }
-
- // Since they are errors on local syncing, there is nothing to do in the server
- if(activityType != Activity::Type::ActivityType)
- QApplication::style()->drawControl(QStyle::CE_PushButton, &secondaryButton, painter);
-
- // draw the message
- // change pen color for the message
- if(!messageText.isEmpty()){
- const QString elidedMessage = fm.elidedText(messageText, Qt::ElideRight, spaceLeftForText);
- painter->drawText(messageTextBox, elidedMessage);
- }
-
- // change pen color for the time
- if (isSelected)
- painter->setPen(p.color(QPalette::Disabled, QPalette::HighlightedText));
- else
- painter->setPen(p.color(QPalette::Disabled, QPalette::Text));
-
- // draw the time
- const QString elidedTime = fm.elidedText(timeText, Qt::ElideRight, spaceLeftForText);
- painter->drawText(timeBox, elidedTime);
-
- painter->restore();
-}
-
-bool ActivityItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
- const QStyleOptionViewItem &option, const QModelIndex &index)
-{
- Activity::Type activityType = qvariant_cast<Activity::Type>(index.data(ActionRole));
- if(activityType != Activity::Type::ActivityType){
- if (event->type() == QEvent::MouseButtonRelease){
- QMouseEvent *mouseEvent = (QMouseEvent*)event;
- if(mouseEvent){
- int mouseEventX = mouseEvent->x();
- int mouseEventY = mouseEvent->y();
- int buttonsWidth = _primaryButtonWidth + _spaceBetweenButtons + _secondaryButtonWidth;
- int x = option.rect.left() + option.rect.width() - buttonsWidth - _timeWidth;
- int y = option.rect.top();
-
- // clickable area for ...
- if (mouseEventX > x && mouseEventX < x + buttonsWidth){
- if(mouseEventY > y && mouseEventY < y + _buttonHeight){
-
- // ...primary button ('more information' or 'accept' on notifications or 'open browser' on errors)
- if (mouseEventX > x && mouseEventX < x + _primaryButtonWidth){
- emit primaryButtonClickedOnItemView(index);
-
- // ...secondary button ('dismiss' on notifications or 'open file manager' on errors)
- } else {
- x += _primaryButtonWidth + _spaceBetweenButtons;
- if (mouseEventX > x && mouseEventX < x + _secondaryButtonWidth)
- emit secondaryButtonClickedOnItemView(index);
- }
- }
- }
- }
- }
- }
-
- return QStyledItemDelegate::editorEvent(event, model, option, index);
-}
-
-void ActivityItemDelegate::slotStyleChanged()
-{
- customizeStyle();
-}
-
-void ActivityItemDelegate::customizeStyle()
-{
- QPalette pal;
- pal.setColor(QPalette::Base, QColor(0,0,0)); // use dark background colour to invert icons
-
- _iconClose = Theme::createColorAwareIcon(QLatin1String(":/client/resources/close.svg"));
- _iconClose_sel = Theme::createColorAwareIcon(QLatin1String(":/client/resources/close.svg"), pal);
- _iconMore = Theme::createColorAwareIcon(QLatin1String(":/client/resources/more.svg"));
- _iconMore_sel = Theme::createColorAwareIcon(QLatin1String(":/client/resources/more.svg"), pal);
-
- _iconFolder = QIcon(QLatin1String(":/client/resources/folder.svg"));
-
- _iconActivity = Theme::createColorAwareIcon(QLatin1String(":/client/resources/activity.png"));
- _iconActivity_sel = Theme::createColorAwareIcon(QLatin1String(":/client/resources/activity.png"), pal);
- _iconBell = Theme::createColorAwareIcon(QLatin1String(":/client/resources/bell.svg"));
- _iconBell_sel = Theme::createColorAwareIcon(QLatin1String(":/client/resources/bell.svg"), pal);
-
- _iconStateError = QIcon(QLatin1String(":/client/resources/state-error.svg"));
- _iconStateWarning = QIcon(QLatin1String(":/client/resources/state-warning.svg"));
- _iconStateInfo = QIcon(QLatin1String(":/client/resources/state-info.svg"));
- _iconStateSync = QIcon(QLatin1String(":/client/resources/state-sync.svg"));
-}
-
-} // namespace OCC
diff --git a/src/gui/activityitemdelegate.h b/src/gui/activityitemdelegate.h
deleted file mode 100644
index 908889eee..000000000
--- a/src/gui/activityitemdelegate.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) by Klaas Freitag <freitag@kde.org>
- * Copyright (C) by Olivier Goffart <ogoffart@woboq.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 <QStyledItemDelegate>
-#include <QMouseEvent>
-
-class QMouseEvent;
-
-namespace OCC {
-
-/**
- * @brief The ActivityItemDelegate class
- * @ingroup gui
- */
-class ActivityItemDelegate : public QStyledItemDelegate
-{
- Q_OBJECT
-public:
- enum datarole { ActionIconRole = Qt::UserRole + 1,
- UserIconRole,
- AccountRole,
- ObjectTypeRole,
- ActionsLinksRole,
- ActionTextRole,
- ActionRole,
- MessageRole,
- PathRole,
- LinkRole,
- PointInTimeRole,
- AccountConnectedRole,
- SyncFileStatusRole };
-
- ActivityItemDelegate();
-
- void paint(QPainter *, const QStyleOptionViewItem &, const QModelIndex &) const override;
- QSize sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const override;
- bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option,
- const QModelIndex &index) override;
-
- static int rowHeight();
- static int iconHeight();
-
-public slots:
- void slotStyleChanged();
-
-signals:
- void primaryButtonClickedOnItemView(const QModelIndex &index);
- void secondaryButtonClickedOnItemView(const QModelIndex &index);
-
-private:
- void customizeStyle();
-
- static int _margin;
- static int _iconHeight;
- static int _primaryButtonWidth;
- static int _secondaryButtonWidth;
- static int _spaceBetweenButtons;
- static int _timeWidth;
- static int _buttonHeight;
- static const QString _remote_share;
- static const QString _call;
-
- QIcon _iconClose;
- QIcon _iconClose_sel;
- QIcon _iconMore;
- QIcon _iconMore_sel;
-
- QIcon _iconFolder;
-
- QIcon _iconActivity;
- QIcon _iconActivity_sel;
- QIcon _iconBell;
- QIcon _iconBell_sel;
-
- QIcon _iconStateError;
- QIcon _iconStateWarning;
- QIcon _iconStateInfo;
- QIcon _iconStateSync;
-};
-
-} // namespace OCC
diff --git a/src/gui/activitywidget.cpp b/src/gui/activitywidget.cpp
deleted file mode 100644
index 469b0d14e..000000000
--- a/src/gui/activitywidget.cpp
+++ /dev/null
@@ -1,653 +0,0 @@
-/*
- * Copyright (C) by Klaas Freitag <freitag@owncloud.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 <QtGui>
-#include <QtWidgets>
-
-#include "activitylistmodel.h"
-#include "activitywidget.h"
-#include "syncresult.h"
-#include "logger.h"
-#include "theme.h"
-#include "folderman.h"
-#include "syncfileitem.h"
-#include "folder.h"
-#include "openfilemanager.h"
-#include "owncloudpropagator.h"
-#include "account.h"
-#include "accountstate.h"
-#include "accountmanager.h"
-#include "activityitemdelegate.h"
-#include "QProgressIndicator.h"
-#include "notificationconfirmjob.h"
-#include "servernotificationhandler.h"
-#include "theme.h"
-#include "ocsjob.h"
-#include "configfile.h"
-#include "guiutility.h"
-#include "socketapi.h"
-#include "ui_activitywidget.h"
-#include "syncengine.h"
-
-#include <climits>
-
-// time span in milliseconds which has to be between two
-// refreshes of the notifications
-#define NOTIFICATION_REQUEST_FREE_PERIOD 15000
-
-namespace OCC {
-
-ActivityWidget::ActivityWidget(AccountState *accountState, QWidget *parent)
- : QWidget(parent)
- , _ui(new Ui::ActivityWidget)
- , _notificationRequestsRunning(0)
- , _accountState(accountState)
- , _accept(tr("Accept"))
- , _remote_share("remote_share")
-{
- _ui->setupUi(this);
-
-// Adjust copyToClipboard() when making changes here!
-#if defined(Q_OS_MAC)
- _ui->_activityList->setMinimumWidth(400);
-#endif
-
- _model = new ActivityListModel(accountState, this);
- ActivityItemDelegate *delegate = new ActivityItemDelegate;
- delegate->setParent(this);
- _ui->_activityList->setItemDelegate(delegate);
- _ui->_activityList->setAlternatingRowColors(true);
- _ui->_activityList->setModel(_model);
-
- showLabels();
-
- connect(_model, &ActivityListModel::activityJobStatusCode,
- this, &ActivityWidget::slotAccountActivityStatus);
-
- connect(_model, &QAbstractItemModel::rowsInserted, this, &ActivityWidget::rowsInserted);
-
- connect(delegate, &ActivityItemDelegate::primaryButtonClickedOnItemView, this, &ActivityWidget::slotPrimaryButtonClickedOnListView);
- connect(delegate, &ActivityItemDelegate::secondaryButtonClickedOnItemView, this, &ActivityWidget::slotSecondaryButtonClickedOnListView);
- connect(_ui->_activityList, &QListView::activated, this, &ActivityWidget::slotOpenFile);
-
- connect(ProgressDispatcher::instance(), &ProgressDispatcher::progressInfo,
- this, &ActivityWidget::slotProgressInfo);
- connect(ProgressDispatcher::instance(), &ProgressDispatcher::itemCompleted,
- this, &ActivityWidget::slotItemCompleted);
- connect(ProgressDispatcher::instance(), &ProgressDispatcher::syncError,
- this, &ActivityWidget::addError);
-
- _removeTimer.setInterval(1000);
-
- // Connect styleChanged events to our widgets, so they can adapt (Dark-/Light-Mode switching)
- connect(this, &ActivityWidget::styleChanged, delegate, &ActivityItemDelegate::slotStyleChanged);
-}
-
-ActivityWidget::~ActivityWidget()
-{
- delete _ui;
-}
-
-void ActivityWidget::slotProgressInfo(const QString &folder, const ProgressInfo &progress)
-{
- if (progress.status() == ProgressInfo::Reconcile) {
- // Wipe all non-persistent entries - as well as the persistent ones
- // in cases where a local discovery was done.
- auto f = FolderMan::instance()->folder(folder);
- if (!f)
- return;
- const auto &engine = f->syncEngine();
- const auto style = engine.lastLocalDiscoveryStyle();
- foreach (Activity activity, _model->errorsList()) {
- if (activity._folder != folder){
- continue;
- }
-
- if (style == LocalDiscoveryStyle::FilesystemOnly){
- _model->removeActivityFromActivityList(activity);
- continue;
- }
-
- if(activity._status == SyncFileItem::Conflict && !QFileInfo(f->path() + activity._file).exists()){
- _model->removeActivityFromActivityList(activity);
- continue;
- }
-
- if(activity._status == SyncFileItem::FileLocked && !QFileInfo(f->path() + activity._file).exists()){
- _model->removeActivityFromActivityList(activity);
- continue;
- }
-
-
- if(activity._status == SyncFileItem::FileIgnored && !QFileInfo(f->path() + activity._file).exists()) {
- _model->removeActivityFromActivityList(activity);
- continue;
- }
-
-
- if(!QFileInfo(f->path() + activity._file).exists()){
- _model->removeActivityFromActivityList(activity);
- continue;
- }
-
- auto path = QFileInfo(activity._file).dir().path().toUtf8();
- if (path == ".")
- path.clear();
-
- if(engine.shouldDiscoverLocally(path))
- _model->removeActivityFromActivityList(activity);
- }
-
- }
-
- if (progress.status() == ProgressInfo::Done) {
- // We keep track very well of pending conflicts.
- // Inform other components about them.
- QStringList conflicts;
- foreach (Activity activity, _model->errorsList()) {
- if (activity._folder == folder
- && activity._status == SyncFileItem::Conflict) {
- conflicts.append(activity._file);
- }
- }
-
- emit ProgressDispatcher::instance()->folderConflicts(folder, conflicts);
- }
-}
-
-void ActivityWidget::slotItemCompleted(const QString &folder, const SyncFileItemPtr &item){
- auto folderInstance = FolderMan::instance()->folder(folder);
-
- if (!folderInstance)
- return;
-
- // check if we are adding it to the right account and if it is useful information (protocol errors)
- if(folderInstance->accountState() == _accountState){
- qCWarning(lcActivity) << "Item " << item->_file << " retrieved resulted in " << item->_errorString;
-
- Activity activity;
- activity._type = Activity::SyncFileItemType; //client activity
- activity._status = item->_status;
- activity._dateTime = QDateTime::currentDateTime();
- activity._message = item->_originalFile;
- activity._link = folderInstance->accountState()->account()->url();
- activity._accName = folderInstance->accountState()->account()->displayName();
- activity._file = item->_file;
- activity._folder = folder;
-
- if(item->_status == SyncFileItem::NoStatus || item->_status == SyncFileItem::Success){
- qCWarning(lcActivity) << "Item " << item->_file << " retrieved successfully.";
- activity._message.prepend(" ");
- activity._message.prepend(tr("Synced"));
- _model->addSyncFileItemToActivityList(activity);
- } else {
- qCWarning(lcActivity) << "Item " << item->_file << " retrieved resulted in error " << item->_errorString;
- activity._subject = item->_errorString;
-
- if(item->_status == SyncFileItem::Status::FileIgnored) {
- _model->addIgnoredFileToList(activity);
- } else {
- // add 'protocol error' to activity list
- _model->addErrorToActivityList(activity);
- }
- }
- }
-}
-
-void ActivityWidget::addError(const QString &folderAlias, const QString &message,
- ErrorCategory category)
-{
- auto folderInstance = FolderMan::instance()->folder(folderAlias);
- if (!folderInstance)
- return;
-
- if(folderInstance->accountState() == _accountState){
- qCWarning(lcActivity) << "Item " << folderInstance->shortGuiLocalPath() << " retrieved resulted in " << message;
-
- Activity activity;
- activity._type = Activity::SyncResultType;
- activity._status = SyncResult::Error;
- activity._dateTime = QDateTime::fromString(QDateTime::currentDateTime().toString(), Qt::ISODate);
- activity._subject = message;
- activity._message = folderInstance->shortGuiLocalPath();
- activity._link = folderInstance->shortGuiLocalPath();
- activity._accName = folderInstance->accountState()->account()->displayName();
- activity._folder = folderAlias;
-
-
- if (category == ErrorCategory::InsufficientRemoteStorage) {
- ActivityLink link;
- link._label = tr("Retry all uploads");
- link._link = folderInstance->path();
- link._verb = "";
- link._isPrimary = true;
- activity._links.append(link);
- }
-
- // add 'other errors' to activity list
- _model->addErrorToActivityList(activity);
- }
-}
-
-
-void ActivityWidget::slotPrimaryButtonClickedOnListView(const QModelIndex &index){
- QUrl link = qvariant_cast<QString>(index.data(ActivityItemDelegate::LinkRole));
- QString objectType = index.data(ActivityItemDelegate::ObjectTypeRole).toString();
- if(!link.isEmpty()){
- qCWarning(lcActivity) << "Opening" << link.toString() << "in browser for Notification/Activity" << qvariant_cast<QString>(index.data(ActivityItemDelegate::ActionTextRole));
- Utility::openBrowser(link, this);
- } else if(objectType == _remote_share){
- QVariant customItem = index.data(ActivityItemDelegate::ActionsLinksRole).toList().first();
- ActivityLink actionLink = qvariant_cast<ActivityLink>(customItem);
- if(actionLink._label == _accept){
- qCWarning(lcActivity) << objectType << "action" << actionLink._label << "for" << qvariant_cast<QString>(index.data(ActivityItemDelegate::ActionTextRole));
- const QString accountName = index.data(ActivityItemDelegate::AccountRole).toString();
- slotSendNotificationRequest(accountName, actionLink._link, actionLink._verb, index.row());
- } else {
- qCWarning(lcActivity) << "Failed: " << objectType << "action" << actionLink._label << "for" << qvariant_cast<QString>(index.data(ActivityItemDelegate::ActionTextRole));
- }
- }
-}
-
-void ActivityWidget::slotSecondaryButtonClickedOnListView(const QModelIndex &index){
- QList<QVariant> customList = index.data(ActivityItemDelegate::ActionsLinksRole).toList();
- QString objectType = index.data(ActivityItemDelegate::ObjectTypeRole).toString();
-
- QList<ActivityLink> actionLinks;
- foreach(QVariant customItem, customList){
- actionLinks << qvariant_cast<ActivityLink>(customItem);
- }
-
- if(objectType == _remote_share && actionLinks.first()._label == _accept)
- actionLinks.removeFirst();
-
- if(qvariant_cast<Activity::Type>(index.data(ActivityItemDelegate::ActionRole)) == Activity::Type::NotificationType){
- const QString accountName = index.data(ActivityItemDelegate::AccountRole).toString();
- if(actionLinks.size() == 1){
- if(actionLinks.at(0)._verb == "DELETE"){
- qCWarning(lcActivity) << "Dismissing Notification/Activity" << qvariant_cast<QString>(index.data(ActivityItemDelegate::ActionTextRole));
- slotSendNotificationRequest(index.data(ActivityItemDelegate::AccountRole).toString(), actionLinks.at(0)._link, actionLinks.at(0)._verb, index.row());
- }
- } else if(actionLinks.size() > 1){
- QMenu menu;
- qCWarning(lcActivity) << "Displaying menu for Notification/Activity" << qvariant_cast<QString>(index.data(ActivityItemDelegate::ActionTextRole));
- foreach (ActivityLink actionLink, actionLinks) {
- QAction *menuAction = new QAction(actionLink._label, &menu);
- connect(menuAction, &QAction::triggered, this, [this, index, accountName, actionLink] {
- this->slotSendNotificationRequest(accountName, actionLink._link, actionLink._verb, index.row());
- });
- menu.addAction(menuAction);
- }
- menu.exec(QCursor::pos());
- }
- }
-
- Activity::Type activityType = qvariant_cast<Activity::Type>(index.data(ActivityItemDelegate::ActionRole));
- if(activityType == Activity::Type::SyncFileItemType || activityType == Activity::Type::SyncResultType)
- slotOpenFile(index);
-}
-
-void ActivityWidget::slotNotificationRequestFinished(int statusCode)
-{
- int row = sender()->property("activityRow").toInt();
-
- // the ocs API returns stat code 100 or 200 inside the xml if it succeeded.
- if (statusCode != OCS_SUCCESS_STATUS_CODE && statusCode != OCS_SUCCESS_STATUS_CODE_V2) {
- qCWarning(lcActivity) << "Notification Request to Server failed, leave notification visible.";
- } else {
- // to do use the model to rebuild the list or remove the item
- qCWarning(lcActivity) << "Notification Request to Server successed, rebuilding list.";
- _model->removeActivityFromActivityList(row);
- }
-}
-
-void ActivityWidget::slotRefreshActivities()
-{
- _model->slotRefreshActivity();
-}
-
-void ActivityWidget::slotRefreshNotifications()
-{
- // start a server notification handler if no notification requests
- // are running
- if (_notificationRequestsRunning == 0) {
- ServerNotificationHandler *snh = new ServerNotificationHandler(_accountState);
- connect(snh, &ServerNotificationHandler::newNotificationList,
- this, &ActivityWidget::slotBuildNotificationDisplay);
-
- snh->slotFetchNotifications();
- } else {
- qCWarning(lcActivity) << "Notification request counter not zero.";
- }
-}
-
-void ActivityWidget::slotRemoveAccount()
-{
- _model->slotRemoveAccount();
-}
-
-void ActivityWidget::showLabels()
-{
- _ui->_bottomLabel->hide(); // hide whatever was there before
- QString t("");
- QSetIterator<QString> i(_accountsWithoutActivities);
- while (i.hasNext()) {
- t.append(tr("<br/>Account %1 does not have activities enabled.").arg(i.next()));
- }
- if(!t.isEmpty()){
- _ui->_bottomLabel->setTextFormat(Qt::RichText);
- _ui->_bottomLabel->setText(t);
- _ui->_bottomLabel->show();
- }
-}
-
-void ActivityWidget::slotAccountActivityStatus(int statusCode)
-{
- if (!(_accountState && _accountState->account())) {
- return;
- }
- if (statusCode == 999) {
- _accountsWithoutActivities.insert(_accountState->account()->displayName());
- } else {
- _accountsWithoutActivities.remove(_accountState->account()->displayName());
- }
-
- checkActivityWidgetVisibility();
- showLabels();
-}
-
-// FIXME: Reused from protocol widget. Move over to utilities.
-QString ActivityWidget::timeString(QDateTime dt, QLocale::FormatType format) const
-{
- const QLocale loc = QLocale::system();
- QString dtFormat = loc.dateTimeFormat(format);
- static const QRegExp re("(HH|H|hh|h):mm(?!:s)");
- dtFormat.replace(re, "\\1:mm:ss");
- return loc.toString(dt, dtFormat);
-}
-
-void ActivityWidget::storeActivityList(QTextStream &ts)
-{
- ActivityList activities = _model->activityList();
-
- foreach (Activity activity, activities) {
- ts << right
- // account name
- << qSetFieldWidth(activity._accName.length())
- << activity._accName
- // separator
- << qSetFieldWidth(2) << " - "
-
- // date and time
- << qSetFieldWidth(activity._dateTime.toString().length())
- << activity._dateTime.toString()
- // separator
- << qSetFieldWidth(2) << " - "
-
- // fileq
- << qSetFieldWidth(activity._file.length())
- << activity._file
- // separator
- << qSetFieldWidth(2) << " - "
-
- // subject
- << qSetFieldWidth(activity._subject.length())
- << activity._subject
- // separator
- << qSetFieldWidth(2) << " - "
-
- // message
- << qSetFieldWidth(activity._message.length())
- << activity._message
- << endl;
- }
-}
-
-void ActivityWidget::checkActivityWidgetVisibility()
-{
- int accountCount = AccountManager::instance()->accounts().count();
- bool hasAccountsWithActivity =
- _accountsWithoutActivities.count() != accountCount;
-
- _ui->_activityList->setVisible(hasAccountsWithActivity);
-
- emit hideActivityTab(!hasAccountsWithActivity);
-}
-
-void ActivityWidget::slotOpenFile(QModelIndex indx)
-{
- qCDebug(lcActivity) << indx.isValid() << indx.data(ActivityItemDelegate::PathRole).toString() << QFile::exists(indx.data(ActivityItemDelegate::PathRole).toString());
- if (indx.isValid()) {
- QString fullPath = indx.data(ActivityItemDelegate::PathRole).toString();
- if(!fullPath.isEmpty()){
- if (QFile::exists(fullPath)) {
- showInFileManager(fullPath);
- }
- }
- }
-}
-
-// GUI: Display the notifications.
-// All notifications in list are coming from the same account
-// but in the _widgetForNotifId hash widgets for all accounts are
-// collected.
-void ActivityWidget::slotBuildNotificationDisplay(const ActivityList &list)
-{
- // Whether a new notification was added to the list
- bool newNotificationShown = false;
-
- _model->clearNotifications();
-
- foreach (auto activity, list) {
- if (_blacklistedNotifications.contains(activity)) {
- qCInfo(lcActivity) << "Activity in blacklist, skip";
- continue;
- }
-
- // handle gui logs. In order to NOT annoy the user with every fetching of the
- // notifications the notification id is stored in a Set. Only if an id
- // is not in the set, it qualifies for guiLog.
- // Important: The _guiLoggedNotifications set must be wiped regularly which
- // will repeat the gui log.
-
- // after one hour, clear the gui log notification store
- if (_guiLogTimer.elapsed() > 60 * 60 * 1000) {
- _guiLoggedNotifications.clear();
- }
-
- if (!_guiLoggedNotifications.contains(activity._id)) {
- newNotificationShown = true;
- _guiLoggedNotifications.insert(activity._id);
-
- // Assemble a tray notification for the NEW notification
- ConfigFile cfg;
- if(cfg.optionalServerNotifications()){
- if(AccountManager::instance()->accounts().count() == 1){
- emit guiLog(activity._subject, "");
- } else {
- emit guiLog(activity._subject, activity._accName);
- }
- }
- }
-
- _model->addNotificationToActivityList(activity);
- }
-
- // restart the gui log timer now that we show a new notification
- if(newNotificationShown) {
- _guiLogTimer.start();
- }
-}
-
-void ActivityWidget::slotSendNotificationRequest(const QString &accountName, const QString &link, const QByteArray &verb, int row)
-{
- qCInfo(lcActivity) << "Server Notification Request " << verb << link << "on account" << accountName;
-
- const QStringList validVerbs = QStringList() << "GET"
- << "PUT"
- << "POST"
- << "DELETE";
-
- if (validVerbs.contains(verb)) {
- AccountStatePtr acc = AccountManager::instance()->account(accountName);
- if (acc) {
- NotificationConfirmJob *job = new NotificationConfirmJob(acc->account());
- QUrl l(link);
- job->setLinkAndVerb(l, verb);
- job->setProperty("activityRow", QVariant::fromValue(row));
- connect(job, &AbstractNetworkJob::networkError,
- this, &ActivityWidget::slotNotifyNetworkError);
- connect(job, &NotificationConfirmJob::jobFinished,
- this, &ActivityWidget::slotNotifyServerFinished);
- job->start();
-
- // count the number of running notification requests. If this member var
- // is larger than zero, no new fetching of notifications is started
- _notificationRequestsRunning++;
- }
- } else {
- qCWarning(lcActivity) << "Notification Links: Invalid verb:" << verb;
- }
-}
-
-void ActivityWidget::endNotificationRequest(int replyCode)
-{
- _notificationRequestsRunning--;
- slotNotificationRequestFinished(replyCode);
-}
-
-void ActivityWidget::slotNotifyNetworkError(QNetworkReply *reply)
-{
- NotificationConfirmJob *job = qobject_cast<NotificationConfirmJob *>(sender());
- if (!job) {
- return;
- }
-
- int resultCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
-
- endNotificationRequest(resultCode);
- qCWarning(lcActivity) << "Server notify job failed with code " << resultCode;
-}
-
-void ActivityWidget::slotNotifyServerFinished(const QString &reply, int replyCode)
-{
- NotificationConfirmJob *job = qobject_cast<NotificationConfirmJob *>(sender());
- if (!job) {
- return;
- }
-
- endNotificationRequest(replyCode);
- qCInfo(lcActivity) << "Server Notification reply code" << replyCode << reply;
-}
-
-void ActivityWidget::slotStyleChanged()
-{
- // Notify the other widgets (Dark-/Light-Mode switching)
- emit styleChanged();
-}
-
-/* ==================================================================== */
-
-ActivitySettings::ActivitySettings(AccountState *accountState, QWidget *parent)
- : QWidget(parent)
- , _accountState(accountState)
-{
- _vbox = new QVBoxLayout(this);
- setLayout(_vbox);
-
- _activityWidget = new ActivityWidget(_accountState, this);
-
- _vbox->insertWidget(1, _activityWidget);
- connect(_activityWidget, &ActivityWidget::guiLog, this, &ActivitySettings::guiLog);
- connect(&_notificationCheckTimer, &QTimer::timeout,
- this, &ActivitySettings::slotRegularNotificationCheck);
-
- // Add a progress indicator to spin if the acitivity list is updated.
- _progressIndicator = new QProgressIndicator(this);
-
- // connect a model signal to stop the animation
- connect(_activityWidget, &ActivityWidget::rowsInserted, _progressIndicator, &QProgressIndicator::stopAnimation);
- connect(_activityWidget, &ActivityWidget::rowsInserted, this, &ActivitySettings::slotDisplayActivities);
-
- // Connect styleChanged events to our widgets, so they can adapt (Dark-/Light-Mode switching)
- connect(this, &ActivitySettings::styleChanged, _activityWidget, &ActivityWidget::slotStyleChanged);
-}
-
-void ActivitySettings::slotDisplayActivities(){
- _vbox->removeWidget(_progressIndicator);
-}
-
-void ActivitySettings::setNotificationRefreshInterval(std::chrono::milliseconds interval)
-{
- qCDebug(lcActivity) << "Starting Notification refresh timer with " << interval.count() / 1000 << " sec interval";
- _notificationCheckTimer.start(interval.count());
-}
-
-void ActivitySettings::slotRemoveAccount()
-{
- _activityWidget->slotRemoveAccount();
-}
-
-void ActivitySettings::slotRefresh()
-{
- // QElapsedTimer isn't actually constructed as invalid.
- if (!_timeSinceLastCheck.contains(_accountState)) {
- _timeSinceLastCheck[_accountState].invalidate();
- }
- QElapsedTimer &timer = _timeSinceLastCheck[_accountState];
-
- // Fetch Activities only if visible and if last check is longer than 15 secs ago
- if (timer.isValid() && timer.elapsed() < NOTIFICATION_REQUEST_FREE_PERIOD) {
- qCDebug(lcActivity) << "Do not check as last check is only secs ago: " << timer.elapsed() / 1000;
- return;
- }
- if (_accountState && _accountState->isConnected()) {
- if (isVisible() || !timer.isValid()) {
- _vbox->insertWidget(0, _progressIndicator);
- _vbox->setAlignment(_progressIndicator, Qt::AlignHCenter);
- _progressIndicator->startAnimation();
- _activityWidget->slotRefreshActivities();
- }
- _activityWidget->slotRefreshNotifications();
- timer.start();
- }
-}
-
-void ActivitySettings::slotRegularNotificationCheck()
-{
- slotRefresh();
-}
-
-bool ActivitySettings::event(QEvent *e)
-{
- if (e->type() == QEvent::Show) {
- slotRefresh();
- }
- return QWidget::event(e);
-}
-
-ActivitySettings::~ActivitySettings()
-{
-}
-
-void ActivitySettings::slotStyleChanged()
-{
- if(_progressIndicator)
- _progressIndicator->setColor(QGuiApplication::palette().color(QPalette::Text));
-
- // Notify the other widgets (Dark-/Light-Mode switching)
- emit styleChanged();
-}
-
-}
diff --git a/src/gui/activitywidget.h b/src/gui/activitywidget.h
deleted file mode 100644
index ee271c62a..000000000
--- a/src/gui/activitywidget.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) by Klaas Freitag <freitag@owncloud.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.
- */
-
-#ifndef ACTIVITYWIDGET_H
-#define ACTIVITYWIDGET_H
-
-#include <QDialog>
-#include <QDateTime>
-#include <QLocale>
-#include <QAbstractListModel>
-#include <chrono>
-
-#include "progressdispatcher.h"
-#include "owncloudgui.h"
-#include "account.h"
-#include "activitydata.h"
-#include "accountmanager.h"
-
-#include "ui_activitywidget.h"
-
-class QPushButton;
-class QProgressIndicator;
-
-namespace OCC {
-
-class Account;
-class AccountStatusPtr;
-class JsonApiJob;
-class ActivityListModel;
-
-namespace Ui {
- class ActivityWidget;
-}
-class Application;
-
-/**
- * @brief The ActivityWidget class
- * @ingroup gui
- *
- * The list widget to display the activities, contained in the
- * subsequent ActivitySettings widget.
- */
-
-class ActivityWidget : public QWidget
-{
- Q_OBJECT
-public:
- explicit ActivityWidget(AccountState *accountState, QWidget *parent = nullptr);
- ~ActivityWidget();
- QSize sizeHint() const override { return ownCloudGui::settingsDialogSize(); }
- void storeActivityList(QTextStream &ts);
-
- /**
- * Adjusts the activity tab's and some widgets' visibility
- *
- * Based on whether activities are enabled and whether notifications are
- * available.
- */
- void checkActivityWidgetVisibility();
-
-public slots:
- void slotOpenFile(QModelIndex indx);
- void slotRefreshActivities();
- void slotRefreshNotifications();
- void slotRemoveAccount();
- void slotAccountActivityStatus(int statusCode);
- void addError(const QString &folderAlias, const QString &message, ErrorCategory category);
- void slotProgressInfo(const QString &folder, const ProgressInfo &progress);
- void slotItemCompleted(const QString &folder, const SyncFileItemPtr &item);
- void slotStyleChanged();
-
-signals:
- void guiLog(const QString &, const QString &);
- void rowsInserted();
- void hideActivityTab(bool);
- void sendNotificationRequest(const QString &accountName, const QString &link, const QByteArray &verb, int row);
- void styleChanged();
-
-private slots:
- void slotBuildNotificationDisplay(const ActivityList &list);
- void slotSendNotificationRequest(const QString &accountName, const QString &link, const QByteArray &verb, int row);
- void slotNotifyNetworkError(QNetworkReply *);
- void slotNotifyServerFinished(const QString &reply, int replyCode);
- void endNotificationRequest(int replyCode);
- void slotNotificationRequestFinished(int statusCode);
- void slotPrimaryButtonClickedOnListView(const QModelIndex &index);
- void slotSecondaryButtonClickedOnListView(const QModelIndex &index);
-
-private:
- void customizeStyle();
- void showLabels();
- QString timeString(QDateTime dt, QLocale::FormatType format) const;
- Ui::ActivityWidget *_ui;
- QSet<QString> _accountsWithoutActivities;
- QElapsedTimer _guiLogTimer;
- QSet<int> _guiLoggedNotifications;
- ActivityList _blacklistedNotifications;
-
- QTimer _removeTimer;
-
- // number of currently running notification requests. If non zero,
- // no query for notifications is started.
- int _notificationRequestsRunning;
-
- ActivityListModel *_model;
- AccountState *_accountState;
- const QString _accept;
- const QString _remote_share;
-};
-
-
-/**
- * @brief The ActivitySettings class
- * @ingroup gui
- *
- * Implements a tab for the settings dialog, displaying the three activity
- * lists.
- */
-class ActivitySettings : public QWidget
-{
- Q_OBJECT
-public:
- explicit ActivitySettings(AccountState *accountState, QWidget *parent = nullptr);
-
- ~ActivitySettings();
- QSize sizeHint() const override { return ownCloudGui::settingsDialogSize(); }
-
-public slots:
- void slotRefresh();
- void slotRemoveAccount();
- void setNotificationRefreshInterval(std::chrono::milliseconds interval);
- void slotStyleChanged();
-
-private slots:
- void slotRegularNotificationCheck();
- void slotDisplayActivities();
-
-signals:
- void guiLog(const QString &, const QString &);
- void styleChanged();
-
-private:
- bool event(QEvent *e) override;
-
- ActivityWidget *_activityWidget;
- QProgressIndicator *_progressIndicator;
- QVBoxLayout *_vbox;
- QTimer _notificationCheckTimer;
- QHash<AccountState *, QElapsedTimer> _timeSinceLastCheck;
-
- AccountState *_accountState;
-};
-}
-#endif // ActivityWIDGET_H
diff --git a/src/gui/activitywidget.ui b/src/gui/activitywidget.ui
deleted file mode 100644
index 7e5e9f73c..000000000
--- a/src/gui/activitywidget.ui
+++ /dev/null
@@ -1,98 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>OCC::ActivityWidget</class>
- <widget class="QWidget" name="OCC::ActivityWidget">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>652</width>
- <height>556</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string notr="true">Form</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout">
- <property name="sizeConstraint">
- <enum>QLayout::SetDefaultConstraint</enum>
- </property>
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QListView" name="_activityList">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="frameShape">
- <enum>QFrame::StyledPanel</enum>
- </property>
- <property name="frameShadow">
- <enum>QFrame::Sunken</enum>
- </property>
- <property name="lineWidth">
- <number>1</number>
- </property>
- <property name="sizeAdjustPolicy">
- <enum>QAbstractScrollArea::AdjustToContents</enum>
- </property>
- <property name="editTriggers">
- <set>QAbstractItemView::NoEditTriggers</set>
- </property>
- <property name="showDropIndicator" stdset="0">
- <bool>false</bool>
- </property>
- <property name="defaultDropAction">
- <enum>Qt::IgnoreAction</enum>
- </property>
- <property name="resizeMode">
- <enum>QListView::Adjust</enum>
- </property>
- <property name="viewMode">
- <enum>QListView::ListMode</enum>
- </property>
- <property name="modelColumn">
- <number>0</number>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="_bottomLabel">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string notr="true">TextLabel</string>
- </property>
- <property name="textFormat">
- <enum>Qt::RichText</enum>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <tabstops>
- <tabstop>_activityList</tabstop>
- </tabstops>
- <resources/>
- <connections/>
-</ui>
diff --git a/src/gui/generalsettings.ui b/src/gui/generalsettings.ui
index fcdfc073c..1c7c25015 100644
--- a/src/gui/generalsettings.ui
+++ b/src/gui/generalsettings.ui
@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
- <width>785</width>
+ <width>516</width>
<height>523</height>
</rect>
</property>
diff --git a/src/gui/networksettings.ui b/src/gui/networksettings.ui
index 5d7dc94e8..b9391cf7e 100644
--- a/src/gui/networksettings.ui
+++ b/src/gui/networksettings.ui
@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
- <width>563</width>
+ <width>516</width>
<height>444</height>
</rect>
</property>
diff --git a/src/gui/owncloudgui.cpp b/src/gui/owncloudgui.cpp
index 27662f715..8916c2846 100644
--- a/src/gui/owncloudgui.cpp
+++ b/src/gui/owncloudgui.cpp
@@ -207,10 +207,6 @@ void ownCloudGui::slotSyncStateChange(Folder *folder)
|| result.status() == SyncResult::Error) {
Logger::instance()->enterNextLogFile();
}
-
- if (result.status() == SyncResult::NotYetStarted) {
- _settingsDialog->slotRefreshActivity(folder->accountState());
- }
}
void ownCloudGui::slotFoldersChanged()
@@ -792,10 +788,7 @@ void ownCloudGui::setupActions()
_navLinksMenu->setEnabled(false);
_actionSettings = new QAction(tr("Settings …"), this);
_actionNewAccountWizard = new QAction(tr("New account …"), this);
- _actionRecent = new QAction(tr("View more activity …"), this);
- _actionRecent->setEnabled(true);
- QObject::connect(_actionRecent, &QAction::triggered, this, &ownCloudGui::slotShowSyncProtocol);
QObject::connect(_actionSettings, &QAction::triggered, this, &ownCloudGui::slotShowSettings);
QObject::connect(_actionNewAccountWizard, &QAction::triggered, this, &ownCloudGui::slotNewAccountWizard);
_actionHelp = new QAction(tr("Help"), this);
@@ -909,8 +902,6 @@ void ownCloudGui::slotRebuildRecentMenus()
} else {
_recentActionsMenu->addAction(tr("No items synced recently"))->setEnabled(false);
}
- // add a more... entry.
- _recentActionsMenu->addAction(_actionRecent);
}
/// Returns true if the completion of a given item should show up in the
@@ -970,8 +961,6 @@ void ownCloudGui::slotUpdateProgress(const QString &folder, const ProgressInfo &
_actionStatus->setText(msg);
}
- _actionRecent->setIcon(QIcon()); // Fixme: Set a "in-progress"-item eventually.
-
if (!progress._lastCompletedItem.isEmpty()
&& shouldShowInRecentsMenu(progress._lastCompletedItem)) {
if (Progress::isWarningKind(progress._lastCompletedItem._status)) {
diff --git a/src/gui/servernotificationhandler.cpp b/src/gui/servernotificationhandler.cpp
deleted file mode 100644
index bcf386033..000000000
--- a/src/gui/servernotificationhandler.cpp
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) by Klaas Freitag <freitag@owncloud.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 "servernotificationhandler.h"
-#include "accountstate.h"
-#include "capabilities.h"
-#include "networkjobs.h"
-
-#include "iconjob.h"
-
-#include <QJsonDocument>
-#include <QJsonObject>
-
-namespace OCC {
-
-Q_LOGGING_CATEGORY(lcServerNotification, "nextcloud.gui.servernotification", QtInfoMsg)
-
-const QString notificationsPath = QLatin1String("ocs/v2.php/apps/notifications/api/v2/notifications");
-const char propertyAccountStateC[] = "oc_account_state";
-const int successStatusCode = 200;
-const int notModifiedStatusCode = 304;
-QMap<int, QIcon> ServerNotificationHandler::iconCache;
-
-ServerNotificationHandler::ServerNotificationHandler(AccountState *accountState, QObject *parent)
- : QObject(parent)
- , _accountState(accountState)
-{
-}
-
-void ServerNotificationHandler::slotFetchNotifications()
-{
- // check connectivity and credentials
- if (!(_accountState && _accountState->isConnected() &&
- _accountState->account() && _accountState->account()->credentials() &&
- _accountState->account()->credentials()->ready())) {
- deleteLater();
- return;
- }
- // check if the account has notifications enabled. If the capabilities are
- // not yet valid, its assumed that notifications are available.
- if (_accountState->account()->capabilities().isValid()) {
- if (!_accountState->account()->capabilities().notificationsAvailable()) {
- qCInfo(lcServerNotification) << "Account" << _accountState->account()->displayName() << "does not have notifications enabled.";
- deleteLater();
- return;
- }
- }
-
- // if the previous notification job has finished, start next.
- _notificationJob = new JsonApiJob(_accountState->account(), notificationsPath, this);
- QObject::connect(_notificationJob.data(), &JsonApiJob::jsonReceived,
- this, &ServerNotificationHandler::slotNotificationsReceived);
- QObject::connect(_notificationJob.data(), &JsonApiJob::etagResponseHeaderReceived,
- this, &ServerNotificationHandler::slotEtagResponseHeaderReceived);
- _notificationJob->setProperty(propertyAccountStateC, QVariant::fromValue<AccountState *>(_accountState));
- _notificationJob->addRawHeader("If-None-Match", _accountState->notificationsEtagResponseHeader());
- _notificationJob->start();
-}
-
-void ServerNotificationHandler::slotEtagResponseHeaderReceived(const QByteArray &value, int statusCode){
- if(statusCode == successStatusCode){
- qCWarning(lcServerNotification) << "New Notification ETag Response Header received " << value;
- AccountState *account = qvariant_cast<AccountState *>(sender()->property(propertyAccountStateC));
- account->setNotificationsEtagResponseHeader(value);
- }
-}
-
-void ServerNotificationHandler::slotIconDownloaded(QByteArray iconData){
- QPixmap pixmap;
- pixmap.loadFromData(iconData);
- iconCache.insert(sender()->property("activityId").toInt(), QIcon(pixmap));
-}
-
-void ServerNotificationHandler::slotNotificationsReceived(const QJsonDocument &json, int statusCode)
-{
- if (statusCode != successStatusCode && statusCode != notModifiedStatusCode) {
- qCWarning(lcServerNotification) << "Notifications failed with status code " << statusCode;
- deleteLater();
- return;
- }
-
- if (statusCode == notModifiedStatusCode) {
- qCWarning(lcServerNotification) << "Status code " << statusCode << " Not Modified - No new notifications.";
- deleteLater();
- return;
- }
-
- auto notifies = json.object().value("ocs").toObject().value("data").toArray();
-
- AccountState *ai = qvariant_cast<AccountState *>(sender()->property(propertyAccountStateC));
-
- ActivityList list;
-
- foreach (auto element, notifies) {
- Activity a;
- auto json = element.toObject();
- a._type = Activity::NotificationType;
- a._accName = ai->account()->displayName();
- a._id = json.value("notification_id").toInt();
-
- //need to know, specially for remote_share
- a._objectType = json.value("object_type").toString();
- a._status = 0;
-
- a._subject = json.value("subject").toString();
- a._message = json.value("message").toString();
-
- if(!json.value("icon").toString().isEmpty()){
- IconJob *iconJob = new IconJob(QUrl(json.value("icon").toString()));
- iconJob->setProperty("activityId", a._id);
- connect(iconJob, &IconJob::jobFinished, this, &ServerNotificationHandler::slotIconDownloaded);
- }
-
- QUrl link(json.value("link").toString());
- if (!link.isEmpty()) {
- if(link.host().isEmpty()){
- link.setScheme(ai->account()->url().scheme());
- link.setHost(ai->account()->url().host());
- }
- if (link.port() == -1) {
- link.setPort(ai->account()->url().port());
- }
- }
- a._link = link;
- a._dateTime = QDateTime::fromString(json.value("datetime").toString(), Qt::ISODate);
-
- auto actions = json.value("actions").toArray();
- foreach (auto action, actions) {
- auto actionJson = action.toObject();
- ActivityLink al;
- al._label = QUrl::fromPercentEncoding(actionJson.value("label").toString().toUtf8());
- al._link = actionJson.value("link").toString();
- al._verb = actionJson.value("type").toString().toUtf8();
- al._isPrimary = actionJson.value("primary").toBool();
-
- a._links.append(al);
- }
-
- // Add another action to dismiss notification on server
- // https://github.com/owncloud/notifications/blob/master/docs/ocs-endpoint-v1.md#deleting-a-notification-for-a-user
- ActivityLink al;
- al._label = tr("Dismiss");
- al._link = Utility::concatUrlPath(ai->account()->url(), notificationsPath + "/" + QString::number(a._id)).toString();
- al._verb = "DELETE";
- al._isPrimary = false;
- a._links.append(al);
-
- list.append(a);
- }
- emit newNotificationList(list);
-
- deleteLater();
-}
-}
diff --git a/src/gui/servernotificationhandler.h b/src/gui/servernotificationhandler.h
deleted file mode 100644
index f0276da52..000000000
--- a/src/gui/servernotificationhandler.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) by Klaas Freitag <freitag@owncloud.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.
- */
-
-#ifndef SERVERNOTIFICATIONHANDLER_H
-#define SERVERNOTIFICATIONHANDLER_H
-
-#include <QtCore>
-
-#include "activitywidget.h"
-
-class QJsonDocument;
-
-namespace OCC {
-
-class ServerNotificationHandler : public QObject
-{
- Q_OBJECT
-public:
- explicit ServerNotificationHandler(AccountState *accountState, QObject *parent = nullptr);
- static QMap<int, QIcon> iconCache;
-
-signals:
- void newNotificationList(ActivityList);
-
-public slots:
- void slotFetchNotifications();
-
-private slots:
- void slotNotificationsReceived(const QJsonDocument &json, int statusCode);
- void slotEtagResponseHeaderReceived(const QByteArray &value, int statusCode);
- void slotIconDownloaded(QByteArray iconData);
-
-private:
- QPointer<JsonApiJob> _notificationJob;
- AccountState *_accountState;
-};
-}
-
-#endif // SERVERNOTIFICATIONHANDLER_H
diff --git a/src/gui/settingsdialog.cpp b/src/gui/settingsdialog.cpp
index a80de4da5..6fa7bfa47 100644
--- a/src/gui/settingsdialog.cpp
+++ b/src/gui/settingsdialog.cpp
@@ -23,7 +23,6 @@
#include "configfile.h"
#include "progressdispatcher.h"
#include "owncloudgui.h"
-#include "activitywidget.h"
#include "accountmanager.h"
#include <QLabel>
@@ -189,39 +188,13 @@ void SettingsDialog::showFirstPage()
}
}
-void SettingsDialog::showActivityPage()
-{
- if (auto account = qvariant_cast<AccountState*>(sender()->property("account"))) {
- _activitySettings[account]->show();
- _ui->stack->setCurrentWidget(_activitySettings[account]);
- }
-}
-
void SettingsDialog::showIssuesList(AccountState *account) {
- for (auto it = _actionGroupWidgets.begin(); it != _actionGroupWidgets.end(); ++it) {
+ /*for (auto it = _actionGroupWidgets.begin(); it != _actionGroupWidgets.end(); ++it) {
if (it.value() == _activitySettings[account]) {
it.key()->activate(QAction::ActionEvent::Trigger);
break;
}
- }
-}
-
-void SettingsDialog::activityAdded(AccountState *s){
- _ui->stack->addWidget(_activitySettings[s]);
- connect(_activitySettings[s], &ActivitySettings::guiLog, _gui,
- &ownCloudGui::slotShowOptionalTrayMessage);
-
- ConfigFile cfg;
- _activitySettings[s]->setNotificationRefreshInterval(cfg.notificationRefreshInterval());
-
- // Note: all the actions have a '\n' because the account name is in two lines and
- // all buttons must have the same size in order to keep a good layout
- QAction *action = createColorAwareAction(QLatin1String(":/client/resources/activity.png"), tr("Activity"));
- action->setProperty("account", QVariant::fromValue(s));
- _toolBar->insertAction(_actionBefore, action);
- _actionGroup->addAction(action);
- _actionGroupWidgets.insert(action, _activitySettings[s]);
- connect(action, &QAction::triggered, this, &SettingsDialog::showActivityPage);
+ }*/
}
void SettingsDialog::accountAdded(AccountState *s)
@@ -229,16 +202,6 @@ void SettingsDialog::accountAdded(AccountState *s)
auto height = _toolBar->sizeHint().height();
bool brandingSingleAccount = !Theme::instance()->multiAccount();
- _activitySettings[s] = new ActivitySettings(s, this);
-
-
-
- // if this is not the first account, then before we continue to add more accounts we add a separator
- if(AccountManager::instance()->accounts().first().data() != s &&
- AccountManager::instance()->accounts().size() >= 1){
- _actionGroupWidgets.insert(_toolBar->insertSeparator(_actionBefore), _activitySettings[s]);
- }
-
QAction *accountAction;
QImage avatar = s->account()->avatar();
const QString actionText = brandingSingleAccount ? tr("Account") : s->account()->displayName();
@@ -270,15 +233,8 @@ void SettingsDialog::accountAdded(AccountState *s)
connect(s->account().data(), &Account::accountChangedAvatar, this, &SettingsDialog::slotAccountAvatarChanged);
connect(s->account().data(), &Account::accountChangedDisplayName, this, &SettingsDialog::slotAccountDisplayNameChanged);
- // Refresh immediatly when getting online
- connect(s, &AccountState::isConnectedChanged, this, &SettingsDialog::slotRefreshActivityAccountStateSender);
-
// Connect styleChanged event, to adapt (Dark-/Light-Mode switching)
connect(this, &SettingsDialog::styleChanged, accountSettings, &AccountSettings::slotStyleChanged);
- connect(this, &SettingsDialog::styleChanged, _activitySettings[s], &ActivitySettings::slotStyleChanged);
-
- activityAdded(s);
- slotRefreshActivity(s);
}
void SettingsDialog::slotAccountAvatarChanged()
@@ -334,19 +290,6 @@ void SettingsDialog::accountRemoved(AccountState *s)
_actionForAccount.remove(s->account().data());
}
- if(_activitySettings.contains(s)){
- _activitySettings[s]->slotRemoveAccount();
- _activitySettings[s]->hide();
-
- // get the settings widget and the separator
- foreach(QAction *action, _actionGroupWidgets.keys(_activitySettings[s])){
- _actionGroupWidgets.remove(action);
- _toolBar->removeAction(action);
- }
- _toolBar->widgetForAction(_actionBefore)->hide();
- _activitySettings.remove(s);
- }
-
// Hide when the last account is deleted. We want to enter the same
// state we'd be in the client was started up without an account
// configured.
@@ -416,15 +359,4 @@ QAction *SettingsDialog::createColorAwareAction(const QString &iconPath, const Q
return createActionWithIcon(coloredIcon, text, iconPath);
}
-void SettingsDialog::slotRefreshActivityAccountStateSender()
-{
- slotRefreshActivity(qobject_cast<AccountState*>(sender()));
-}
-
-void SettingsDialog::slotRefreshActivity(AccountState *accountState)
-{
- if (accountState->isConnected())
- _activitySettings[accountState]->slotRefresh();
-}
-
} // namespace OCC
diff --git a/src/gui/settingsdialog.h b/src/gui/settingsdialog.h
index f5ec654d9..8242522c2 100644
--- a/src/gui/settingsdialog.h
+++ b/src/gui/settingsdialog.h
@@ -37,7 +37,6 @@ class AccountSettings;
class Application;
class FolderMan;
class ownCloudGui;
-class ActivitySettings;
/**
* @brief The SettingsDialog class
@@ -55,11 +54,8 @@ public:
public slots:
void showFirstPage();
- void showActivityPage();
void showIssuesList(AccountState *account);
void slotSwitchPage(QAction *action);
- void slotRefreshActivity(AccountState *accountState);
- void slotRefreshActivityAccountStateSender();
void slotAccountAvatarChanged();
void slotAccountDisplayNameChanged();
@@ -78,7 +74,6 @@ private slots:
private:
void customizeStyle();
- void activityAdded(AccountState *);
QAction *createColorAwareAction(const QString &iconName, const QString &fileName);
QAction *createActionWithIcon(const QIcon &icon, const QString &text, const QString &iconPath = QString());
@@ -95,7 +90,6 @@ private:
QHash<Account *, QAction *> _actionForAccount;
QToolBar *_toolBar;
- QMap<AccountState *, ActivitySettings *> _activitySettings;
ownCloudGui *_gui;
};
diff --git a/src/gui/settingsdialog.ui b/src/gui/settingsdialog.ui
index 3f886ed22..18632134f 100644
--- a/src/gui/settingsdialog.ui
+++ b/src/gui/settingsdialog.ui
@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
- <width>693</width>
+ <width>516</width>
<height>457</height>
</rect>
</property>
diff --git a/src/gui/systray.cpp b/src/gui/systray.cpp
index 97d6a1a03..c377c69bb 100644
--- a/src/gui/systray.cpp
+++ b/src/gui/systray.cpp
@@ -42,14 +42,12 @@ Systray::Systray() // TODO: make singleton, provide ::instance()
{
// Create QML tray engine, build component, set C++ backend context used in window.qml
// Use pointer instead of engine() helper function until Qt 5.12 is minimum standard
- QQmlEngine *engine = new QQmlEngine;
- _trayComponent = new QQmlComponent(engine, QUrl(QStringLiteral("qrc:/qml/src/gui/tray/window.qml")));
- _trayContext = engine->contextForObject(_trayComponent->create());
-
- engine->addImageProvider("avatars", new ImageProvider);
- engine->rootContext()->setContextProperty("userModelBackend", UserModel::instance());
- engine->rootContext()->setContextProperty("activityModel", ActivityModel::instance());
- engine->rootContext()->setContextProperty("systrayBackend", this);
+ _trayEngine = new QQmlEngine;
+ _trayEngine->addImageProvider("avatars", new ImageProvider);
+ _trayEngine->rootContext()->setContextProperty("userModelBackend", UserModel::instance());
+ _trayEngine->rootContext()->setContextProperty("systrayBackend", this);
+ _trayComponent = new QQmlComponent(_trayEngine, QUrl(QStringLiteral("qrc:/qml/src/gui/tray/window.qml")));
+ _trayContext = _trayEngine->contextForObject(_trayComponent->create());
// TODO: hack to pass the icon to QML
//ctxt->setContextProperty("theme", QLatin1String("colored"));
@@ -59,8 +57,6 @@ Systray::Systray() // TODO: make singleton, provide ::instance()
slotChangeActivityModel(AccountManager::instance()->accounts().first());
}
- //connect(AccountManager::instance(), &AccountManager::accountAdded,
- // this, &Systray::slotChangeActivityModel);
hideWindow();
}
@@ -72,6 +68,7 @@ void Systray::slotChangeActivityModel(const AccountStatePtr account)
{
_currentAccount = account;
emit currentUserChanged();
+ _trayEngine->rootContext()->setContextProperty("activityModel", UserModel::instance()->currentActivityModel());
}
void Systray::showMessage(const QString &title, const QString &message, MessageIcon icon, int millisecondsTimeoutHint)
diff --git a/src/gui/systray.h b/src/gui/systray.h
index f99f024e6..50c277186 100644
--- a/src/gui/systray.h
+++ b/src/gui/systray.h
@@ -62,6 +62,7 @@ private slots:
private:
AccountStatePtr _currentAccount;
+ QQmlEngine *_trayEngine;
QQmlComponent *_trayComponent;
QQmlContext *_trayContext;
};
diff --git a/src/gui/activitydata.cpp b/src/gui/tray/ActivityData.cpp
index 866c97956..866c97956 100644
--- a/src/gui/activitydata.cpp
+++ b/src/gui/tray/ActivityData.cpp
diff --git a/src/gui/activitydata.h b/src/gui/tray/ActivityData.h
index d2f3c864f..d2f3c864f 100644
--- a/src/gui/activitydata.h
+++ b/src/gui/tray/ActivityData.h
diff --git a/src/gui/activitylistmodel.cpp b/src/gui/tray/ActivityListModel.cpp
index eeb0cc836..4a875d2f6 100644
--- a/src/gui/activitylistmodel.cpp
+++ b/src/gui/tray/ActivityListModel.cpp
@@ -24,21 +24,18 @@
#include "accountmanager.h"
#include "folderman.h"
#include "accessmanager.h"
-#include "activityitemdelegate.h"
-#include "activitydata.h"
-#include "activitylistmodel.h"
+#include "ActivityData.h"
+#include "ActivityListModel.h"
#include "theme.h"
-#include "servernotificationhandler.h"
-
namespace OCC {
Q_LOGGING_CATEGORY(lcActivity, "nextcloud.gui.activity", QtInfoMsg)
-ActivityListModel::ActivityListModel(AccountState *accountState, QWidget *parent)
- : QAbstractListModel(parent)
+ActivityListModel::ActivityListModel(AccountState *accountState, QObject* parent)
+ : QAbstractListModel()
, _accountState(accountState)
{
}
@@ -61,7 +58,7 @@ QVariant ActivityListModel::data(const QModelIndex &index, int role) const
QStringList list;
switch (role) {
- case ActivityItemDelegate::PathRole:
+ case PathRole:
if(!a._file.isEmpty()){
auto folder = FolderMan::instance()->folder(a._folder);
QString relPath(a._file);
@@ -79,7 +76,7 @@ QVariant ActivityListModel::data(const QModelIndex &index, int role) const
}
}
return QVariant();
- case ActivityItemDelegate::ActionsLinksRole:{
+ case ActionsLinksRole:{
QList<QVariant> customList;
foreach (ActivityLink customItem, a._links) {
QVariant customVariant;
@@ -88,16 +85,16 @@ QVariant ActivityListModel::data(const QModelIndex &index, int role) const
}
return customList;
}
- case ActivityItemDelegate::ActionIconRole:{
+ case ActionIconRole:{
ActionIcon actionIcon;
if(a._type == Activity::NotificationType){
- QIcon cachedIcon = ServerNotificationHandler::iconCache.value(a._id);
+ /*QIcon cachedIcon = ServerNotificationHandler::iconCache.value(a._id);
if(!cachedIcon.isNull()) {
actionIcon.iconType = ActivityIconType::iconUseCached;
actionIcon.cachedIcon = cachedIcon;
} else {
actionIcon.iconType = ActivityIconType::iconBell;
- }
+ }*/
} else if(a._type == Activity::SyncResultType){
actionIcon.iconType = ActivityIconType::iconStateError;
} else if(a._type == Activity::SyncFileItemType){
@@ -123,24 +120,24 @@ QVariant ActivityListModel::data(const QModelIndex &index, int role) const
icn.setValue(actionIcon);
return icn;
}
- case ActivityItemDelegate::ObjectTypeRole:
+ case ObjectTypeRole:
return a._objectType;
- case ActivityItemDelegate::ActionRole:{
+ case ActionRole:{
QVariant type;
type.setValue(a._type);
return type;
}
- case ActivityItemDelegate::ActionTextRole:
+ case ActionTextRole:
return a._subject;
- case ActivityItemDelegate::MessageRole:
+ case MessageRole:
return a._message;
- case ActivityItemDelegate::LinkRole:
+ case LinkRole:
return a._link;
- case ActivityItemDelegate::AccountRole:
+ case AccountRole:
return a._accName;
- case ActivityItemDelegate::PointInTimeRole:
+ case PointInTimeRole:
return QString("%1 (%2)").arg(a._dateTime.toLocalTime().toString(Qt::DefaultLocaleShortDate), Utility::timeAgoInWords(a._dateTime.toLocalTime()));
- case ActivityItemDelegate::AccountConnectedRole:
+ case AccountConnectedRole:
return (ast && ast->isConnected());
default:
return QVariant();
diff --git a/src/gui/activitylistmodel.h b/src/gui/tray/ActivityListModel.h
index 1ff352beb..135301592 100644
--- a/src/gui/activitylistmodel.h
+++ b/src/gui/tray/ActivityListModel.h
@@ -47,12 +47,27 @@ public:
iconStateInfo,
iconStateSync
};
+
+ enum datarole { ActionIconRole = Qt::UserRole + 1,
+ UserIconRole,
+ AccountRole,
+ ObjectTypeRole,
+ ActionsLinksRole,
+ ActionTextRole,
+ ActionRole,
+ MessageRole,
+ PathRole,
+ LinkRole,
+ PointInTimeRole,
+ AccountConnectedRole,
+ SyncFileStatusRole };
+
struct ActionIcon {
ActivityIconType iconType;
QIcon cachedIcon;
};
- explicit ActivityListModel(AccountState *accountState, QWidget *parent = nullptr);
+ explicit ActivityListModel(AccountState *accountState, QObject* parent = 0);
QVariant data(const QModelIndex &index, int role) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
diff --git a/src/gui/tray/UserLine.qml b/src/gui/tray/UserLine.qml
index 7dd648fda..8aaa58398 100644
--- a/src/gui/tray/UserLine.qml
+++ b/src/gui/tray/UserLine.qml
@@ -6,7 +6,7 @@ import QtQuick.Layouts 1.2
MenuItem {
Connections {
- target: systrayBackend
+ target: userModelBackend
onRefreshUserMenu: {
userLine.visible = isCurrentUser ? false : true
userLine.height = isCurrentUser ? 0 : 60
@@ -17,7 +17,6 @@ MenuItem {
visible: isCurrentUser ? false : true
width: 216
height: isCurrentUser ? 0 : 60
- //color: "transparent"
Rectangle {
id: userLineBackground
@@ -43,7 +42,7 @@ MenuItem {
}
onClicked: {
- systrayBackend.switchCurrentUser(index)
+ userModelBackend.switchCurrentUser(index)
}
RowLayout {
@@ -55,7 +54,7 @@ MenuItem {
id: accountAvatar
Layout.leftMargin: 4
verticalAlignment: Qt.AlignCenter
- source: avatar
+ source: ("image://avatars/" + index)
Layout.preferredHeight: (userLineBackground.height -16)
Layout.preferredWidth: (userLineBackground.height -16)
}
diff --git a/src/gui/tray/UserModel.cpp b/src/gui/tray/UserModel.cpp
index 95591226f..9ee8ae42a 100644
--- a/src/gui/tray/UserModel.cpp
+++ b/src/gui/tray/UserModel.cpp
@@ -10,6 +10,7 @@ namespace OCC {
User::User(AccountStatePtr &account, const bool &isCurrent)
: _account(account)
, _isCurrentUser(isCurrent)
+ , _activityModel(new ActivityListModel(_account.data()))
{
}
@@ -32,6 +33,11 @@ Folder *User::getFolder()
}
}
+ActivityListModel *User::getActivityModel()
+{
+ return _activityModel;
+}
+
void User::openLocalFolder()
{
QDesktopServices::openUrl(this->getFolder()->path());
@@ -67,11 +73,17 @@ QImage User::avatar() const
{
QImage img = AvatarJob::makeCircularAvatar(_account->account()->avatar());
if (img.isNull()) {
- img = QImage(":/client/resources/account.svg");
+ img = AvatarJob::makeCircularAvatar(QImage(":/client/resources/account.png"));
}
return img;
}
+bool User::serverHasTalk() const
+{
+ auto test = _account->hasTalk();
+ return _account->hasTalk();
+}
+
bool User::isCurrentUser() const
{
return _isCurrentUser;
@@ -79,6 +91,7 @@ bool User::isCurrentUser() const
bool User::isConnected() const
{
+ bool test = (_account->connectionStatus() == AccountState::ConnectionStatus::Connected);
return (_account->connectionStatus() == AccountState::ConnectionStatus::Connected);
}
@@ -143,17 +156,26 @@ Q_INVOKABLE QString UserModel::currentUserServer()
return _users[_currentUserId].server();
}
+Q_INVOKABLE bool UserModel::currentServerHasTalk()
+{
+ return _users[_currentUserId].serverHasTalk();
+}
+
void UserModel::addUser(AccountStatePtr &user, const bool &isCurrent)
{
- auto newUser = User(user, isCurrent);
beginInsertRows(QModelIndex(), rowCount(), rowCount());
- _users << newUser;
+ _users << User(user, isCurrent);
if (isCurrent) {
- _currentUserId = _users.indexOf(newUser);
+ _currentUserId = _users.indexOf(_users.last());
}
endInsertRows();
}
+int UserModel::currentUserIndex()
+{
+ return _currentUserId;
+}
+
Q_INVOKABLE void UserModel::openCurrentAccountLocalFolder()
{
_users[_currentUserId].openLocalFolder();
@@ -204,74 +226,9 @@ QHash<int, QByteArray> UserModel::roleNames() const
return roles;
}
-/*-------------------------------------------------------------------------------------*/
-
-QString UserActivity::type() const
-{
- return "Test";
-}
-QString UserActivity::fileName() const
-{
- return "Test";
-}
-
-QString UserActivity::info() const
-{
- return "Test";
-}
-
-
-ActivityModel *ActivityModel::_instance = nullptr;
-
-ActivityModel *ActivityModel::instance()
-{
- if (_instance == nullptr) {
- _instance = new ActivityModel();
- }
- return _instance;
-}
-
-ActivityModel::ActivityModel(QObject *parent)
- : QAbstractListModel()
-{
-}
-
-QHash<int, QByteArray> ActivityModel::roleNames() const
-{
- QHash<int, QByteArray> roles;
- roles[TypeRole] = "type";
- roles[FileNameRole] = "filename";
- roles[InfoRole] = "info";
- return roles;
-}
-
-int ActivityModel::rowCount(const QModelIndex &parent) const
+ActivityListModel *UserModel::currentActivityModel()
{
- Q_UNUSED(parent);
- return _activities.count();
-}
-
-QVariant ActivityModel::data(const QModelIndex &index, int role) const
-{
- if (index.row() < 0 || index.row() >= _activities.count()) {
- return QVariant();
- }
-
- const UserActivity &activity = _activities[index.row()];
- if (role == TypeRole)
- return activity.type();
- else if (role == FileNameRole)
- return activity.fileName();
- else if (role == InfoRole)
- return activity.info();
- return QVariant();
-}
-
-void ActivityModel::addActivity(const UserActivity &activity)
-{
- beginInsertRows(QModelIndex(), rowCount(), rowCount());
- _activities << activity;
- endInsertRows();
+ return _users[currentUserIndex()].getActivityModel();
}
/*-------------------------------------------------------------------------------------*/
diff --git a/src/gui/tray/UserModel.h b/src/gui/tray/UserModel.h
index 35eb3f9c2..f93d33d8d 100644
--- a/src/gui/tray/UserModel.h
+++ b/src/gui/tray/UserModel.h
@@ -6,6 +6,7 @@
#include <QStringList>
#include <QQuickImageProvider>
+#include "ActivityListModel.h"
#include "accountmanager.h"
#include "folderman.h"
@@ -22,15 +23,18 @@ public:
bool isCurrentUser() const;
void setCurrentUser(const bool &isCurrent);
Folder *getFolder();
+ ActivityListModel *getActivityModel();
void openLocalFolder();
QString name() const;
QString server() const;
+ bool serverHasTalk() const;
QImage avatar() const;
QString id() const;
private:
AccountStatePtr _account;
bool _isCurrentUser;
+ ActivityListModel *_activityModel;
};
class UserModel : public QAbstractListModel
@@ -41,6 +45,7 @@ public:
virtual ~UserModel() {};
void addUser(AccountStatePtr &user, const bool &isCurrent = false);
+ int currentUserIndex();
int rowCount(const QModelIndex &parent = QModelIndex()) const;
@@ -54,8 +59,11 @@ public:
Q_INVOKABLE bool isCurrentUserConnected();
Q_INVOKABLE QString currentUserName();
Q_INVOKABLE QString currentUserServer();
+ Q_INVOKABLE bool currentServerHasTalk();
Q_INVOKABLE void switchCurrentUser(const int &id);
+ ActivityListModel *currentActivityModel();
+
enum UserRoles {
NameRole = Qt::UserRole + 1,
ServerRole,
@@ -85,40 +93,6 @@ private:
void initUserList();
};
-class UserActivity
-{
-public:
- QString type() const;
- QString fileName() const;
- QString info() const;
-};
-
-class ActivityModel : public QAbstractListModel
-{
- Q_OBJECT
-public:
- static ActivityModel *instance();
- virtual ~ActivityModel() {};
-
- int rowCount(const QModelIndex &parent = QModelIndex()) const;
- QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
- void addActivity(const UserActivity &activity);
-
- enum ActivityRoles {
- TypeRole = Qt::UserRole + 1,
- FileNameRole,
- InfoRole
- };
-
-protected:
- QHash<int, QByteArray> roleNames() const;
-
-private:
- static ActivityModel *_instance;
- ActivityModel(QObject *parent = 0);
- QList<UserActivity> _activities;
-};
-
class ImageProvider : public QQuickImageProvider
{
public:
diff --git a/src/gui/tray/window.qml b/src/gui/tray/window.qml
index 28e61f466..337302960 100644
--- a/src/gui/tray/window.qml
+++ b/src/gui/tray/window.qml
@@ -20,15 +20,25 @@ Window {
}
}
+ onVisibleChanged: {
+ currentAccountAvatar.source = ""
+ currentAccountAvatar.source = "image://avatars/currentUser"
+ currentAccountUser.text = userModelBackend.currentUserName();
+ currentAccountServer.text = userModelBackend.currentUserServer();
+ trayWindowTalkButton.visible = userModelBackend.currentServerHasTalk() ? true : false;
+ }
+
Connections {
target: userModelBackend
onRefreshCurrentUserGui: {
- currentAccountAvatar.source = userModelBackend.currentUserAvatar()
- currentAccountUser.text = userModelBackend.currentUserName()
- currentAccountServer.text = userModelBackend.currentUserServer()
+ currentAccountAvatar.source = ""
+ currentAccountAvatar.source = "image://avatars/currentUser"
+ currentAccountUser.text = userModelBackend.currentUserName();
+ currentAccountServer.text = userModelBackend.currentUserServer();
}
onNewUserSelected: {
- accountMenu.close()
+ accountMenu.close();
+ trayWindowTalkButton.visible = userModelBackend.currentServerHasTalk() ? true : false;
}
}
@@ -85,6 +95,7 @@ Window {
hoverEnabled: true
onClicked:
{
+ accMenuLoginButton.text = (userModelBackend.isCurrentUserConnected() ? "Logout" : "Login")
accountMenu.open()
}
@@ -109,7 +120,7 @@ Window {
MenuSeparator { id: accountMenuSeparator }
MenuItem {
- text: (userModelBackend.isCurrentUserConnected() ? "Logout" : "Login")
+ id: accMenuLoginButton
onClicked: (userModelBackend.isCurrentUserConnected()
? userModelBackend.logout()
: userModelBackend.login() )
@@ -188,7 +199,8 @@ Window {
id: currentAccountAvatar
Layout.leftMargin: 8
verticalAlignment: Qt.AlignCenter
- source: userModelBackend.currentUserAvatar()
+ cache: false
+ source: "image://avatars/currentUser"
Layout.preferredHeight: (trayWindowHeaderBackground.height -16)
Layout.preferredWidth: (trayWindowHeaderBackground.height -16)
}
@@ -262,6 +274,7 @@ Window {
Layout.preferredWidth: (trayWindowHeaderBackground.height)
Layout.preferredHeight: (trayWindowHeaderBackground.height)
flat: true
+ visible: userModelBackend.currentServerHasTalk() ? true : false
icon.source: "qrc:///client/theme/white/talk-app.svg"
icon.color: "transparent"
@@ -289,6 +302,7 @@ Window {
Layout.preferredWidth: (trayWindowHeaderBackground.height)
Layout.preferredHeight: (trayWindowHeaderBackground.height)
flat: true
+ visible: false
icon.source: "qrc:///client/theme/white/more-apps.svg"
icon.color: "transparent"
diff --git a/src/libsync/capabilities.cpp b/src/libsync/capabilities.cpp
index 39df7d167..d0c5f727f 100644
--- a/src/libsync/capabilities.cpp
+++ b/src/libsync/capabilities.cpp
@@ -103,7 +103,8 @@ bool Capabilities::isValid() const
return !_capabilities.isEmpty();
}
-bool Capabilities::hasActivities() const {
+bool Capabilities::hasActivities() const
+{
return _capabilities.contains("activity");
}