From 6a6d375265962ccfba3c581536bd0a0f4217c36d Mon Sep 17 00:00:00 2001 From: Ronan Abhamon Date: Tue, 15 Nov 2016 14:29:49 +0100 Subject: [PATCH] unstable --- tests/resources.qrc | 1 + tests/src/app/App.cpp | 54 +++++++-- tests/src/app/App.hpp | 32 ++++- .../components/notification/Notification.cpp | 109 ++++++++++++++++-- .../components/notification/Notification.hpp | 33 +++++- tests/src/main.cpp | 4 +- .../ui/modules/Common/Popup/DesktopPopup.qml | 3 + .../Notifications/CallNotification.qml | 11 ++ tests/ui/modules/Linphone/qmldir | 3 + tests/ui/views/App/MainWindow/Contacts.qml | 2 +- 10 files changed, 220 insertions(+), 32 deletions(-) create mode 100644 tests/ui/modules/Linphone/Notifications/CallNotification.qml 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.