1 /**************************************************************************
2 * Otter Browser: Web browser controlled by the user, not vice-versa.
3 * Copyright (C) 2013 - 2018 Michal Dutkiewicz aka Emdek <michal@emdek.pl>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 **************************************************************************/
19
20 #include "NotificationsManager.h"
21 #include "Application.h"
22 #include "SessionsManager.h"
23 #include "../ui/MainWindow.h"
24
25 #include <QtCore/QFile>
26 #include <QtCore/QMetaEnum>
27 #include <QtCore/QSettings>
28 #include <QtMultimedia/QSoundEffect>
29
30 namespace Otter
31 {
32
33 NotificationsManager* NotificationsManager::m_instance(nullptr);
34 QMap<int, QString> NotificationsManager::m_identifiers;
35 QVector<NotificationsManager::EventDefinition> NotificationsManager::m_definitions;
36 int NotificationsManager::m_eventIdentifierEnumerator(0);
37
Notification(const QString & message,NotificationLevel level,int event,QObject * parent)38 Notification::Notification(const QString &message, NotificationLevel level, int event, QObject *parent) : QObject(parent),
39 m_message(message),
40 m_creationTime(QDateTime::currentDateTime()),
41 m_level(level),
42 m_event(event)
43 {
44 }
45
markAsClicked()46 void Notification::markAsClicked()
47 {
48 emit clicked();
49
50 deleteLater();
51 }
52
markAsIgnored()53 void Notification::markAsIgnored()
54 {
55 emit ignored();
56
57 deleteLater();
58 }
59
setData(const QVariant & data)60 void Notification::setData(const QVariant &data)
61 {
62 m_data = data;
63 }
64
getMessage() const65 QString Notification::getMessage() const
66 {
67 return m_message;
68 }
69
getCreationTime() const70 QDateTime Notification::getCreationTime() const
71 {
72 return m_creationTime;
73 }
74
getData() const75 QVariant Notification::getData() const
76 {
77 return m_data;
78 }
79
getLevel() const80 Notification::NotificationLevel Notification::getLevel() const
81 {
82 return m_level;
83 }
84
NotificationsManager(QObject * parent)85 NotificationsManager::NotificationsManager(QObject *parent) : QObject(parent)
86 {
87 registerEvent(QT_TRANSLATE_NOOP("notifications", "Feed Updated"), QT_TRANSLATE_NOOP("notifications", "Feed update was completed"));
88 registerEvent(QT_TRANSLATE_NOOP("notifications", "Download Completed"), QT_TRANSLATE_NOOP("notifications", "File download was completed"));
89 registerEvent(QT_TRANSLATE_NOOP("notifications", "Update Available"), QT_TRANSLATE_NOOP("notifications", "Update is available to be downloaded"));
90 }
91
createInstance()92 void NotificationsManager::createInstance()
93 {
94 if (!m_instance)
95 {
96 m_instance = new NotificationsManager(QCoreApplication::instance());
97 m_eventIdentifierEnumerator = NotificationsManager::staticMetaObject.indexOfEnumerator(QLatin1String("EventIdentifier").data());
98 }
99 }
100
createNotification(int event,const QString & message,Notification::NotificationLevel level,QObject * parent)101 Notification* NotificationsManager::createNotification(int event, const QString &message, Notification::NotificationLevel level, QObject *parent)
102 {
103 Notification *notification(new Notification(message, level, event, Application::getInstance()));
104 const EventDefinition definition(getEventDefinition(event));
105
106 if (!definition.playSound.isEmpty())
107 {
108 QSoundEffect *effect(new QSoundEffect(m_instance));
109 effect->setSource(QUrl::fromLocalFile(definition.playSound));
110 effect->setLoopCount(1);
111 effect->setVolume(0.5);
112
113 if (effect->status() == QSoundEffect::Error)
114 {
115 effect->deleteLater();
116 }
117 else
118 {
119 connect(effect, &QSoundEffect::playingChanged, m_instance, [=]()
120 {
121 if (!effect->isPlaying())
122 {
123 effect->deleteLater();
124 }
125 });
126
127 effect->play();
128 }
129 }
130
131 if (definition.showAlert)
132 {
133 Application::getInstance()->alert(MainWindow::findMainWindow(parent));
134 }
135
136 if (definition.showNotification)
137 {
138 Application::showNotification(notification);
139 }
140
141 return notification;
142 }
143
getEventName(int identifier)144 QString NotificationsManager::getEventName(int identifier)
145 {
146 if (m_identifiers.contains(identifier))
147 {
148 return m_identifiers[identifier];
149 }
150
151 QString name(NotificationsManager::staticMetaObject.enumerator(m_eventIdentifierEnumerator).valueToKey(identifier));
152
153 if (!name.isEmpty())
154 {
155 name.chop(5);
156
157 return name;
158 }
159
160 return {};
161 }
162
getEventDefinition(int identifier)163 NotificationsManager::EventDefinition NotificationsManager::getEventDefinition(int identifier)
164 {
165 if (identifier < 0 || identifier >= m_definitions.count())
166 {
167 return {};
168 }
169
170 const QSettings notificationsSettings(SessionsManager::getReadableDataPath(QLatin1String("notifications.ini")), QSettings::IniFormat);
171 const QString eventName(getEventName(identifier));
172 EventDefinition definition(m_definitions.at(identifier));
173 definition.playSound = notificationsSettings.value(eventName + QLatin1String("/playSound"), {}).toString();
174 definition.showAlert = notificationsSettings.value(eventName + QLatin1String("/showAlert"), false).toBool();
175 definition.showNotification = notificationsSettings.value(eventName + QLatin1String("/showNotification"), false).toBool();
176
177 return definition;
178 }
179
getEventDefinitions()180 QVector<NotificationsManager::EventDefinition> NotificationsManager::getEventDefinitions()
181 {
182 QVector<EventDefinition> definitions;
183 definitions.reserve(m_definitions.count());
184
185 for (int i = 0; i < m_definitions.count(); ++i)
186 {
187 definitions.append(getEventDefinition(i));
188 }
189
190 return definitions;
191 }
192
registerEvent(const QString & title,const QString & description)193 int NotificationsManager::registerEvent(const QString &title, const QString &description)
194 {
195 const int identifier(m_definitions.count());
196
197 EventDefinition definition;
198 definition.title = title;
199 definition.description = description;
200 definition.identifier = identifier;
201
202 m_definitions.append(definition);
203
204 return identifier;
205 }
206
207 }
208