[Pkg-owncloud-commits] [owncloud-client] 129/470: Display server notifications on the client (#3733)
Sandro Knauß
hefee-guest at moszumanska.debian.org
Thu May 12 16:24:54 UTC 2016
This is an automated email from the git hooks/post-receive script.
hefee-guest pushed a commit to branch master
in repository owncloud-client.
commit 32e16b323c24f4b90da8cf31831a1b875675b676
Author: Klaas Freitag <freitag at owncloud.com>
Date: Fri Mar 4 17:41:57 2016 +0100
Display server notifications on the client (#3733)
As interaction is required, the notifications are displayed in a
separate widget above the server activity list.
Note that design and also where we display the notifications can
still be discussed and changed.
---
src/gui/CMakeLists.txt | 3 +
src/gui/activitywidget.cpp | 164 +++++++++++++++++++++++++++++++++++++++++++++
src/gui/activitywidget.h | 38 ++++++++++-
src/gui/activitywidget.ui | 43 +++++++++++-
4 files changed, 244 insertions(+), 4 deletions(-)
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt
index 2cf4886..d7c12b8 100644
--- a/src/gui/CMakeLists.txt
+++ b/src/gui/CMakeLists.txt
@@ -32,6 +32,7 @@ set(client_UI
owncloudsetuppage.ui
addcertificatedialog.ui
proxyauthdialog.ui
+ notificationwidget.ui
wizard/owncloudadvancedsetuppage.ui
wizard/owncloudconnectionmethoddialog.ui
wizard/owncloudhttpcredspage.ui
@@ -84,6 +85,8 @@ set(client_SRCS
proxyauthhandler.cpp
proxyauthdialog.cpp
synclogdialog.cpp
+ notificationwidget.cpp
+ notificationconfirmjob.cpp
creds/credentialsfactory.cpp
creds/httpcredentialsgui.cpp
creds/shibbolethcredentials.cpp
diff --git a/src/gui/activitywidget.cpp b/src/gui/activitywidget.cpp
index 2fa67fa..0347b43 100644
--- a/src/gui/activitywidget.cpp
+++ b/src/gui/activitywidget.cpp
@@ -33,6 +33,8 @@
#include "activityitemdelegate.h"
#include "protocolwidget.h"
#include "QProgressIndicator.h"
+#include "notificationwidget.h"
+#include "notificationconfirmjob.h"
#include "ui_activitywidget.h"
@@ -52,6 +54,20 @@ QString ActivityList::accountName() const
/* ==================================================================== */
+QHash <QString, QVariant> ActivityLink::toVariantHash()
+{
+ QHash<QString, QVariant> hash;
+
+ hash["label"] = _label;
+ hash["link"] = _link;
+ hash["verb"] = _verb;
+ hash["primary"] = _isPrimary;
+
+ return hash;
+}
+
+/* ==================================================================== */
+
ActivityListModel::ActivityListModel(QWidget *parent)
:QAbstractListModel(parent)
{
@@ -176,6 +192,7 @@ void ActivityListModel::slotActivitiesReceived(const QVariantMap& json, int stat
auto json = activ.toMap();
Activity a;
+ a._type = Activity::ActivityType;
a._accName = ast->account()->displayName();
a._id = json.value("id").toLongLong();
a._subject = json.value("subject").toString();
@@ -277,6 +294,16 @@ ActivityWidget::ActivityWidget(QWidget *parent) :
_ui->_activityList->setAlternatingRowColors(true);
_ui->_activityList->setModel(_model);
+ _ui->_notifyLabel->hide();
+ _ui->_notifyScroll->hide();
+
+ // Create a widget container for the notifications. The ui file defines
+ // a scroll area that get a widget with a layout as children
+ QWidget *w = new QWidget(this);
+ _notificationsLayout = new QVBoxLayout(this);
+ w->setLayout(_notificationsLayout);
+ _ui->_notifyScroll->setWidget(w);
+
showLabels();
connect(_model, SIGNAL(activityJobStatusCode(AccountState*,int)),
@@ -290,6 +317,9 @@ ActivityWidget::ActivityWidget(QWidget *parent) :
connect( _ui->_activityList, SIGNAL(activated(QModelIndex)), this,
SLOT(slotOpenFile(QModelIndex)));
+
+ connect( this, SIGNAL(newNotificationList(ActivityList)), this,
+ SLOT(slotBuildNotificationDisplay(ActivityList)) );
}
ActivityWidget::~ActivityWidget()
@@ -300,6 +330,7 @@ ActivityWidget::~ActivityWidget()
void ActivityWidget::slotRefresh(AccountState *ptr)
{
_model->slotRefreshActivity(ptr);
+ slotFetchNotifications(ptr);
}
void ActivityWidget::slotRemoveAccount( AccountState *ptr )
@@ -313,6 +344,8 @@ void ActivityWidget::showLabels()
_ui->_headerLabel->setTextFormat(Qt::RichText);
_ui->_headerLabel->setText(t);
+ _ui->_notifyLabel->setText(tr("Action Required: Notifications"));
+
t.clear();
QSetIterator<QString> i(_accountsWithoutActivities);
while (i.hasNext() ) {
@@ -400,6 +433,137 @@ void ActivityWidget::slotOpenFile(QModelIndex indx)
}
}
+void ActivityWidget::slotFetchNotifications(AccountState *ptr)
+{
+ /* start the notification fetch job as well */
+ if( !ptr) {
+ return;
+ }
+
+ // if the previous notification job has finished, start next.
+ if( !_notificationJob ) {
+ _notificationJob = new JsonApiJob( ptr->account(), QLatin1String("ocs/v2.php/apps/notifications/api/v1/notifications"), this );
+ QObject::connect(_notificationJob.data(), SIGNAL(jsonReceived(QVariantMap, int)),
+ this, SLOT(slotNotificationsReceived(QVariantMap, int)));
+ _notificationJob->setProperty("AccountStatePtr", QVariant::fromValue<AccountState*>(ptr));
+
+ qDebug() << "Start fetching notifications for " << ptr->account()->displayName();
+ _notificationJob->start();
+ } else {
+ qDebug() << "Notification Job still running, not starting a new one.";
+ }
+}
+
+
+void ActivityWidget::slotNotificationsReceived(const QVariantMap& json, int statusCode)
+{
+ if( statusCode != 200 ) {
+ qDebug() << "Failed for Notifications";
+ return;
+ }
+
+ auto notifies = json.value("ocs").toMap().value("data").toList();
+
+ AccountState* ai = qvariant_cast<AccountState*>(sender()->property("AccountStatePtr"));
+
+ qDebug() << "Notifications for " << ai->account()->displayName() << notifies;
+
+ ActivityList list;
+
+ foreach( auto element, notifies ) {
+ Activity a;
+ auto json = element.toMap();
+ a._type = Activity::NotificationType;
+ a._accName = ai->account()->displayName();
+ a._id = json.value("notification_id").toLongLong();
+ a._subject = json.value("subject").toString();
+ a._message = json.value("message").toString();
+ QString s = json.value("link").toString();
+ if( !s.isEmpty() ) {
+ a._link = QUrl(s);
+ }
+ a._dateTime = json.value("datetime").toDateTime();
+ a._dateTime.setTimeSpec(Qt::UTC);
+
+ auto actions = json.value("actions").toList();
+ foreach( auto action, actions) {
+ auto actionJson = action.toMap();
+ ActivityLink al;
+ al._label = QUrl::fromPercentEncoding(actionJson.value("label").toByteArray());
+ al._link = actionJson.value("link").toString();
+ al._verb = actionJson.value("type").toString();
+ al._isPrimary = actionJson.value("primary").toBool();
+
+ a._links.append(al);
+ }
+
+ list.append(a);
+ }
+ emit newNotificationList( list );
+}
+
+// GUI: Display the notifications
+void ActivityWidget::slotBuildNotificationDisplay(const ActivityList& list)
+{
+ foreach( auto activity, list ) {
+ NotificationWidget *widget = 0;
+
+ if( _widgetForNotifId.contains(activity._id) ) {
+ widget = _widgetForNotifId[activity._id];
+ } else {
+ widget = new NotificationWidget(this);
+ connect(widget, SIGNAL(sendNotificationRequest(QString, QString, QString)),
+ this, SLOT(slotSendNotificationRequest(QString, QString, QString)));
+ _notificationsLayout->addWidget(widget);
+ // _ui->_notifyScroll->setMinimumHeight( widget->height());
+ _ui->_notifyScroll->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContentsOnFirstShow);
+ _widgetForNotifId[activity._id] = widget;
+ }
+
+ widget->setAccountName( activity._accName );
+ widget->setActivity( activity );
+ }
+ _ui->_notifyLabel->setHidden( list.count() == 0 );
+ _ui->_notifyScroll->setHidden( list.count() == 0 );
+}
+
+void ActivityWidget::slotSendNotificationRequest(const QString& accountName, const QString& link, const QString& verb)
+{
+ qDebug() << "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());
+ QString myLink(link);
+ QUrl l(myLink);
+ job->setLinkAndVerb(l, verb);
+ connect( job, SIGNAL( networkError(QNetworkReply*)),
+ this, SLOT(slotNotifyNetworkError(QNetworkReply*)));
+ connect( job, SIGNAL( jobFinished(QString, int)),
+ this, SLOT(slotNotifyServerFinished(QString, int)) );
+ job->start();
+ }
+ } else {
+ qDebug() << "Invalid verb:" << verb;
+ }
+}
+
+
+void ActivityWidget::slotNotifyNetworkError( QNetworkReply* )
+{
+ qDebug() << "Server notify job failed.";
+}
+
+void ActivityWidget::slotNotifyServerFinished( const QString& reply, int replyCode )
+{
+ // FIXME: remove the widget after a couple of seconds
+ qDebug() << "Server Notification reply code"<< replyCode << reply;
+
+}
+
/* ==================================================================== */
ActivitySettings::ActivitySettings(QWidget *parent)
diff --git a/src/gui/activitywidget.h b/src/gui/activitywidget.h
index c3ba5ca..c27724c 100644
--- a/src/gui/activitywidget.h
+++ b/src/gui/activitywidget.h
@@ -33,6 +33,8 @@ namespace OCC {
class Account;
class AccountStatusPtr;
class ProtocolWidget;
+class JsonApiJob;
+class NotificationWidget;
namespace Ui {
class ActivityWidget;
@@ -40,6 +42,23 @@ namespace Ui {
class Application;
/**
+ * @brief The ActivityLink class describes actions of an activity
+ *
+ * These are part of notifications which are mapped into activities.
+ */
+
+class ActivityLink
+{
+public:
+ QHash <QString, QVariant> toVariantHash();
+
+ QString _label;
+ QString _link;
+ QString _verb;
+ bool _isPrimary;
+};
+
+/**
* @brief Activity Structure
* @ingroup gui
*
@@ -49,6 +68,11 @@ class Application;
class Activity
{
public:
+ enum Type {
+ ActivityType,
+ NotificationType
+ };
+ Type _type;
qlonglong _id;
QString _subject;
QString _message;
@@ -57,6 +81,7 @@ public:
QDateTime _dateTime;
QString _accName;
+ QVector <ActivityLink> _links;
/**
* @brief Sort operator to sort the list youngest first.
* @param val
@@ -146,12 +171,21 @@ public slots:
void slotRefresh(AccountState* ptr);
void slotRemoveAccount( AccountState *ptr );
void slotAccountActivityStatus(AccountState *ast, int statusCode);
+ void slotFetchNotifications(AccountState *ptr);
signals:
void guiLog(const QString&, const QString&);
void copyToClipboard();
void rowsInserted();
void hideAcitivityTab(bool);
+ void newNotificationList(const ActivityList& list);
+
+private slots:
+ void slotNotificationsReceived(const QVariantMap& json, int statusCode);
+ void slotBuildNotificationDisplay(const ActivityList& list);
+ void slotSendNotificationRequest(const QString &accountName, const QString& link, const QString& verb);
+ void slotNotifyNetworkError( QNetworkReply* );
+ void slotNotifyServerFinished( const QString& reply, int replyCode );
private:
void showLabels();
@@ -160,8 +194,10 @@ private:
QPushButton *_copyBtn;
QSet<QString> _accountsWithoutActivities;
-
+ QMap<int, NotificationWidget*> _widgetForNotifId;
+ QPointer<JsonApiJob> _notificationJob;
ActivityListModel *_model;
+ QVBoxLayout *_notificationsLayout;
};
diff --git a/src/gui/activitywidget.ui b/src/gui/activitywidget.ui
index eb48941..fefd7b3 100644
--- a/src/gui/activitywidget.ui
+++ b/src/gui/activitywidget.ui
@@ -15,23 +15,60 @@
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
- <widget class="QLabel" name="_headerLabel">
+ <widget class="QLabel" name="_notifyLabel">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="1" column="0">
- <widget class="QListView" name="_activityList"/>
+ <widget class="QScrollArea" name="_notifyScroll">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="widgetResizable">
+ <bool>true</bool>
+ </property>
+ <widget class="QWidget" name="_scrollAreaWidgetContents">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>677</width>
+ <height>70</height>
+ </rect>
+ </property>
+ </widget>
+ </widget>
</item>
<item row="2" column="0">
- <widget class="QLabel" name="_bottomLabel">
+ <widget class="QLabel" name="_headerLabel">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="3" column="0">
+ <widget class="QListView" name="_activityList">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="_bottomLabel">
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0">
<widget class="QDialogButtonBox" name="_dialogButtonBox"/>
</item>
</layout>
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-owncloud/owncloud-client.git
More information about the Pkg-owncloud-commits
mailing list