Torc  0.1
torcnotify.cpp
Go to the documentation of this file.
1 /* Class TorcNotify
2 *
3 * Copyright (C) Mark Kendall 2016-18
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 2 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, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19 
20 // Qt
21 #include <QCoreApplication>
22 #include <QReadWriteLock>
23 #include <QDateTime>
24 
25 // Torc
26 #include "torclogging.h"
27 #include "torcnotify.h"
28 
30 
32  : QObject(),
34  m_notifiers(),
35  m_notifications(),
36  m_applicationNameChanged(false)
37 {
38 }
39 
41 {
42  // there isn't always an app object when gNotify is created, so connect the dots here but ensure
43  // connections are unique to account for multiple runs.
44  connect(qApp, &QCoreApplication::applicationNameChanged, gNotify, &TorcNotify::ApplicationNameChanged, Qt::UniqueConnection);
45 
46  QWriteLocker locker(&m_handlerLock);
47 
48  foreach (TorcNotification* notification, m_notifications)
49  (void)notification->Setup();
50 
51  return true;
52 }
53 
55 {
56  QWriteLocker locker(&m_handlerLock);
57  foreach (TorcNotifier* notifier, m_notifiers)
58  if (notifier->GetUniqueId() == Name)
59  return notifier;
60 
61  return nullptr;
62 }
63 
64 void TorcNotify::Graph(QByteArray *Data)
65 {
66  if (!Data)
67  return;
68 
69  foreach(TorcNotification *notification, m_notifications)
70  {
71  QString id = notification->GetUniqueId();
72  QString label = notification->GetUserName();
73  QString desc;
74  QStringList source = notification->GetDescription();
75  foreach (const QString &item, source)
76  if (!item.isEmpty())
77  desc.append(QString(DEVICE_LINE_ITEM).arg(item));
78 
79  if (label.isEmpty())
80  label = id;
81  Data->append(QStringLiteral(" \"%1\" [shape=record style=rounded id=\"%1\" label=<<B>%2</B>%3>];\r\n").arg(id, label, desc));
82 
83  // and add links
84  notification->Graph(Data);
85  }
86 
87  foreach(TorcNotifier *notifier, m_notifiers)
88  {
89  QString id = notifier->GetUniqueId();
90  QString label = notifier->GetUserName();
91  QString desc;
92  QStringList source = notifier->GetDescription();
93  foreach (const QString &item, source)
94  desc.append(QString(DEVICE_LINE_ITEM).arg(item));
95 
96  if (label.isEmpty())
97  label = id;
98  Data->append(QStringLiteral(" \"%1\" [shape=record style=rounded id=\"%1\" label=<<B>%2</B>%3>];\r\n").arg(id, label, desc));
99  }
100 }
101 
102 QVariantMap TorcNotify::SetNotificationText(const QString &Title, const QString &Body, const QMap<QString,QString> &Custom)
103 {
104  static bool initialised = false;
105  static QMap<QString,QString> data;
106  static QReadWriteLock *lock = new QReadWriteLock(QReadWriteLock::Recursive);
107 
108  if (!initialised || m_applicationNameChanged == true)
109  {
110  {
111  QWriteLocker locker(lock);
112  data.insert(QStringLiteral("applicationname"), QCoreApplication::applicationName());
113  initialised = true;
114  }
115  {
116  QWriteLocker locker(&m_handlerLock);
117  m_applicationNameChanged = false;
118  }
119  }
120 
121  QDateTime datetime = QDateTime::currentDateTime();
122  QTime time = datetime.time();
123  QDate date = datetime.date();
124 
125  {
126  QWriteLocker locker(lock);
127  data.insert(QStringLiteral("datetime"), datetime.toString(Qt::TextDate));
128  data.insert(QStringLiteral("shortdatetime"), datetime.toString(Qt::SystemLocaleShortDate));
129  data.insert(QStringLiteral("longdatetime"), datetime.toString(Qt::SystemLocaleLongDate));
130  data.insert(QStringLiteral("time"), time.toString(Qt::TextDate));
131  data.insert(QStringLiteral("shorttime"), time.toString(Qt::SystemLocaleShortDate));
132  data.insert(QStringLiteral("longtime"), time.toString(Qt::SystemLocaleLongDate));
133  data.insert(QStringLiteral("date"), date.toString(Qt::TextDate));
134  data.insert(QStringLiteral("shortdate"), date.toString(Qt::SystemLocaleShortDate));
135  data.insert(QStringLiteral("longdate"), date.toString(Qt::SystemLocaleLongDate));
136  }
137 
138  QRegExp regexp("%(([^\\|%]+)?\\||\\|(.))?([\\w#]+)(\\|(.+))?%");
139  regexp.setMinimal(true);
140 
141  // modify title and body for 'global' data
142  QString title = Title;
143  QString body = Body;
144  int pos = 0;
145  {
146  QReadLocker locker(lock);
147 
148  while ((pos = regexp.indexIn(Title, pos)) != -1)
149  {
150  QString key = regexp.cap(4).toLower().trimmed();
151  if (data.contains(key))
152  title.replace(regexp.cap(0), QStringLiteral("%1%2%3%4").arg(regexp.cap(2), regexp.cap(3), data.value(key), regexp.cap(6)));
153  pos += regexp.matchedLength();
154  }
155  pos = 0;
156  while ((pos = regexp.indexIn(Body, pos)) != -1)
157  {
158  QString key = regexp.cap(4).toLower().trimmed();
159  if (data.contains(key))
160  body.replace(regexp.cap(0), QStringLiteral("%1%2%3%4").arg(regexp.cap(2), regexp.cap(3), data.value(key), regexp.cap(6)));
161  pos += regexp.matchedLength();
162  }
163  }
164  // and custom data
165  pos = 0;
166  while ((pos = regexp.indexIn(Title, pos)) != -1)
167  {
168  QString key = regexp.cap(4).toLower().trimmed();
169  if (Custom.contains(key))
170  title.replace(regexp.cap(0), QStringLiteral("%1%2%3%4").arg(regexp.cap(2), regexp.cap(3), Custom.value(key), regexp.cap(6)));
171  pos += regexp.matchedLength();
172  }
173  pos = 0;
174  while ((pos = regexp.indexIn(Body, pos)) != -1)
175  {
176  QString key = regexp.cap(4).toLower().trimmed();
177  if (Custom.contains(key))
178  body.replace(regexp.cap(0), QStringLiteral("%1%2%3%4").arg(regexp.cap(2), regexp.cap(3), Custom.value(key), regexp.cap(6)));
179  pos += regexp.matchedLength();
180  }
181 
182 
183  QVariantMap message;
184  message.insert(NOTIFICATION_TITLE, title);
185  message.insert(NOTIFICATION_BODY, body);
186 
187  QMap<QString,QString>::const_iterator it = Custom.constBegin();
188  for ( ; it != Custom.constEnd(); ++it)
189  message.insert(it.key(), it.value());
190  return message;
191 }
192 
194 {
195  QWriteLocker locker(&m_handlerLock);
196  m_applicationNameChanged = true;
197 }
198 
199 void TorcNotify::Create(const QVariantMap &Details)
200 {
201  QWriteLocker locker(&m_handlerLock);
202 
203  QVariantMap::const_iterator ii = Details.constBegin();
204  for ( ; ii != Details.constEnd(); ++ii)
205  {
206  if (ii.key() == QStringLiteral("notify"))
207  {
208  QVariantMap notify = ii.value().toMap();
209  QVariantMap::const_iterator i = notify.constBegin();
210  for ( ; i != notify.constEnd(); ++i)
211  {
212  if (i.key() == QStringLiteral("notifiers"))
213  {
214  QVariantMap notifiers = i.value().toMap();
215  QVariantMap::iterator it = notifiers.begin();
216  for ( ; it != notifiers.end(); ++it)
217  {
218  QVariantMap details = it.value().toMap();
219  if (!details.contains(QStringLiteral("name")))
220  {
221  LOG(VB_GENERAL, LOG_ERR, QStringLiteral("Notifier '%1' has no name").arg(it.key()));
222  continue;
223  }
224 
226  for ( ; factory; factory = factory->NextFactory())
227  {
228  TorcNotifier* notifier = factory->Create(it.key(), details);
229  if (notifier)
230  {
231  m_notifiers.append(notifier);
232  LOG(VB_GENERAL, LOG_INFO, QStringLiteral("New notifier '%1'").arg(notifier->GetUniqueId()));
233  break;
234  }
235  }
236  }
237  }
238  else if (i.key() == QStringLiteral("notifications"))
239  {
240  QVariantMap notifications = i.value().toMap();
241  QVariantMap::iterator it = notifications.begin();
242  for ( ; it != notifications.end(); ++it)
243  {
244  QVariantMap details = it.value().toMap();
245  if (!details.contains(QStringLiteral("name")))
246  {
247  LOG(VB_GENERAL, LOG_ERR, QStringLiteral("Notification '%1' has no name").arg(it.key()));
248  continue;
249  }
250 
251  if (!details.contains(QStringLiteral("outputs")))
252  {
253  LOG(VB_GENERAL, LOG_ERR, QStringLiteral("Notification '%1' does not specify 'outputs' (notififiers)").arg(it.key()));
254  continue;
255  }
256 
257  if (!details.contains(QStringLiteral("message")))
258  {
259  LOG(VB_GENERAL, LOG_ERR, QStringLiteral("Notificaiton '%1' does not specify 'message'").arg(it.key()));
260  continue;
261  }
262 
264  for ( ; factory; factory = factory->NextFactory())
265  {
266  TorcNotification* notification = factory->Create(it.key(), details);
267  if (notification)
268  {
269  m_notifications.append(notification);
270  LOG(VB_GENERAL, LOG_INFO, QStringLiteral("New notification '%1'").arg(notification->GetUniqueId()));
271  break;
272  }
273  }
274  }
275  }
276  }
277  }
278  }
279 }
280 
282 {
283  QWriteLocker locker(&m_handlerLock);
284  foreach (TorcNotifier* notifier, m_notifiers)
285  notifier->DownRef();
286  m_notifiers.clear();
287 
288  foreach (TorcNotification* notification, m_notifications)
289  notification->DownRef();
290  m_notifications.clear();
291 }
virtual TorcNotifier * Create(const QString &Type, const QVariantMap &Details)=0
QString GetUserName(void)
Definition: torcdevice.cpp:168
void Graph(QByteArray *Data)
Definition: torcnotify.cpp:64
#define DEVICE_LINE_ITEM
Definition: torcdevice.h:16
virtual bool DownRef(void)
void Create(const QVariantMap &Details) override
Definition: torcnotify.cpp:199
bool Validate(void)
Definition: torcnotify.cpp:40
TorcNotificationFactory * NextFactory(void) const
virtual void Graph(QByteArray *Data)=0
void ApplicationNameChanged(void)
Definition: torcnotify.cpp:193
static TorcNotifierFactory * GetTorcNotifierFactory(void)
void Destroy(void) override
Definition: torcnotify.cpp:281
TorcNotifierFactory * NextFactory(void) const
#define NOTIFICATION_BODY
Definition: torcnotifier.h:11
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: torclogging.h:20
QVariantMap SetNotificationText(const QString &Title, const QString &Body, const QMap< QString, QString > &Custom)
Definition: torcnotify.cpp:102
QReadWriteLock m_handlerLock
TorcNotifier * FindNotifierByName(const QString &Name)
Definition: torcnotify.cpp:54
#define NOTIFICATION_TITLE
Definition: torcnotifier.h:10
virtual bool Setup(void)
virtual QStringList GetDescription(void)=0
static TorcNotify * gNotify
Definition: torcnotify.h:19
virtual TorcNotification * Create(const QString &Type, const QVariantMap &Details)=0
QString GetUniqueId(void)
Definition: torcdevice.cpp:162
static TorcNotificationFactory * GetTorcNotificationFactory(void)