Merge pull request #17 from QuasarApp/task_258

Notification history view
This commit is contained in:
Snegovoy Alex 2023-04-17 15:45:31 +03:00 committed by GitHub
commit 1fe2d4c6cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 482 additions and 16 deletions

View File

@ -16,6 +16,7 @@
<file>qmlNotify_languages/fr.qm</file>
<file>qmlNotify_languages/de.qm</file>
<file>qmlNotify_languages/zh.qm</file>
<file>NotifyModule/NotificationHistoryView.qml</file>
</qresource>
<qresource prefix="/icons">
<file alias="warning">icons/Warning.png</file>

View File

@ -61,6 +61,15 @@ BasePopUp {
Layout.fillWidth: true
}
ToolButton {
text: String.fromCharCode(0x2630)
font.pointSize: 10
onClicked: {
history.open()
popup.close()
}
}
ToolButton {
text: "X"
onClicked: {
@ -151,10 +160,9 @@ BasePopUp {
}
}
}
title: titleText
}

View File

@ -0,0 +1,120 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Controls.Material 2.15
import QtQuick.Layouts 1.3
Dialog {
id: root
readonly property var historyModel: notificationService.history
header: ToolBar {
id: toolbar
ToolButton {
id: clearAllButton
text: qsTr("clear")
height: parent.height
anchors {
left: parent.left
verticalCenter: parent.verticalCenter
}
onClicked: historyModel.clearAllHistory()
}
Label {
id: toolbarTitle
text: qsTr("Notifications")
anchors {
horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
}
}
}
contentItem: ListView {
id: notificationLV
clip: true
spacing: 10
model: historyModel
ScrollBar.vertical: ScrollBar {}
delegate: SwipeDelegate {
id: swipeDelegate
text: model.notificationValue
width: notificationLV.width
ListView.onRemove: SequentialAnimation {
PropertyAction {
target: swipeDelegate
property: "ListView.delayRemove"
value: true
}
NumberAnimation {
target: swipeDelegate
property: "x"
to: -swipeDelegate.width
duration: 200
easing.type: Easing.InOutQuad
}
PropertyAction {
target: swipeDelegate;
property: "ListView.delayRemove"
value: false
}
}
contentItem: RowLayout {
Image {
id: image
Layout.preferredWidth: toolbar.height;
Layout.preferredHeight: toolbar.height;
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
fillMode: Image.PreserveAspectCrop
clip: true
source: model.icon
}
ColumnLayout {
Label {
id: notificationTitle
text: model.title
elide: Label.ElideRight
}
Label {
id: notificationText
text: model.text
elide: Label.ElideRight
linkColor: Material.accent
wrapMode: Text.WordWrap
Layout.fillWidth: true
}
}
}
swipe.right: Label {
id: deleteLabel
text: qsTr("Delete")
color: "white"
verticalAlignment: Label.AlignVCenter
padding: 12
height: parent.height
anchors.right: parent.right
SwipeDelegate.onClicked: notificationLV.model.removeNotificationItemAtIndex(index)
background: Rectangle {
color: "red"
}
}
}
}
}

View File

@ -73,4 +73,19 @@ Item {
questionMsgBox._show();
}
}
NotificationHistoryView {
id: history
width: Math.min(Math.max(Math.min(parent.width * 0.6, 1024 ), 320), parent.width)
height: Math.min(Math.max(Math.min(parent.height * 0.6, 720), 240), parent.height)
anchors.centerIn: parent
}
Connections {
target: model
function onSigShowHistory() {
history.open()
}
}
}

View File

@ -0,0 +1,65 @@
#include "historynotificationsmodel.h"
#include <QDebug>
HistoryNotificationsModel::HistoryNotificationsModel(QObject *parent)
: QAbstractListModel{parent} {
}
int HistoryNotificationsModel::rowCount(const QModelIndex &parent) const {
Q_UNUSED(parent);
return notificationsList.count();
}
QVariant HistoryNotificationsModel::data(const QModelIndex &index, int role) const {
if(index.row() < 0 || index.row() >= notificationsList.count())
return QVariant();
switch (role) {
case Icon:
return notificationsList.at(index.row()).img();
case Title:
return notificationsList.at(index.row()).title();
case Message:
return notificationsList.at(index.row()).text();
case Type:
return notificationsList.at(index.row()).type();
default:
break;
}
return QVariant();
}
QHash<int, QByteArray> HistoryNotificationsModel::roleNames() const {
QHash<int, QByteArray> roles;
roles[Icon] = "icon";
roles[Title] = "title";
roles[Message] = "text";
roles[Type] = "type";
return roles;
}
void HistoryNotificationsModel::addHistoryObject(const QmlNotificationService::NotificationData &notificationData) {
beginInsertRows({}, rowCount({}), rowCount({}));
notificationsList.append(notificationData);
endInsertRows();
}
void HistoryNotificationsModel::setHistory(const QList<QmlNotificationService::NotificationData> &historyList) {
notificationsList = std::move(historyList);
}
void HistoryNotificationsModel::clearAllHistory() {
beginResetModel();
notificationsList.clear();
endResetModel();
}
void HistoryNotificationsModel::removeNotificationItemAtIndex(const int elementIndex) {
beginRemoveRows({}, elementIndex, elementIndex);
notificationsList.removeAt(elementIndex);
endRemoveRows();
}

View File

@ -0,0 +1,33 @@
#ifndef HISTORYNOTIFICATIONMODEL_H
#define HISTORYNOTIFICATIONMODEL_H
#include <QAbstractListModel>
#include "notificationdata.h"
class HistoryNotificationsModel : public QAbstractListModel
{
Q_OBJECT
enum Roles {
Icon = Qt::UserRole + 1,
Title,
Message,
Type
};
public:
explicit HistoryNotificationsModel(QObject *parent = nullptr);
int rowCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
QHash<int, QByteArray> roleNames() const override;
void addHistoryObject(const QmlNotificationService::NotificationData &notificationData);
void setHistory(const QList<QmlNotificationService::NotificationData> &historyList);
Q_INVOKABLE void clearAllHistory();
Q_INVOKABLE void removeNotificationItemAtIndex(const int index);
private:
QList<QmlNotificationService::NotificationData> notificationsList;
};
#endif // HISTORYNOTIFICATIONMODEL_H

View File

@ -1,4 +1,4 @@
/*
/*
* Copyright (C) 2018-2023 QuasarApp.
* Distributed under the GPLv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
@ -23,6 +23,14 @@ QString NotificationData::text() const {
}
QString NotificationData::img() const {
const QString imageSrc = imgSrc();
if(imageSrc.size())
return imageSrc;
return this->getDefaultImage(_type);
}
QString NotificationData::imgSrc() const {
return _img;
}
@ -41,6 +49,22 @@ bool NotificationData::operator !=(const NotificationData &righ) {
return !operator==(righ);
}
QString NotificationData::getDefaultImage(const int code) const {
const auto notificationType = static_cast<NotificationData::Type>(code);
switch (notificationType) {
case NotificationData::Type::Normal:
return "qrc:/icons/info";
case NotificationData::Type::Warning:
return "qrc:/icons/warning";
case NotificationData::Type::Error:
return "qrc:/icons/error";
default:
return "";
}
}
int NotificationData::type() const {
return _type;
}

View File

@ -45,11 +45,18 @@ public:
Q_INVOKABLE QString text() const;
/**
* @brief img This method return url to image of a question/notification object.
* @return url of image.
* @brief img This method return url to image of a question/notification object if url is empty then return default question/notification image.
* @return url of image or url of default image.
*/
Q_INVOKABLE QString img() const;
/**
* @brief imgSrc This method return url to image of a question/notification object.
* @return url of image.
*/
QString imgSrc() const;
/**
* @brief title This method return title of a question/notification object.
* @return title of a question/notification object.
@ -78,6 +85,8 @@ public:
bool operator !=(const NotificationData &righ);
private:
QString getDefaultImage(const int code) const;
QString _text;
QString _img;
QString _title;

View File

@ -7,13 +7,21 @@
#include "notificationservice.h"
#include <QSharedPointer>
namespace QmlNotificationService {
NotificationService::NotificationService(QObject * ptr): QObject (ptr) {
qRegisterMetaType<NotificationData>("NotificationData");
qRegisterMetaType<QList<NotificationData>> ("QList<NotificationData>");
_history = new HistoryNotificationsModel();
QQmlEngine::setObjectOwnership(_history, QQmlEngine::CppOwnership);
connect(_history, &HistoryNotificationsModel::rowsInserted, this, &NotificationService::countNotificationsChanged);
connect(_history, &HistoryNotificationsModel::rowsRemoved, this, &NotificationService::countNotificationsChanged);
connect(_history, &HistoryNotificationsModel::modelReset, this, &NotificationService::countNotificationsChanged);
}
NotificationService::~NotificationService() {
delete _history;
}
NotificationData NotificationService::notify() const {
@ -25,9 +33,9 @@ NotificationData NotificationService::question() const {
}
void NotificationService::setNotify(const NotificationData& notify) {
if (_notify != notify)
_history.push_back(_notify);
if (_notify != notify) {
_history->addHistoryObject(notify);
}
_notify = notify;
emit notifyChanged();
@ -104,8 +112,16 @@ NotificationService *NotificationService::getService() {
return service;
}
const QList<NotificationData> &NotificationService::history() const {
QObject *NotificationService::history() const {
return _history;
}
void NotificationService::showHistory() {
emit sigShowHistory();
}
int NotificationService::notificationsCount() const {
return _history->rowCount({});
}
}

View File

@ -9,9 +9,11 @@
#define NOTIFICATIONSERVICE_H
#include "notificationdata.h"
#include "historynotificationsmodel.h"
#include <QHash>
#include <QObject>
#include <QQmlEngine>
namespace QmlNotificationService {
@ -30,7 +32,9 @@ class NOTIFYSERVICESHARED_EXPORT NotificationService: public QObject
Q_PROPERTY(NotificationData notify READ notify NOTIFY notifyChanged)
Q_PROPERTY(NotificationData question READ question NOTIFY questionChanged)
Q_PROPERTY(QList<NotificationData> history READ history NOTIFY notifyChanged)
Q_PROPERTY(QObject* history READ history NOTIFY notifyChanged)
Q_PROPERTY(int notificationsCount READ notificationsCount NOTIFY countNotificationsChanged)
public:
/**
@ -121,12 +125,26 @@ public:
static NotificationService* getService();
/**
* @brief history - This method used for return notify list.
* @return list of all notify.
* @brief history - This method used for return notify history model.
* @return history model of all notify.
*/
const QList<NotificationData> & history() const;
QObject* history() const;
signals:
/**
* @brief showHistory - This method used for emit signal by which show notification menu.
*/
Q_INVOKABLE void showHistory();
/**
* @brief notificationsCount - This method used for return count of history notifications.
* @return count of history notifications.
*/
Q_INVOKABLE int notificationsCount() const;
~NotificationService();
signals:
/**
* @brief notifyChanged This signal emited whet the notificator (Ths object) received a new notification message.
*/
@ -145,14 +163,21 @@ signals:
*/
void questionCompleted(bool accepted, int questionCode);
void historyListChanged();
void sigShowHistory();
void countNotificationsChanged();
private:
explicit NotificationService(QObject *ptr = nullptr);
QHash<int, Listner> _listners;
NotificationData _question;
NotificationData _notify;
QList<NotificationData> _history;
HistoryNotificationsModel* _history = nullptr;
};
}

View File

@ -8,4 +8,19 @@
<translation>Botschaft</translation>
</message>
</context>
<context>
<name>NotificationHistoryView</name>
<message>
<source>Notifications</source>
<translation>Benachrichtigungen</translation>
</message>
<message>
<source>Delete</source>
<translation>Löschen</translation>
</message>
<message>
<source>clear</source>
<translation>klare</translation>
</message>
</context>
</TS>

View File

@ -8,4 +8,19 @@
<translation>Message</translation>
</message>
</context>
<context>
<name>NotificationHistoryView</name>
<message>
<source>Notifications</source>
<translation>Notifications</translation>
</message>
<message>
<source>Delete</source>
<translation>Delete</translation>
</message>
<message>
<source>clear</source>
<translation>clear</translation>
</message>
</context>
</TS>

View File

@ -8,4 +8,19 @@
<translation>Mensaje</translation>
</message>
</context>
<context>
<name>NotificationHistoryView</name>
<message>
<source>Notifications</source>
<translation>Notificaciones</translation>
</message>
<message>
<source>Delete</source>
<translation>Borrar</translation>
</message>
<message>
<source>clear</source>
<translation>borrar</translation>
</message>
</context>
</TS>

View File

@ -8,4 +8,19 @@
<translation>Un message</translation>
</message>
</context>
<context>
<name>NotificationHistoryView</name>
<message>
<source>Notifications</source>
<translation>Avis</translation>
</message>
<message>
<source>Delete</source>
<translation>Supprimer</translation>
</message>
<message>
<source>clear</source>
<translation>claire</translation>
</message>
</context>
</TS>

View File

@ -8,4 +8,19 @@
<translation></translation>
</message>
</context>
<context>
<name>NotificationHistoryView</name>
<message>
<source>Notifications</source>
<translation></translation>
</message>
<message>
<source>Delete</source>
<translation></translation>
</message>
<message>
<source>clear</source>
<translation></translation>
</message>
</context>
</TS>

View File

@ -8,4 +8,19 @@
<translation>Wiadomość</translation>
</message>
</context>
<context>
<name>NotificationHistoryView</name>
<message>
<source>Notifications</source>
<translation>Powiadomienia</translation>
</message>
<message>
<source>Delete</source>
<translation>Usuwać</translation>
</message>
<message>
<source>clear</source>
<translation>wyczyść</translation>
</message>
</context>
</TS>

View File

@ -8,4 +8,19 @@
<translation>Cообщение</translation>
</message>
</context>
<context>
<name>NotificationHistoryView</name>
<message>
<source>Notifications</source>
<translation>Уведомления</translation>
</message>
<message>
<source>Delete</source>
<translation>Удалить</translation>
</message>
<message>
<source>clear</source>
<translation>очистить</translation>
</message>
</context>
</TS>

View File

@ -8,4 +8,19 @@
<translation>İleti</translation>
</message>
</context>
<context>
<name>NotificationHistoryView</name>
<message>
<source>Notifications</source>
<translation>Bildirimler</translation>
</message>
<message>
<source>Delete</source>
<translation>Silmek</translation>
</message>
<message>
<source>clear</source>
<translation>temizle</translation>
</message>
</context>
</TS>

View File

@ -8,4 +8,19 @@
<translation>Повідомлення</translation>
</message>
</context>
<context>
<name>NotificationHistoryView</name>
<message>
<source>Notifications</source>
<translation>Повідомлення</translation>
</message>
<message>
<source>Delete</source>
<translation>Видалити</translation>
</message>
<message>
<source>clear</source>
<translation>очистити</translation>
</message>
</context>
</TS>

View File

@ -8,4 +8,19 @@
<translation></translation>
</message>
</context>
<context>
<name>NotificationHistoryView</name>
<message>
<source>Notifications</source>
<translation></translation>
</message>
<message>
<source>Delete</source>
<translation></translation>
</message>
<message>
<source>clear</source>
<translation></translation>
</message>
</context>
</TS>