Merge branch 'master' into issues/494

This commit is contained in:
Camila Ayres 2018-08-13 17:42:53 +02:00 committed by GitHub
commit 8e8a619ee1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 10 additions and 526 deletions

View file

@ -33,7 +33,6 @@ set(client_UI_SRCS
sslerrordialog.ui
addcertificatedialog.ui
proxyauthdialog.ui
notificationwidget.ui
mnemonicdialog.ui
wizard/owncloudadvancedsetuppage.ui
wizard/owncloudconnectionmethoddialog.ui
@ -95,7 +94,6 @@ set(client_SRCS
proxyauthdialog.cpp
synclogdialog.cpp
tooltipupdater.cpp
notificationwidget.cpp
notificationconfirmjob.cpp
servernotificationhandler.cpp
guiutility.cpp

View file

@ -30,7 +30,6 @@
#include "accountmanager.h"
#include "activityitemdelegate.h"
#include "QProgressIndicator.h"
#include "notificationwidget.h"
#include "notificationconfirmjob.h"
#include "servernotificationhandler.h"
#include "theme.h"
@ -85,7 +84,6 @@ ActivityWidget::ActivityWidget(AccountState *accountState, QWidget *parent)
connect(delegate, &ActivityItemDelegate::primaryButtonClickedOnItemView, this, &ActivityWidget::slotPrimaryButtonClickedOnListView);
connect(delegate, &ActivityItemDelegate::secondaryButtonClickedOnItemView, this, &ActivityWidget::slotSecondaryButtonClickedOnListView);
connect(_ui->_activityList, &QListView::activated, this, &ActivityWidget::slotOpenFile);
connect(&_removeTimer, &QTimer::timeout, this, &ActivityWidget::slotCheckToCleanWidgets);
connect(ProgressDispatcher::instance(), &ProgressDispatcher::progressInfo,
this, &ActivityWidget::slotProgressInfo);
@ -347,7 +345,7 @@ void ActivityWidget::slotAccountActivityStatus(int statusCode)
_accountsWithoutActivities.remove(_accountState->account()->displayName());
}
checkActivityTabVisibility();
checkActivityWidgetVisibility();
showLabels();
}
@ -398,16 +396,15 @@ void ActivityWidget::storeActivityList(QTextStream &ts)
}
}
void ActivityWidget::checkActivityTabVisibility()
void ActivityWidget::checkActivityWidgetVisibility()
{
int accountCount = AccountManager::instance()->accounts().count();
bool hasAccountsWithActivity =
_accountsWithoutActivities.count() != accountCount;
bool hasNotifications = !_widgetForNotifId.isEmpty();
_ui->_activityList->setVisible(hasAccountsWithActivity);
emit hideActivityTab(!hasAccountsWithActivity && !hasNotifications);
emit hideActivityTab(!hasAccountsWithActivity);
}
void ActivityWidget::slotOpenFile(QModelIndex indx)
@ -508,7 +505,7 @@ void ActivityWidget::slotSendNotificationRequest(const QString &accountName, con
}
}
void ActivityWidget::endNotificationRequest(NotificationWidget *widget, int replyCode)
void ActivityWidget::endNotificationRequest(int replyCode)
{
_notificationRequestsRunning--;
slotNotificationRequestFinished(replyCode);
@ -523,7 +520,7 @@ void ActivityWidget::slotNotifyNetworkError(QNetworkReply *reply)
int resultCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
endNotificationRequest(job->widget(), resultCode);
endNotificationRequest(resultCode);
qCWarning(lcActivity) << "Server notify job failed with code " << resultCode;
}
@ -534,72 +531,10 @@ void ActivityWidget::slotNotifyServerFinished(const QString &reply, int replyCod
return;
}
endNotificationRequest(job->widget(), replyCode);
endNotificationRequest(replyCode);
qCInfo(lcActivity) << "Server Notification reply code" << replyCode << reply;
// if the notification was successful start a timer that triggers
// removal of the done widgets in a few seconds
// Add 200 millisecs to the predefined value to make sure that the timer in
// widget's method readyToClose() has elapsed.
if (replyCode == OCS_SUCCESS_STATUS_CODE || replyCode == OCS_SUCCESS_STATUS_CODE_V2) {
//scheduleWidgetToRemove(job->widget());
}
}
// blacklist the activity coming in here.
void ActivityWidget::slotRequestCleanupAndBlacklist(const Activity &blacklistActivity)
{
if (!_blacklistedNotifications.contains(blacklistActivity)) {
_blacklistedNotifications.append(blacklistActivity);
}
NotificationWidget *widget = _widgetForNotifId[blacklistActivity.ident()];
scheduleWidgetToRemove(widget);
}
void ActivityWidget::scheduleWidgetToRemove(NotificationWidget *widget, int milliseconds)
{
if (!widget) {
return;
}
// in five seconds from now, remove the widget.
QDateTime removeTime = QDateTime::currentDateTimeUtc().addMSecs(milliseconds);
QDateTime &it = _widgetsToRemove[widget];
if (!it.isValid() || it > removeTime) {
it = removeTime;
}
if (!_removeTimer.isActive()) {
_removeTimer.start();
}
}
// Called every second to see if widgets need to be removed.
void ActivityWidget::slotCheckToCleanWidgets()
{
auto currentTime = QDateTime::currentDateTimeUtc();
auto it = _widgetsToRemove.begin();
while (it != _widgetsToRemove.end()) {
// loop over all widgets in the to-remove queue
QDateTime t = it.value();
NotificationWidget *widget = it.key();
if (currentTime > t) {
// found one to remove!
Activity::Identifier id = widget->activity().ident();
_widgetForNotifId.remove(id);
widget->deleteLater();
it = _widgetsToRemove.erase(it);
} else {
++it;
}
}
if (_widgetsToRemove.isEmpty()) {
_removeTimer.stop();
}
}
/* ==================================================================== */
ActivitySettings::ActivitySettings(AccountState *accountState, QWidget *parent)

View file

@ -37,7 +37,6 @@ namespace OCC {
class Account;
class AccountStatusPtr;
class JsonApiJob;
class NotificationWidget;
class ActivityListModel;
namespace Ui {
@ -68,7 +67,7 @@ public:
* Based on whether activities are enabled and whether notifications are
* available.
*/
void checkActivityTabVisibility();
void checkActivityWidgetVisibility();
public slots:
void slotOpenFile(QModelIndex indx);
@ -76,7 +75,6 @@ public slots:
void slotRefreshNotifications();
void slotRemoveAccount();
void slotAccountActivityStatus(int statusCode);
void slotRequestCleanupAndBlacklist(const Activity &blacklistActivity);
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);
@ -93,9 +91,7 @@ private slots:
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(NotificationWidget *widget, int replyCode);
void scheduleWidgetToRemove(NotificationWidget *widget, int milliseconds = 100);
void slotCheckToCleanWidgets();
void endNotificationRequest(int replyCode);
void slotNotificationRequestFinished(int statusCode);
void slotPrimaryButtonClickedOnListView(const QModelIndex &index);
void slotSecondaryButtonClickedOnListView(const QModelIndex &index);
@ -105,12 +101,10 @@ private:
QString timeString(QDateTime dt, QLocale::FormatType format) const;
Ui::ActivityWidget *_ui;
QSet<QString> _accountsWithoutActivities;
QMap<Activity::Identifier, NotificationWidget *> _widgetForNotifId;
QElapsedTimer _guiLogTimer;
QSet<int> _guiLoggedNotifications;
ActivityList _blacklistedNotifications;
QHash<NotificationWidget *, QDateTime> _widgetsToRemove;
QTimer _removeTimer;
// number of currently running notification requests. If non zero,

View file

@ -20,11 +20,10 @@
namespace OCC {
Q_DECLARE_LOGGING_CATEGORY(lcNotifications)
Q_LOGGING_CATEGORY(lcNotificationsJob, "nextcloud.gui.notifications", QtInfoMsg)
NotificationConfirmJob::NotificationConfirmJob(AccountPtr account)
: AbstractNetworkJob(account, "")
, _widget(0)
{
setIgnoreCredentialFailure(true);
}
@ -35,20 +34,10 @@ void NotificationConfirmJob::setLinkAndVerb(const QUrl &link, const QByteArray &
_verb = verb;
}
void NotificationConfirmJob::setWidget(NotificationWidget *widget)
{
_widget = widget;
}
NotificationWidget *NotificationConfirmJob::widget()
{
return _widget;
}
void NotificationConfirmJob::start()
{
if (!_link.isValid()) {
qCWarning(lcNotifications) << "Attempt to trigger invalid URL: " << _link.toString();
qCWarning(lcNotificationsJob) << "Attempt to trigger invalid URL: " << _link.toString();
return;
}
QNetworkRequest req;

View file

@ -25,8 +25,6 @@
namespace OCC {
class NotificationWidget;
/**
* @brief The NotificationConfirmJob class
* @ingroup gui
@ -54,20 +52,6 @@ public:
*/
void start() Q_DECL_OVERRIDE;
/**
* @brief setWidget stores the associated widget to be able to use
* it when the job has finished
* @param widget pointer to the notification widget to store
*/
void setWidget(NotificationWidget *widget);
/**
* @brief widget - get the associated notification widget as stored
* with setWidget method.
* @return widget pointer to the notification widget
*/
NotificationWidget *widget();
signals:
/**
@ -83,7 +67,6 @@ private slots:
private:
QByteArray _verb;
QUrl _link;
NotificationWidget *_widget;
};
}

View file

@ -1,169 +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 "notificationwidget.h"
#include "QProgressIndicator.h"
#include "common/utility.h"
#include "common/asserts.h"
#include "guiutility.h"
#include <QPushButton>
#include "ocsjob.h"
namespace OCC {
Q_LOGGING_CATEGORY(lcNotifications, "nextcloud.gui.notifications", QtInfoMsg)
NotificationWidget::NotificationWidget(QWidget *parent)
: QWidget(parent)
{
_ui.setupUi(this);
_progressIndi = new QProgressIndicator(this);
_ui.horizontalLayout->addWidget(_progressIndi);
}
void NotificationWidget::setActivity(const Activity &activity)
{
_myActivity = activity;
_accountName = activity._accName;
ASSERT(!_accountName.isEmpty());
_ui._subjectLabel->setVisible(!activity._subject.isEmpty());
_ui._messageLabel->setVisible(!activity._message.isEmpty());
_ui._subjectLabel->setText(activity._subject);
_ui._messageLabel->setText(activity._message);
_ui._notifIcon->setPixmap(QPixmap(":/client/resources/bell.svg"));
_ui._notifIcon->setMinimumWidth(22);
_ui._notifIcon->setMinimumHeight(22);
_ui._notifIcon->show();
QString tText = tr("%1").arg(Utility::timeAgoInWords(activity._dateTime));
_ui._timeLabel->setText(tText);
// always remove the buttons
foreach (auto button, _ui._buttonBox->buttons()) {
_ui._buttonBox->removeButton(button);
}
_buttons.clear();
// open the notification in the browser if there is a link
if(!_myActivity._link.isEmpty()){
QString buttonText(tr("More information"));
QPushButton *openBrowser = _ui._buttonBox->addButton(buttonText, QDialogButtonBox::AcceptRole);
openBrowser->setDefault(true);
connect(openBrowser, &QAbstractButton::clicked, this, &NotificationWidget::slotOpenBrowserButtonClicked);
_buttons.prepend(openBrowser);
}
// display buttons for the links
if (activity._links.isEmpty()) {
// is there any case where this code is executed?
// in case there is no action defined, do a close button.
QPushButton *b = _ui._buttonBox->addButton(QDialogButtonBox::Close);
b->setDefault(true);
connect(b, &QAbstractButton::clicked, this, &NotificationWidget::slotButtonClicked);
_buttons.append(b);
} else {
foreach (auto link, activity._links) {
QPushButton *b = _ui._buttonBox->addButton(link._label, QDialogButtonBox::AcceptRole);
b->setDefault(link._isPrimary);
connect(b, &QAbstractButton::clicked, this, &NotificationWidget::slotButtonClicked);
_buttons.append(b);
}
}
}
Activity NotificationWidget::activity() const
{
return _myActivity;
}
void NotificationWidget::slotOpenBrowserButtonClicked(){
QUrl url(_myActivity._link);
Utility::openBrowser(url, this);
}
void NotificationWidget::slotButtonClicked()
{
QObject *buttonWidget = QObject::sender();
int index = -1;
if (buttonWidget) {
// find the button that was clicked, it has to be in the list
// of buttons that were added to the button box before.
for (int i = 0; i < _buttons.count(); i++) {
if (_buttons.at(i) == buttonWidget) {
index = i;
}
_buttons.at(i)->setEnabled(false);
}
// there is an extra button: 'Open'
if(!_myActivity._link.isEmpty())
index--;
// if the button was found, the link must be called
if (index > -1 && _myActivity._links.count() == 0) {
// no links, that means it was the close button
// empty link. Just close and remove the widget.
QString doneText = tr("Closing in a few seconds...");
_ui._timeLabel->setText(doneText);
emit requestCleanupAndBlacklist(_myActivity);
return;
}
if (index > -1 && index < _myActivity._links.count()) {
ActivityLink triggeredLink = _myActivity._links.at(index);
_actionLabel = triggeredLink._label;
if (!triggeredLink._link.isEmpty()) {
qCInfo(lcNotifications) << "Notification Link: " << triggeredLink._verb << triggeredLink._link;
_progressIndi->startAnimation();
emit sendNotificationRequest(_accountName, triggeredLink._link, triggeredLink._verb);
}
}
}
}
void NotificationWidget::slotNotificationRequestFinished(int statusCode)
{
int i = 0;
QString doneText;
QLocale locale;
QString timeStr = locale.toString(QTime::currentTime());
// 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(lcNotifications) << "Notification Request to Server failed, leave button visible.";
for (i = 0; i < _buttons.count(); i++) {
_buttons.at(i)->setEnabled(true);
}
//: The second parameter is a time, such as 'failed at 09:58pm'
doneText = tr("%1 request failed at %2").arg(_actionLabel, timeStr);
} else {
// the call to the ocs API succeeded.
_ui._buttonBox->hide();
//: The second parameter is a time, such as 'selected at 09:58pm'
doneText = tr("'%1' selected at %2").arg(_actionLabel, timeStr);
}
_ui._timeLabel->setText(doneText);
_progressIndi->stopAnimation();
}
}

View file

@ -1,61 +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 NOTIFICATIONWIDGET_H
#define NOTIFICATIONWIDGET_H
#include <QWidget>
#include "activitydata.h"
#include "ui_notificationwidget.h"
#define NOTIFICATION_WIDGET_CLOSE_AFTER_MILLISECS 4800
class QProgressIndicator;
namespace OCC {
class NotificationWidget : public QWidget
{
Q_OBJECT
public:
explicit NotificationWidget(QWidget *parent = 0);
bool readyToClose();
Activity activity() const;
signals:
void sendNotificationRequest(const QString &, const QString &link, const QByteArray &verb);
void requestCleanupAndBlacklist(const Activity &activity);
public slots:
void setActivity(const Activity &activity);
void slotNotificationRequestFinished(int statusCode);
private slots:
void slotButtonClicked();
void slotOpenBrowserButtonClicked();
private:
Ui_NotificationWidget _ui;
Activity _myActivity;
QList<QPushButton *> _buttons;
QString _accountName;
QProgressIndicator *_progressIndi;
QString _actionLabel;
};
}
#endif // NOTIFICATIONWIDGET_H

View file

@ -1,185 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>NotificationWidget</class>
<widget class="QWidget" name="NotificationWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>725</width>
<height>129</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="sizeConstraint">
<enum>QLayout::SetMaximumSize</enum>
</property>
<property name="leftMargin">
<number>24</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>26</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="horizontalSpacing">
<number>0</number>
</property>
<property name="verticalSpacing">
<number>2</number>
</property>
<item row="0" column="1">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<layout class="QHBoxLayout" name="labelsHorizontalLayout" stretch="1,1">
<property name="spacing">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<item>
<widget class="QLabel" name="_notifIcon">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap>../../resources/bell.svg</pixmap>
</property>
<property name="alignment">
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
<property name="margin">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="_subjectLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Lorem ipsum dolor sit amet</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="_messageLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod temporm </string>
</property>
<property name="scaledContents">
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="margin">
<number>0</number>
</property>
<property name="indent">
<number>28</number>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>6</number>
</property>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>28</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="_timeLabel">
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
<property name="text">
<string>TextLabel</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="_buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>