diff --git a/tests/resources.qrc b/tests/resources.qrc
index ac469fb3a..d851e1f3e 100644
--- a/tests/resources.qrc
+++ b/tests/resources.qrc
@@ -117,6 +117,7 @@
ui/modules/Linphone/Contact/Avatar.qml
ui/modules/Linphone/Contact/ContactDescription.qml
ui/modules/Linphone/Contact/Contact.qml
+ ui/modules/Linphone/Notifications/CallNotification.qml
ui/modules/Linphone/Presence/PresenceLevel.qml
ui/modules/Linphone/Presence/PresenceString.qml
ui/modules/Linphone/qmldir
diff --git a/tests/src/app/App.cpp b/tests/src/app/App.cpp
index 274e5322f..18e8df2d0 100644
--- a/tests/src/app/App.cpp
+++ b/tests/src/app/App.cpp
@@ -1,3 +1,4 @@
+#include
#include
#include
#include
@@ -6,7 +7,6 @@
#include "../components/contacts/ContactsListProxyModel.hpp"
#include "../components/linphone/LinphoneCore.hpp"
-#include "../components/notification/Notification.hpp"
#include "../components/settings/AccountSettingsModel.hpp"
#include "../components/timeline/TimelineModel.hpp"
@@ -17,6 +17,8 @@
// ===================================================================
+App *App::m_instance = nullptr;
+
App::App (int &argc, char **argv) : QApplication(argc, argv) {
// Try to use default locale. Otherwise use english.
if (m_translator.load(QString(LANGUAGES_PATH) + QLocale::system().name()) ||
@@ -36,7 +38,11 @@ App::App (int &argc, char **argv) : QApplication(argc, argv) {
m_engine.addImportPath(":/ui/modules");
m_engine.addImportPath(":/ui/scripts");
m_engine.addImportPath(":/ui/views");
+}
+// -------------------------------------------------------------------
+
+void App::initContentApp () {
// Register types and load context properties.
registerTypes();
addContextProperties();
@@ -51,9 +57,10 @@ App::App (int &argc, char **argv) : QApplication(argc, argv) {
qWarning("System tray not found on this system.");
else
setTrayIcon();
-}
-// -------------------------------------------------------------------
+ // Set notification attr.
+ setNotificationAttributes();
+}
void App::registerTypes () {
qmlRegisterUncreatableType(
@@ -92,13 +99,16 @@ void App::addContextProperties () {
// Other.
context->setContextProperty("LinphoneCore", LinphoneCore::getInstance());
- context->setContextProperty("Notification", new Notification());
+
+ m_notification = new Notification();
+ context->setContextProperty("Notification", m_notification);
}
void App::setTrayIcon () {
QQuickWindow *root = qobject_cast(m_engine.rootObjects().at(0));
QMenu *menu = new QMenu();
- m_tray_icon = new QSystemTrayIcon(root);
+
+ m_system_tray_icon = new QSystemTrayIcon(root);
// trayIcon: Right click actions.
QAction *quit_action = new QAction("Quit", root);
@@ -108,7 +118,7 @@ void App::setTrayIcon () {
root->connect(restore_action, &QAction::triggered, root, &QQuickWindow::showNormal);
// trayIcon: Left click actions.
- root->connect(m_tray_icon, &QSystemTrayIcon::activated, [root](QSystemTrayIcon::ActivationReason reason) {
+ root->connect(m_system_tray_icon, &QSystemTrayIcon::activated, [root](QSystemTrayIcon::ActivationReason reason) {
if (reason == QSystemTrayIcon::Trigger) {
if (root->visibility() == QWindow::Hidden)
root->showNormal();
@@ -122,8 +132,32 @@ void App::setTrayIcon () {
menu->addSeparator();
menu->addAction(quit_action);
- m_tray_icon->setContextMenu(menu);
- m_tray_icon->setIcon(QIcon(WINDOW_ICON_PATH));
- m_tray_icon->setToolTip("Linphone");
- m_tray_icon->show();
+ m_system_tray_icon->setContextMenu(menu);
+ m_system_tray_icon->setIcon(QIcon(WINDOW_ICON_PATH));
+ m_system_tray_icon->setToolTip("Linphone");
+ m_system_tray_icon->show();
+}
+
+void App::setNotificationAttributes () {
+ QDesktopWidget *desktop = QApplication::desktop();
+
+ // The primary screen is the default given by Qt or the screen of
+ // system tray icon.
+ int primary_screen = desktop->primaryScreen();
+ if (m_system_tray_icon) {
+ // primary_screen = QDesktopWidget::screenNumber(m_system_tray_icon);
+
+ QRect icon_rect = m_system_tray_icon->geometry();
+ QRect screen_rect = desktop->screenGeometry(primary_screen);
+
+ int x = icon_rect.x() + icon_rect.width() / 2;
+ int y = icon_rect.y() + icon_rect.height() / 2;
+
+ Qt::Edges edge = (x < screen_rect.width() / 2) ? Qt::LeftEdge : Qt::RightEdge;
+ edge |= (y < screen_rect.height() / 2) ? Qt::TopEdge : Qt::BottomEdge;
+
+ m_notification->setEdge(edge);
+ }
+
+ m_notification->setScreenNumber(primary_screen);
}
diff --git a/tests/src/app/App.hpp b/tests/src/app/App.hpp
index f38ea1cf5..a236dec2d 100644
--- a/tests/src/app/App.hpp
+++ b/tests/src/app/App.hpp
@@ -7,22 +7,46 @@
#include
#include
+#include "../components/notification/Notification.hpp"
+
// ===================================================================
class App : public QApplication {
public:
- App (int &argc, char **argv);
- virtual ~App () {}
+ static void init (int &argc, char **argv) {
+ if (!m_instance) {
+ m_instance = new App(argc, argv);
+ m_instance->initContentApp();
+ }
+ }
+
+ static App *getInstance () {
+ return m_instance;
+ }
+
+ QQmlEngine *getEngine () {
+ return &m_engine;
+ }
private:
+ App (int &argc, char **argv);
+
+ void initContentApp ();
+
void registerTypes ();
void addContextProperties ();
void setTrayIcon ();
+ void setNotificationAttributes ();
+
QQmlApplicationEngine m_engine;
- QQmlFileSelector *m_file_selector;
- QSystemTrayIcon *m_tray_icon;
+ QQmlFileSelector *m_file_selector = nullptr;
+ QSystemTrayIcon *m_system_tray_icon = nullptr;
QTranslator m_translator;
+
+ Notification *m_notification = nullptr;
+
+ static App *m_instance;
};
#endif // APP_H_
diff --git a/tests/src/components/notification/Notification.cpp b/tests/src/components/notification/Notification.cpp
index 72afdae56..27b74299f 100644
--- a/tests/src/components/notification/Notification.cpp
+++ b/tests/src/components/notification/Notification.cpp
@@ -1,20 +1,111 @@
+#include
+#include
#include
+#include "../../app/App.hpp"
#include "Notification.hpp"
+#define NOTIFICATION_X_PROPERTY "popupX"
+#define NOTIFICATION_Y_PROPERTY "popupY"
+
+#define NOTIFICATION_HEIGHT_PROPERTY "popupHeight"
+#define NOTIFICATION_WIDTH_PROPERTY "popupWidth"
+
+#define NOTIFICATION_SHOW_METHOD_NAME "show"
+
+#define N_MAX_NOTIFICATIONS 3
+
// ===================================================================
Notification::Notification (QObject *parent) :
QObject(parent) {
+ QQmlEngine *engine = App::getInstance()->getEngine();
+
+ // Build components.
+ m_components[Notification::Call] = new QQmlComponent(
+ engine, QUrl("qrc:/ui/modules/Linphone/Notifications/CallNotification.qml")
+ );
+
+ // Check errors.
+ for (int i = 0; i < Notification::MaxNbTypes; i++) {
+ QQmlComponent &component = *m_components[i];
+ if (component.isError()) {
+ qWarning() << "Errors found in `Notification` component "
+ << i << ":" << component.errors();
+ abort();
+ }
+ }
}
-void Notification::showMessage (
- const QString &summary,
- const QString &body,
- const QString &icon,
- int timeout
-) {
- qDebug() <<
- "Notification.showMessage(" << summary << ", " <<
- body << ", " << icon << ", " << timeout << ")";
+Notification::~Notification () {
+ for (int i = 0; i < Notification::MaxNbTypes; i++)
+ delete m_components[i];
+}
+
+// -------------------------------------------------------------------
+
+inline int getNotificationSize (const QObject &object, const char *size_property) {
+ QVariant variant = object.property(size_property);
+ bool so_far_so_good;
+ int size = variant.toInt(&so_far_so_good);
+
+ if (!so_far_so_good || size < 0) {
+ qWarning() << "Unable to get notification size.";
+ return -1;
+ }
+
+ return size;
+}
+
+inline bool setNotificationPosition (
+ QObject &object, const char *position_property, int value
+) {
+ QVariant position(value);
+
+ if (!object.setProperty(position_property, position)) {
+ qWarning() << "Unable to set notification position.";
+ return false;
+ }
+
+ return true;
+}
+
+void Notification::showCallMessage (
+ int timeout,
+ const QString &sip_address
+) {
+ qDebug() << "Show call notification message. (addr=" <<
+ sip_address << ")";
+
+ QObject *object = m_components[Notification::Call]->create();
+ int width, height;
+
+ if (
+ (width = getNotificationSize(*object, NOTIFICATION_WIDTH_PROPERTY)) == -1 ||
+ (height = getNotificationSize(*object, NOTIFICATION_HEIGHT_PROPERTY)) == -1
+ ) {
+ delete object;
+ return;
+ }
+
+ QRect screen_rect = QApplication::desktop()->screenGeometry(m_screen_number);
+
+ int x = (m_edge & Qt::LeftEdge) ? 5 : screen_rect.width() - 5 - width;
+ int y = (m_edge & Qt::TopEdge) ? 5 : screen_rect.height() - 5 - height;
+
+ if (
+ !setNotificationPosition(*object, NOTIFICATION_X_PROPERTY, x) ||
+ !setNotificationPosition(*object, NOTIFICATION_Y_PROPERTY, y)
+ ) {
+ delete object;
+ return;
+ }
+
+
+
+
+ QMetaObject::invokeMethod(object, "show", Qt::DirectConnection);
+ QTimer::singleShot(timeout, object, [object]() {
+ delete object;
+ });
}
diff --git a/tests/src/components/notification/Notification.hpp b/tests/src/components/notification/Notification.hpp
index 152c1f977..7c8c9cac5 100644
--- a/tests/src/components/notification/Notification.hpp
+++ b/tests/src/components/notification/Notification.hpp
@@ -1,7 +1,9 @@
#ifndef NOTIFICATION_H_
#define NOTIFICATION_H_
+#include
#include
+#include
// ===================================================================
@@ -10,14 +12,33 @@ class Notification : public QObject {
public:
Notification (QObject *parent = Q_NULLPTR);
+ virtual ~Notification ();
+
+ enum Type {
+ Call,
+ MaxNbTypes
+ };
+ Q_ENUM(Type);
+
+ void setEdge (Qt::Edges edge) {
+ m_edge = edge;
+ }
+
+ void setScreenNumber (int screen_number) {
+ m_screen_number = screen_number;
+ }
public slots:
- void showMessage (
- const QString &summary,
- const QString &body,
- const QString &icon = "",
- int timeout = 10000
- );
+ void showCallMessage (int timeout, const QString &sip_address);
+
+private:
+ Qt::Edges m_edge = Qt::RightEdge | Qt::TopEdge;
+ QQmlComponent *m_components[MaxNbTypes];
+
+ int m_screen_number = 0;
+
+ int m_n_instances = 0;
+ QMutex m_mutex;
};
#endif // NOTIFICATION_H_
diff --git a/tests/src/main.cpp b/tests/src/main.cpp
index 0fdd1f370..24cf0cc30 100644
--- a/tests/src/main.cpp
+++ b/tests/src/main.cpp
@@ -7,8 +7,8 @@ int main (int argc, char *argv[]) {
qInstallMessageHandler(qmlLogger);
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
- App app(argc, argv);
+ App::init(argc, argv);
// Run!
- return app.exec();
+ return App::getInstance()->exec();
}
diff --git a/tests/ui/modules/Common/Popup/DesktopPopup.qml b/tests/ui/modules/Common/Popup/DesktopPopup.qml
index 83e26d415..c11efea80 100644
--- a/tests/ui/modules/Common/Popup/DesktopPopup.qml
+++ b/tests/ui/modules/Common/Popup/DesktopPopup.qml
@@ -11,6 +11,9 @@ Item {
property alias popupX: popup.x
property alias popupY: popup.y
+ readonly property alias popupWidth: popup.width
+ readonly property alias popupHeight: popup.height
+
default property alias _content: content.data
property bool _isOpen: false
diff --git a/tests/ui/modules/Linphone/Notifications/CallNotification.qml b/tests/ui/modules/Linphone/Notifications/CallNotification.qml
new file mode 100644
index 000000000..6f6ed17bd
--- /dev/null
+++ b/tests/ui/modules/Linphone/Notifications/CallNotification.qml
@@ -0,0 +1,11 @@
+import QtQuick 2.7
+
+import Common 1.0
+
+DesktopPopup {
+ Rectangle {
+ color: 'red'
+ width: 200
+ height: 100
+ }
+}
diff --git a/tests/ui/modules/Linphone/qmldir b/tests/ui/modules/Linphone/qmldir
index 84540b032..b75b3aa1c 100644
--- a/tests/ui/modules/Linphone/qmldir
+++ b/tests/ui/modules/Linphone/qmldir
@@ -20,6 +20,9 @@ Avatar 1.0 Contact/Avatar.qml
Contact 1.0 Contact/Contact.qml
ContactDescription 1.0 Contact/ContactDescription.qml
+# Notifications
+CallNotification 1.0 Notifications/CallNotification.qml
+
# Presence
PresenceLevel 1.0 Presence/PresenceLevel.qml
PresenceString 1.0 Presence/PresenceString.qml
diff --git a/tests/ui/views/App/MainWindow/Contacts.qml b/tests/ui/views/App/MainWindow/Contacts.qml
index 84930eefc..9903fb301 100644
--- a/tests/ui/views/App/MainWindow/Contacts.qml
+++ b/tests/ui/views/App/MainWindow/Contacts.qml
@@ -36,7 +36,7 @@ ColumnLayout {
})
}
- spacing: 0
+ spacing: Notification.showCallMessage(10000, "toto@toto.com") || 0
// -----------------------------------------------------------------
// Search Bar & actions.