Skip to content

Commit

Permalink
Advanced notification support: icons, colors, margins, 3-lines, ...
Browse files Browse the repository at this point in the history
  • Loading branch information
iiLubos committed Oct 24, 2023
1 parent 01de745 commit c59475e
Show file tree
Hide file tree
Showing 9 changed files with 175 additions and 135 deletions.
10 changes: 10 additions & 0 deletions app/icons/Waiting.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions app/icons/icons.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@
<file>UploadImage.svg</file>
<file>ReachedDataLimitImage.svg</file>
<file>Close.svg</file>
<file>Waiting.svg</file>
</qresource>
</RCC>
2 changes: 1 addition & 1 deletion app/qmlV2/Style.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ const qrCodeIcon = "qrc:/QR Code.svg"
const checkmarkIcon = "qrc:/Checkmark.svg"
const closeButtonIcon = "qrc:/CloseButton.svg"
const closeIcon = "qrc:/Close.svg"
const waitingIcon = "qrc:/Waiting.svg"

// Images
const uploadImage = "qrc:/UploadImage.svg"
Expand All @@ -80,7 +81,6 @@ const ReachedDataLimitImage = "qrc:/ReachedDataLimitImage.svg"
const commonSpacing = 20 * __dp

// Notification
const notificationHeight = 66 * __dp
const notificationRadius = 12 * __dp
const notificationSpace = 3 * __dp

Expand Down
117 changes: 62 additions & 55 deletions app/qmlV2/component/MMNotification.qml
Original file line number Diff line number Diff line change
Expand Up @@ -11,80 +11,87 @@ import QtQuick
import "../Style.js" as Style
import notificationType 1.0

Row {
Rectangle {
id: notification

width: listView.width - 2 * Style.commonSpacing
height: Style.notificationHeight
height: text.height + 2 * 15 * __dp
anchors.horizontalCenter: parent ? parent.horizontalCenter : undefined

readonly property int innerSpacing: 5 * __dp

Rectangle {
width: parent.width
height: parent.height
radius: Style.notificationRadius
color: {
switch( type ) {
case NotificationType.Information: return Style.informative
case NotificationType.Success: return Style.positive
case NotificationType.Warning: return Style.warning
case NotificationType.Error: return Style.negative
default: return Style.positive
}
radius: Style.notificationRadius
color: {
switch( type ) {
case NotificationType.Information: return Style.informative
case NotificationType.Success: return Style.positive
case NotificationType.Warning: return Style.warning
case NotificationType.Error: return Style.negative
default: return Style.positive
}
}

Rectangle {
id: icon
MMIcon {
id: leftIcon

anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: Style.commonSpacing
width: 18 * __dp
height: 18 * __dp
color: text.color
radius: width/2
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 20 * __dp
width: 18 * __dp
height: 18 * __dp
color: text.color
visible: icon !== NotificationType.None
source: {
switch( icon ) {
case NotificationType.None: return Style.checkmarkIcon
case NotificationType.Waiting: return Style.waitingIcon
case NotificationType.Check: return Style.checkmarkIcon
}
}
}

Text {
id: text
Text {
id: text

anchors.verticalCenter: parent.verticalCenter
anchors.left: icon.right
width: parent.width - 3 * Style.commonSpacing - closeButton.width - icon.width
text: message
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignLeft
leftPadding: Style.commonSpacing - notification.innerSpacing
font: Qt.font(Style.t3)
clip: true
color: {
switch( type ) {
case NotificationType.Information: return Style.deepOcean
case NotificationType.Success: return Style.forest
case NotificationType.Warning: return Style.earth
case NotificationType.Error: return Style.grape
}
anchors.verticalCenter: parent.verticalCenter
anchors.left: leftIcon.right
width: parent.width - 3 * Style.commonSpacing - closeButton.width - leftIcon.width
text: message
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignLeft
leftPadding: Style.commonSpacing - notification.innerSpacing
font: Qt.font(Style.t3)
clip: true
maximumLineCount: 3
wrapMode: Text.WordWrap
lineHeight: 1.4
elide: Text.ElideRight
color: {
switch( type ) {
case NotificationType.Information: return Style.deepOcean
case NotificationType.Success: return Style.forest
case NotificationType.Warning: return Style.earth
case NotificationType.Error: return Style.grape
}
}
}

MMIcon {
id: closeButton
MMIcon {
id: closeButton

anchors.right: parent.right
anchors.rightMargin: Style.commonSpacing
anchors.verticalCenter: parent.verticalCenter
scale: maRemove.containsMouse ? 1.2 : 1
source: Style.closeIcon
color: text.color
anchors.right: parent.right
anchors.rightMargin: Style.commonSpacing
anchors.verticalCenter: parent.verticalCenter
scale: maRemove.containsMouse ? 1.2 : 1
source: Style.closeIcon
color: text.color

MouseArea {
id: maRemove
MouseArea {
id: maRemove

anchors.fill: parent
hoverEnabled: true
onClicked: notificationModel.remove(id)
}
anchors.fill: parent
hoverEnabled: true
onClicked: notificationModel.remove(id)
}
}
}
2 changes: 1 addition & 1 deletion app/qmlV2/component/MMNotificationView.qml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Item {

anchors.top: parent.top
width: parent.width
height: Style.notificationHeight * listView.count + spacing * (listView.count - 1)
height: contentHeight
spacing: Style.notificationSpace
clip: true
model: notificationModel
Expand Down
2 changes: 1 addition & 1 deletion gallery/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ int main( int argc, char *argv[] )
#endif

NotificationModel notificationModel;
engine.rootContext()->setContextProperty("notificationModel", &notificationModel);
engine.rootContext()->setContextProperty( "notificationModel", &notificationModel );

// path to local wrapper pages
engine.rootContext()->setContextProperty( "_qmlWrapperPath", QGuiApplication::applicationDirPath() + "/HotReload/qml/pages/" );
Expand Down
76 changes: 40 additions & 36 deletions gallery/notificationmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,22 @@
#include "notificationmodel.h"
#include <QQmlEngine>

Notification::Notification(uint id, const QString &message, uint interval, NotificationType::MessageType type = NotificationType::Information)
Notification::Notification( uint id, const QString &message, uint interval, NotificationType::MessageType type = NotificationType::Information, NotificationType::IconType icon = NotificationType::None )
{
mId = id;
mMessage = message;
mInterval = interval;
mType = type;
mIcon = icon;
}

NotificationModel::NotificationModel(QObject *parent) : QAbstractListModel{parent}
NotificationModel::NotificationModel( QObject *parent ) : QAbstractListModel{parent}
{
qmlRegisterUncreatableType<NotificationType>("notificationType", 1, 0, "NotificationType", "Not creatable as it is an enum type");
qmlRegisterUncreatableType<NotificationType>( "notificationType", 1, 0, "NotificationType", "Not creatable as it is an enum type" );

mTimer = new QTimer(this);
connect(mTimer, &QTimer::timeout, this, &NotificationModel::timerFired);
mTimer->start(1000);

// Initial data
mNotifications << Notification{ nextId(), "Ahoj", 10, NotificationType::Information };
mNotifications << Notification{ nextId(), "Hello all", 5, NotificationType::Information };
mTimer = new QTimer( this );
connect( mTimer, &QTimer::timeout, this, &NotificationModel::timerFired );
mTimer->start( 1000 );
}

NotificationModel::~NotificationModel()
Expand All @@ -39,58 +36,64 @@ NotificationModel::~NotificationModel()

QHash<int, QByteArray> NotificationModel::roleNames() const
{
return {
{ IdRole, "id" },
{ MessageRole, "message" },
{ TypeRole, "type" }
return
{
{ IdRole, "id" },
{ MessageRole, "message" },
{ TypeRole, "type" },
{ IconRole, "icon" }
};
}

int NotificationModel::rowCount(const QModelIndex &parent) const
int NotificationModel::rowCount( const QModelIndex &parent ) const
{
Q_UNUSED(parent)
Q_UNUSED( parent )
return mNotifications.size();
}

QVariant NotificationModel::data(const QModelIndex &index, int role) const
QVariant NotificationModel::data( const QModelIndex &index, int role ) const
{
if (!hasIndex(index.row(), index.column(), index.parent()))
if ( !hasIndex( index.row(), index.column(), index.parent() ) )
return {};

Notification notification = mNotifications.at(index.row());
if (role == IdRole) return notification.id();
if (role == MessageRole) return notification.message();
if (role == TypeRole) return notification.type();
Notification notification = mNotifications.at( index.row() );
if ( role == IdRole ) return notification.id();
if ( role == MessageRole ) return notification.message();
if ( role == TypeRole ) return notification.type();
if ( role == IconRole ) return notification.icon();

return {};
}

// remove item by message
void NotificationModel::remove(uint id)
void NotificationModel::remove( uint id )
{
for(int i=0; i<mNotifications.count(); i++) {
if(mNotifications[i].id() == id) {
beginRemoveRows(QModelIndex(), i, i);
mNotifications.removeAt(i);
for ( int i = 0; i < mNotifications.count(); i++ )
{
if ( mNotifications[i].id() == id )
{
beginRemoveRows( QModelIndex(), i, i );
mNotifications.removeAt( i );
endRemoveRows();

emit dataChanged(createIndex(0, 0), createIndex(rowCount(), 0)); // refresh whole model
emit dataChanged( createIndex( 0, 0 ), createIndex( rowCount(), 0 ) ); // refresh whole model
emit rowCountChanged();
return;
}
}
}

// add new unique message with interval
void NotificationModel::add(const QString &message, uint interval, NotificationType::MessageType type = NotificationType::Information)
void NotificationModel::add( const QString &message, uint interval, NotificationType::MessageType type = NotificationType::Information, NotificationType::IconType icon = NotificationType::None )
{
for(Notification &notification : mNotifications) {
if(notification.message() == message)
for ( Notification &notification : mNotifications )
{
if ( notification.message() == message )
return;
}

beginInsertRows(QModelIndex(), rowCount(), rowCount());
mNotifications << Notification{ nextId(), message, interval, type };
beginInsertRows( QModelIndex(), rowCount(), rowCount() );
mNotifications << Notification{ nextId(), message, interval, type, icon };
endInsertRows();

emit rowCountChanged();
Expand All @@ -99,9 +102,10 @@ void NotificationModel::add(const QString &message, uint interval, NotificationT
// check for auto removing notification
void NotificationModel::timerFired()
{
for(Notification &notification : mNotifications) {
if(notification.canBeRemoved())
remove(notification.id());
for ( Notification &notification : mNotifications )
{
if ( notification.canBeRemoved() )
remove( notification.id() );
}
}

Expand Down
Loading

0 comments on commit c59475e

Please sign in to comment.