Enroute Flight Navigation
A navigation app for VFR pilots
NotificationManager.h
1/***************************************************************************
2 * Copyright (C) 2023 by Stefan Kebekus *
3 * stefan.kebekus@gmail.com *
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, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20
21#pragma once
22
23#include <QFuture>
24#include <QQmlEngine>
25#include <QTextToSpeech>
26#include <QTimer>
27
28#include "GlobalObject.h"
29#include "Notification.h"
30
31
32namespace Notifications {
33
40
42{
43 Q_OBJECT
44 QML_ELEMENT
45 QML_SINGLETON
46
47public:
48 //
49 // Constructors and destructors
50 //
51
56 explicit NotificationManager(QObject* parent = nullptr);
57
58 // deferred initialization
59 void deferredInitialization() override;
60
61 // No default constructor, important for QML singleton
62 explicit NotificationManager() = delete;
63
65 ~NotificationManager() override = default;
66
67 // factory function for QML singleton
68 static Notifications::NotificationManager* create(QQmlEngine* /*unused*/, QJSEngine* /*unused*/)
69 {
71 }
72
73
74 //
75 // PROPERTIES
76 //
77
88
89
97 Q_PROPERTY(QTextToSpeech* speaker READ speaker NOTIFY speakerChanged)
98
99
100 //
101 // Getter Methods
102 //
103
108 [[nodiscard]] Notifications::Notification* currentVisualNotification() const;
109
114 [[nodiscard]] QTextToSpeech* speaker() const
115 {
116 return m_speaker;
117 }
118
119
120 //
121 // Methods
122 //
123
125 Q_INVOKABLE void addTestNotification();
126
128 Q_INVOKABLE void voiceTest();
129
132
133signals:
136
139
141 void toastPosted(QString text);
142
143private:
144 Q_DISABLE_COPY_MOVE(NotificationManager)
145
146
147 // Adds a notification to m_notifications and rearranges the list. Removes
148 // nullptrs and sorts list by importance.
149 void addNotification(Notifications::Notification* notification);
150
151
152
153 //
154 // Members used for visual notifications
155 //
156
157 // This method clears all nullptrs from m_notifications, sorts the elements
158 // by importance and emits currentNotificationChanged() whenever the first
159 // element the list changes.
160 void showNext();
161
162 // List of Notifications, sorted so that the most important notification
163 // comes first.
164 QVector<QPointer<Notifications::Notification>> m_visualNotifications;
165
166 // Stores pointer to last current visual notification. This is used to
167 // determine when the signal currentVisualNotificationChanged should be
168 // emitted.
169 Notifications::Notification* currentVisualNotificationCache {nullptr};
170
171
172
173 //
174 // Members used for voice notifications
175 //
176
177
178 // If the speaker is finished, start m_speechBreakTimer, in order to call
179 // speakNext() after a one-second break.
180 void onSpeakerStateChanged(QTextToSpeech::State state);
181
182 // Constructs the speaker and moves it to the given thread. Under Linux,
183 // the constructor of QTextToSpeech is very slow, so this runs on a worker
184 // thread. The object is then handed over to the GUI thread by
185 // adoptSpeaker(). This method touches nothing but the new object.
186 static QTextToSpeech* createSpeaker(QThread* thread);
187
188 // Takes over a speaker constructed by createSpeaker(): makes it a child of
189 // this, wires it up, publishes it through the property speaker and starts
190 // speaking pending notifications. Must be called in the GUI thread.
191 void adoptSpeaker(QTextToSpeech* speaker);
192
193
194 // This method cleans the list m_spokenNotifications and sorts it by
195 // importance. If a notification is in the list, it speaks the notication
196 // test.
197 void speakNext();
198
199 // List of Notifications, sorted so that the most important notification
200 // comes first.
201 QVector<QPointer<Notifications::Notification>> m_voiceNotifications;
202
203 // Pointer to the speaker. This is the nullpointer until adoptSpeaker() has
204 // run. Written and read in the GUI thread only.
205 QTextToSpeech* m_speaker {nullptr};
206
207 // Future for the worker that constructs QTextToSpeech under Linux in a
208 // different thread
209 QFuture<QTextToSpeech*> m_speakerFuture;
210
211
212 // This timer is used to stop for one second between two spoken texts. The
213 // slot start() is called when m_speaker is done speaking. The signal
214 // timeout() is connected to speakNext().
215 QTimer m_speechBreakTimer;
216
217
218
219 //
220 // Members used to watch other app components, and to generate notifications
221 // when necessary
222 //
223
224 // Called whenever map and data updates become (un)available
225 void onMapAndDataUpdateSizeChanged();
226
227 // Called whenever the position provider finds that pressure altitude and
228 // geometric altitude differ by implausible amounts, or clears that status.
229 void onPressureAltitudeImplausible();
230
231 // Called whenever the list of oversized aviation maps changes
232 void onOversizedMapsChanged();
233
234 // Called whenever the traffic receiver reports a runtime error, or clears
235 // the error status.
236 void onTrafficReceiverRuntimeError();
237
238 // Called whenever the traffic receiver reports a self test error, or clears
239 // the error status.
240 void onTrafficReceiverSelfTestError();
241
242 // When notifications for maps and data are temporarily not possible, then
243 // use this timer to notify again.
244 QTimer mapsAndDataNotificationTimer;
245
246 // Notification for oversized aviation maps; this pointer guards against
247 // showing the notification more than once.
248 QPointer<Notifications::Notification> m_oversizedMapNotification;
249};
250
251
252} // namespace Notifications
static Q_INVOKABLE Notifications::NotificationManager * notificationManager()
Pointer to appplication-wide static notification manager instance.
GlobalObject(QObject *parent=nullptr)
Standard constructor.
This class manages notifications and presents them to the GUI.
Q_INVOKABLE void voiceTest()
Voice test.
void speakerChanged()
Notification signal.
void deferredInitialization() override
Non-constructor initialization.
Q_INVOKABLE void addTestNotification()
Issue test notification.
Notifications::Notification * currentVisualNotification
Most important notification to be shown in the GUI.
void waitForSpeechEngine()
Wait until speech engine is fully constructed.
void toastPosted(QString text)
Indicates that the GUI should show a toast.
void currentVisualNotificationChanged()
Notification signal.
NotificationManager(QObject *parent=nullptr)
Standard constructor.
QTextToSpeech * speaker
Pointer to QTextToSpeech.
~NotificationManager() override=default
Standard destructor.
Base class for all notifications.