notifications in navigation bar
This commit is contained in:
parent
8566f830d1
commit
836d0b1da3
15 changed files with 489 additions and 12 deletions
|
|
@ -109,6 +109,12 @@
|
||||||
#include "tool/thread/Thread.hpp"
|
#include "tool/thread/Thread.hpp"
|
||||||
#include "tool/ui/DashRectangle.hpp"
|
#include "tool/ui/DashRectangle.hpp"
|
||||||
|
|
||||||
|
#if defined(Q_OS_MACOS)
|
||||||
|
#include "core/event-count-notifier/EventCountNotifierMacOs.hpp"
|
||||||
|
#else
|
||||||
|
#include "core/event-count-notifier/EventCountNotifierSystemTrayIcon.hpp"
|
||||||
|
#endif // if defined(Q_OS_MACOS)
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(App)
|
DEFINE_ABSTRACT_OBJECT(App)
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
|
|
@ -279,6 +285,7 @@ App::App(int &argc, char *argv[])
|
||||||
// Do not use APPLICATION_NAME here.
|
// Do not use APPLICATION_NAME here.
|
||||||
// The EXECUTABLE_NAME will be used in qt standard paths. It's our goal.
|
// The EXECUTABLE_NAME will be used in qt standard paths. It's our goal.
|
||||||
QThread::currentThread()->setPriority(QThread::HighPriority);
|
QThread::currentThread()->setPriority(QThread::HighPriority);
|
||||||
|
qDebug() << "app thread is" << QThread::currentThread();
|
||||||
QCoreApplication::setApplicationName(EXECUTABLE_NAME);
|
QCoreApplication::setApplicationName(EXECUTABLE_NAME);
|
||||||
QApplication::setOrganizationDomain(EXECUTABLE_NAME);
|
QApplication::setOrganizationDomain(EXECUTABLE_NAME);
|
||||||
QCoreApplication::setApplicationVersion(APPLICATION_SEMVER);
|
QCoreApplication::setApplicationVersion(APPLICATION_SEMVER);
|
||||||
|
|
@ -307,6 +314,7 @@ App::App(int &argc, char *argv[])
|
||||||
emit currentDateChanged();
|
emit currentDateChanged();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
mEventCountNotifier = new EventCountNotifier(this);
|
||||||
mDateUpdateTimer.start();
|
mDateUpdateTimer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -402,6 +410,16 @@ void App::setSelf(QSharedPointer<App>(me)) {
|
||||||
auto state = CoreModel::getInstance()->getCore()->getGlobalState();
|
auto state = CoreModel::getInstance()->getCore()->getGlobalState();
|
||||||
mCoreModelConnection->invokeToCore([this, state] { setCoreStarted(state == linphone::GlobalState::On); });
|
mCoreModelConnection->invokeToCore([this, state] { setCoreStarted(state == linphone::GlobalState::On); });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
mCoreModelConnection->makeConnectToModel(&CoreModel::unreadNotificationsChanged, [this] {
|
||||||
|
int n = mEventCountNotifier->getCurrentEventCount();
|
||||||
|
mCoreModelConnection->invokeToCore([this, n] { mEventCountNotifier->notifyEventCount(n); });
|
||||||
|
});
|
||||||
|
mCoreModelConnection->makeConnectToModel(&CoreModel::defaultAccountChanged, [this] {
|
||||||
|
int n = mEventCountNotifier->getCurrentEventCount();
|
||||||
|
mCoreModelConnection->invokeToCore([this, n] { mEventCountNotifier->notifyEventCount(n); });
|
||||||
|
});
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------
|
||||||
mCliModelConnection = SafeConnection<App, CliModel>::create(me, CliModel::getInstance());
|
mCliModelConnection = SafeConnection<App, CliModel>::create(me, CliModel::getInstance());
|
||||||
mCliModelConnection->makeConnectToCore(&App::receivedMessage, [this](int, const QByteArray &byteArray) {
|
mCliModelConnection->makeConnectToCore(&App::receivedMessage, [this](int, const QByteArray &byteArray) {
|
||||||
|
|
@ -430,6 +448,15 @@ QThread *App::getLinphoneThread() {
|
||||||
Notifier *App::getNotifier() const {
|
Notifier *App::getNotifier() const {
|
||||||
return mNotifier;
|
return mNotifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EventCountNotifier *App::getEventCountNotifier() {
|
||||||
|
return mEventCountNotifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
int App::getEventCount() const {
|
||||||
|
return mEventCountNotifier ? mEventCountNotifier->getEventCount() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------
|
//-----------------------------------------------------------
|
||||||
// Initializations
|
// Initializations
|
||||||
//-----------------------------------------------------------
|
//-----------------------------------------------------------
|
||||||
|
|
@ -474,7 +501,7 @@ void App::initCore() {
|
||||||
CoreModel::create("", mLinphoneThread);
|
CoreModel::create("", mLinphoneThread);
|
||||||
if (mParser->isSet("verbose")) QtLogger::enableVerbose(true);
|
if (mParser->isSet("verbose")) QtLogger::enableVerbose(true);
|
||||||
if (mParser->isSet("qt-logs-only")) QtLogger::enableQtOnly(true);
|
if (mParser->isSet("qt-logs-only")) QtLogger::enableQtOnly(true);
|
||||||
|
qDebug() << "linphone thread is" << mLinphoneThread;
|
||||||
QMetaObject::invokeMethod(
|
QMetaObject::invokeMethod(
|
||||||
mLinphoneThread->getThreadId(),
|
mLinphoneThread->getThreadId(),
|
||||||
[this, settings = mSettings]() mutable {
|
[this, settings = mSettings]() mutable {
|
||||||
|
|
@ -629,7 +656,6 @@ static inline bool installLocale(App &app, QTranslator &translator, const QLocal
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::initLocale() {
|
void App::initLocale() {
|
||||||
|
|
||||||
// Try to use preferred locale.
|
// Try to use preferred locale.
|
||||||
QString locale;
|
QString locale;
|
||||||
|
|
||||||
|
|
@ -644,9 +670,9 @@ void App::initLocale() {
|
||||||
|
|
||||||
// Try to use system locale.
|
// Try to use system locale.
|
||||||
// #ifdef Q_OS_MACOS
|
// #ifdef Q_OS_MACOS
|
||||||
// Use this workaround if there is still an issue about detecting wrong language from system on Mac. Qt doesn't use
|
// Use this workaround if there is still an issue about detecting wrong language from system on Mac. Qt doesn't
|
||||||
// the current system language on QLocale::system(). So we need to get it from user settings and overwrite its
|
// use the current system language on QLocale::system(). So we need to get it from user settings and overwrite
|
||||||
// Locale.
|
// its Locale.
|
||||||
// QSettings settings;
|
// QSettings settings;
|
||||||
// QString preferredLanguage = settings.value("AppleLanguages").toStringList().first();
|
// QString preferredLanguage = settings.value("AppleLanguages").toStringList().first();
|
||||||
// QStringList qtLocale = QLocale::system().name().split('_');
|
// QStringList qtLocale = QLocale::system().name().split('_');
|
||||||
|
|
@ -656,9 +682,9 @@ void App::initLocale() {
|
||||||
// }
|
// }
|
||||||
// QLocale sysLocale = QLocale(qtLocale.join('_'));
|
// QLocale sysLocale = QLocale(qtLocale.join('_'));
|
||||||
// #else
|
// #else
|
||||||
QLocale sysLocale(QLocale::system().name()); // Use Locale from name because Qt has a bug where it didn't use the
|
QLocale sysLocale(QLocale::system().name()); // Use Locale from name because Qt has a bug where it didn't use
|
||||||
// QLocale::language (aka : translator.language != locale.language) on
|
// the QLocale::language (aka : translator.language !=
|
||||||
// Mac. #endif
|
// locale.language) on Mac. #endif
|
||||||
if (installLocale(*this, *mTranslatorCore, sysLocale)) {
|
if (installLocale(*this, *mTranslatorCore, sysLocale)) {
|
||||||
qDebug() << "installed sys locale" << sysLocale.name();
|
qDebug() << "installed sys locale" << sysLocale.name();
|
||||||
setLocale(sysLocale.name());
|
setLocale(sysLocale.name());
|
||||||
|
|
@ -879,7 +905,8 @@ void App::createCommandParser() {
|
||||||
// tr("command_line_option_config_arg")},
|
// tr("command_line_option_config_arg")},
|
||||||
|
|
||||||
{"fetch-config",
|
{"fetch-config",
|
||||||
//: "Specify the linphone configuration file to be fetched. It will be merged with the current configuration."
|
//: "Specify the linphone configuration file to be fetched. It will be merged with the current
|
||||||
|
//: configuration."
|
||||||
tr("command_line_option_config_to_fetch").replace("%1", EXECUTABLE_NAME),
|
tr("command_line_option_config_to_fetch").replace("%1", EXECUTABLE_NAME),
|
||||||
//: "URL, path or file"
|
//: "URL, path or file"
|
||||||
tr("command_line_option_config_to_fetch_arg")},
|
tr("command_line_option_config_to_fetch_arg")},
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,9 @@ public:
|
||||||
static QThread *getLinphoneThread();
|
static QThread *getLinphoneThread();
|
||||||
Notifier *getNotifier() const;
|
Notifier *getNotifier() const;
|
||||||
|
|
||||||
|
EventCountNotifier *getEventCountNotifier();
|
||||||
|
int getEventCount() const;
|
||||||
|
|
||||||
// App::postModelAsync(<lambda>) => run lambda in model thread and continue.
|
// App::postModelAsync(<lambda>) => run lambda in model thread and continue.
|
||||||
// App::postModelSync(<lambda>) => run lambda in current thread and block connection.
|
// App::postModelSync(<lambda>) => run lambda in current thread and block connection.
|
||||||
template <typename Func, typename... Args>
|
template <typename Func, typename... Args>
|
||||||
|
|
@ -119,6 +122,10 @@ public:
|
||||||
void restart();
|
void restart();
|
||||||
bool autoStartEnabled();
|
bool autoStartEnabled();
|
||||||
void setSysTrayIcon();
|
void setSysTrayIcon();
|
||||||
|
QSystemTrayIcon *getSystemTrayIcon() const {
|
||||||
|
return mSystemTrayIcon;
|
||||||
|
}
|
||||||
|
void updateSysTrayCount(int n);
|
||||||
QLocale getLocale();
|
QLocale getLocale();
|
||||||
|
|
||||||
void onLoggerInitialized();
|
void onLoggerInitialized();
|
||||||
|
|
@ -187,6 +194,7 @@ private:
|
||||||
QCommandLineParser *mParser = nullptr;
|
QCommandLineParser *mParser = nullptr;
|
||||||
Thread *mLinphoneThread = nullptr;
|
Thread *mLinphoneThread = nullptr;
|
||||||
Notifier *mNotifier = nullptr;
|
Notifier *mNotifier = nullptr;
|
||||||
|
EventCountNotifier *mEventCountNotifier = nullptr;
|
||||||
QSystemTrayIcon *mSystemTrayIcon = nullptr;
|
QSystemTrayIcon *mSystemTrayIcon = nullptr;
|
||||||
QQuickWindow *mMainWindow = nullptr;
|
QQuickWindow *mMainWindow = nullptr;
|
||||||
QQuickWindow *mCallsWindow = nullptr;
|
QQuickWindow *mCallsWindow = nullptr;
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,8 @@ list(APPEND _LINPHONEAPP_SOURCES
|
||||||
core/emoji/EmojiList.cpp
|
core/emoji/EmojiList.cpp
|
||||||
core/emoji/EmojiModel.cpp
|
core/emoji/EmojiModel.cpp
|
||||||
core/emoji/EmojiProxy.cpp
|
core/emoji/EmojiProxy.cpp
|
||||||
|
core/event-count-notifier/AbstractEventCountNotifier.cpp
|
||||||
|
core/event-count-notifier/EventCountNotifierSystemTrayIcon.cpp
|
||||||
core/fps-counter/FPSCounter.cpp
|
core/fps-counter/FPSCounter.cpp
|
||||||
core/friend/FriendCore.cpp
|
core/friend/FriendCore.cpp
|
||||||
core/friend/FriendGui.cpp
|
core/friend/FriendGui.cpp
|
||||||
|
|
@ -128,5 +130,7 @@ else() # Use QDBus for Linux
|
||||||
core/singleapplication/SingleApplicationDBusPrivate.hpp
|
core/singleapplication/SingleApplicationDBusPrivate.hpp
|
||||||
core/singleapplication/SingleApplicationDBus.cpp)
|
core/singleapplication/SingleApplicationDBus.cpp)
|
||||||
endif()
|
endif()
|
||||||
|
if(APPLE)
|
||||||
|
list(APPEND _LINPHONEAPP_SOURCES core/event-count-notifier/EventCountNotifierMacOs.m)
|
||||||
|
endif()
|
||||||
set(_LINPHONEAPP_SOURCES ${_LINPHONEAPP_SOURCES} PARENT_SCOPE)
|
set(_LINPHONEAPP_SOURCES ${_LINPHONEAPP_SOURCES} PARENT_SCOPE)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||||
|
*
|
||||||
|
* This file is part of linphone-desktop
|
||||||
|
* (see https://www.linphone.org).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <QtDebug>
|
||||||
|
|
||||||
|
#include "core/App.hpp"
|
||||||
|
#include "model/core/CoreModel.hpp"
|
||||||
|
#include "model/setting/SettingsModel.hpp"
|
||||||
|
|
||||||
|
#include "AbstractEventCountNotifier.hpp"
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
DEFINE_ABSTRACT_OBJECT(AbstractEventCountNotifier)
|
||||||
|
|
||||||
|
AbstractEventCountNotifier::AbstractEventCountNotifier(QObject *parent) : QObject(parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
int AbstractEventCountNotifier::getEventCount() const {
|
||||||
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||||
|
auto coreModel = CoreModel::getInstance();
|
||||||
|
int count = coreModel->getCore()->getMissedCallsCount();
|
||||||
|
if (SettingsModel::getInstance()->getStandardChatEnabled() || SettingsModel::getInstance()->getSecureChatEnabled())
|
||||||
|
count += coreModel->getCore()->getUnreadChatMessageCountFromActiveLocals();
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AbstractEventCountNotifier::getCurrentEventCount() const {
|
||||||
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||||
|
auto coreModel = CoreModel::getInstance();
|
||||||
|
int count = coreModel->getCore()->getMissedCallsCount();
|
||||||
|
bool filtered = SettingsModel::getInstance()->isSystrayNotificationFiltered();
|
||||||
|
bool global = SettingsModel::getInstance()->isSystrayNotificationGlobal();
|
||||||
|
// if (global && !filtered)
|
||||||
|
if (true) return getEventCount();
|
||||||
|
else {
|
||||||
|
auto currentAccount = CoreModel::getInstance()->getCore()->getDefaultAccount();
|
||||||
|
if (currentAccount) {
|
||||||
|
auto linphoneChatRooms = currentAccount->filterChatRooms("");
|
||||||
|
for (const auto &chatRoom : linphoneChatRooms) {
|
||||||
|
count += chatRoom->getUnreadMessagesCount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||||
|
*
|
||||||
|
* This file is part of linphone-desktop
|
||||||
|
* (see https://www.linphone.org).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ABSTRACT_EVENT_COUNT_NOTIFIER_H_
|
||||||
|
#define ABSTRACT_EVENT_COUNT_NOTIFIER_H_
|
||||||
|
|
||||||
|
#include <QHash>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QPair>
|
||||||
|
#include <QSystemTrayIcon>
|
||||||
|
|
||||||
|
#include "tool/AbstractObject.hpp"
|
||||||
|
#include "tool/thread/SafeConnection.hpp"
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
namespace linphone {
|
||||||
|
class ChatMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
class CallModel;
|
||||||
|
class ChatRoomModel;
|
||||||
|
class HistoryModel;
|
||||||
|
|
||||||
|
class AbstractEventCountNotifier : public QObject, public AbstractObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
AbstractEventCountNotifier(QObject *parent = Q_NULLPTR);
|
||||||
|
|
||||||
|
int getEventCount() const; // global
|
||||||
|
int getCurrentEventCount() const; // Current account
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void notifyEventCount(int n) = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
DECLARE_ABSTRACT_OBJECT
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ABSTRACT_EVENT_COUNT_NOTIFIER_H_
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||||
|
*
|
||||||
|
* This file is part of linphone-desktop
|
||||||
|
* (see https://www.linphone.org).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EVENT_COUNT_NOTIFIER_MAC_OS_H_
|
||||||
|
#define EVENT_COUNT_NOTIFIER_MAC_OS_H_
|
||||||
|
|
||||||
|
#include "AbstractEventCountNotifier.hpp"
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
extern "C" void notifyEventCountMacOs(int n);
|
||||||
|
|
||||||
|
class EventCountNotifier : public AbstractEventCountNotifier {
|
||||||
|
public:
|
||||||
|
EventCountNotifier(QObject *parent = Q_NULLPTR) : AbstractEventCountNotifier(parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void notifyEventCount(int n) override {
|
||||||
|
notifyEventCountMacOs(n);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // EVENT_COUNT_NOTIFIER_MAC_OS_H_
|
||||||
30
Linphone/core/event-count-notifier/EventCountNotifierMacOs.m
Normal file
30
Linphone/core/event-count-notifier/EventCountNotifierMacOs.m
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* EventCountNotifierMacOs.m
|
||||||
|
* Copyright (C) 2017-2018 Belledonne Communications, Grenoble, France
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* Created on: June 30, 2017
|
||||||
|
* Author: Ghislain MARY
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
void notifyEventCountMacOs (int n) {
|
||||||
|
NSString *badgeStr = (n > 0) ? [NSString stringWithFormat:@"%d", n] : @"";
|
||||||
|
[[NSApp dockTile] setBadgeLabel:badgeStr];
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,134 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||||
|
*
|
||||||
|
* This file is part of linphone-desktop
|
||||||
|
* (see https://www.linphone.org).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <QIcon>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QSvgRenderer>
|
||||||
|
#include <QSystemTrayIcon>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QWindow>
|
||||||
|
|
||||||
|
#include "core/App.hpp"
|
||||||
|
#include "model/core/CoreModel.hpp"
|
||||||
|
#include "model/setting/SettingsModel.hpp"
|
||||||
|
#include "tool/Constants.hpp"
|
||||||
|
#include "tool/Utils.hpp"
|
||||||
|
|
||||||
|
#include "EventCountNotifierSystemTrayIcon.hpp"
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
constexpr int IconWidth = 256;
|
||||||
|
constexpr int IconHeight = 256;
|
||||||
|
|
||||||
|
constexpr int IconCounterBackgroundRadius = 100;
|
||||||
|
constexpr int IconCounterBlinkInterval = 1000;
|
||||||
|
constexpr int IconCounterTextPixelSize = 144;
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
DEFINE_ABSTRACT_OBJECT(EventCountNotifier)
|
||||||
|
|
||||||
|
QSharedPointer<EventCountNotifier> EventCountNotifier::create(QObject *parent) {
|
||||||
|
auto sharedPointer = QSharedPointer<EventCountNotifier>(new EventCountNotifier(parent), &QObject::deleteLater);
|
||||||
|
sharedPointer->setSelf(sharedPointer);
|
||||||
|
sharedPointer->moveToThread(App::getInstance()->thread());
|
||||||
|
return sharedPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
EventCountNotifier::EventCountNotifier(QObject *parent) : AbstractEventCountNotifier(parent) {
|
||||||
|
QSvgRenderer renderer((QString(Constants::WindowIconPath)));
|
||||||
|
if (!renderer.isValid()) qFatal("Invalid SVG Image.");
|
||||||
|
|
||||||
|
QPixmap buf(IconWidth, IconHeight);
|
||||||
|
buf.fill(QColor(Qt::transparent));
|
||||||
|
|
||||||
|
QPainter painter(&buf);
|
||||||
|
renderer.render(&painter);
|
||||||
|
|
||||||
|
mBuf = new QPixmap(buf);
|
||||||
|
mBufWithCounter = new QPixmap();
|
||||||
|
|
||||||
|
mBlinkTimer = new QTimer(this);
|
||||||
|
mBlinkTimer->setInterval(IconCounterBlinkInterval);
|
||||||
|
connect(mBlinkTimer, &QTimer::timeout, this, &EventCountNotifier::update);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventCountNotifier::setSelf(QSharedPointer<EventCountNotifier> me) {
|
||||||
|
}
|
||||||
|
|
||||||
|
EventCountNotifier::~EventCountNotifier() {
|
||||||
|
delete mBuf;
|
||||||
|
delete mBufWithCounter;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void EventCountNotifier::notifyEventCount(int n) {
|
||||||
|
mustBeInMainThread(log().arg(Q_FUNC_INFO));
|
||||||
|
n = n > 99 ? 99 : n;
|
||||||
|
QSystemTrayIcon *sysTrayIcon = App::getInstance()->getSystemTrayIcon();
|
||||||
|
if (!sysTrayIcon) return;
|
||||||
|
|
||||||
|
if (!n) {
|
||||||
|
mBlinkTimer->stop();
|
||||||
|
sysTrayIcon->setIcon(QIcon(*mBuf));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*mBufWithCounter = *mBuf;
|
||||||
|
QPainter p(mBufWithCounter);
|
||||||
|
|
||||||
|
const int width = mBufWithCounter->width();
|
||||||
|
const int height = mBufWithCounter->height();
|
||||||
|
|
||||||
|
// Draw background.
|
||||||
|
{
|
||||||
|
p.setBrush(QColor(Utils::getDefaultStyleColor("main1_100")));
|
||||||
|
p.drawEllipse(QPointF(width / 2, height / 2), IconCounterBackgroundRadius, IconCounterBackgroundRadius);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw text.
|
||||||
|
{
|
||||||
|
QFont font = p.font();
|
||||||
|
font.setPixelSize(IconCounterTextPixelSize);
|
||||||
|
|
||||||
|
p.setFont(font);
|
||||||
|
p.setPen(QPen(QColor(Utils::getDefaultStyleColor("main1_500_main"))));
|
||||||
|
p.drawText(QRect(0, 0, width, height), Qt::AlignCenter, QString::number(n));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change counter.
|
||||||
|
mBlinkTimer->stop();
|
||||||
|
auto coreModel = CoreModel::getInstance();
|
||||||
|
if (!coreModel->isInitialized() || SettingsModel::getInstance()->isSystrayNotificationBlinkEnabled())
|
||||||
|
mBlinkTimer->start();
|
||||||
|
mDisplayCounter = true;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventCountNotifier::update() {
|
||||||
|
mustBeInMainThread(log().arg(Q_FUNC_INFO));
|
||||||
|
QSystemTrayIcon *sysTrayIcon = App::getInstance()->getSystemTrayIcon();
|
||||||
|
if (sysTrayIcon) {
|
||||||
|
sysTrayIcon->setIcon(QIcon(mDisplayCounter ? *mBufWithCounter : *mBuf));
|
||||||
|
}
|
||||||
|
mDisplayCounter = !mDisplayCounter;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||||
|
*
|
||||||
|
* This file is part of linphone-desktop
|
||||||
|
* (see https://www.linphone.org).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EVENT_COUNT_NOTIFIER_SYSTEM_TRAY_ICON_H_
|
||||||
|
#define EVENT_COUNT_NOTIFIER_SYSTEM_TRAY_ICON_H_
|
||||||
|
|
||||||
|
#include "AbstractEventCountNotifier.hpp"
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
class QTimer;
|
||||||
|
|
||||||
|
class EventCountNotifier : public AbstractEventCountNotifier {
|
||||||
|
public:
|
||||||
|
static QSharedPointer<EventCountNotifier> create(QObject *parent = Q_NULLPTR);
|
||||||
|
EventCountNotifier(QObject *parent = Q_NULLPTR);
|
||||||
|
void setSelf(QSharedPointer<EventCountNotifier> me);
|
||||||
|
~EventCountNotifier();
|
||||||
|
|
||||||
|
void notifyEventCount(int n) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const QPixmap *mBuf = nullptr;
|
||||||
|
QPixmap *mBufWithCounter = nullptr;
|
||||||
|
QTimer *mBlinkTimer = nullptr;
|
||||||
|
bool mDisplayCounter = false;
|
||||||
|
QSharedPointer<SafeConnection<EventCountNotifier, CoreModel>> mCoreModelConnection;
|
||||||
|
void update();
|
||||||
|
|
||||||
|
DECLARE_ABSTRACT_OBJECT
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // EVENT_COUNT_NOTIFIER_SYSTEM_TRAY_ICON_H_
|
||||||
|
|
@ -34,6 +34,12 @@
|
||||||
#include "model/tool/ToolModel.hpp"
|
#include "model/tool/ToolModel.hpp"
|
||||||
#include "tool/Utils.hpp"
|
#include "tool/Utils.hpp"
|
||||||
|
|
||||||
|
#if defined(Q_OS_MACOS)
|
||||||
|
#include "core/event-count-notifier/EventCountNotifierMacOs.hpp"
|
||||||
|
#else
|
||||||
|
#include "core/event-count-notifier/EventCountNotifierSystemTrayIcon.hpp"
|
||||||
|
#endif // if defined(Q_OS_MACOS)
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
DEFINE_ABSTRACT_OBJECT(CoreModel)
|
DEFINE_ABSTRACT_OBJECT(CoreModel)
|
||||||
|
|
||||||
|
|
@ -124,9 +130,14 @@ void CoreModel::start() {
|
||||||
mMagicSearch->setSelf(mMagicSearch);
|
mMagicSearch->setSelf(mMagicSearch);
|
||||||
connect(mMagicSearch.get(), &MagicSearchModel::searchResultsReceived, this,
|
connect(mMagicSearch.get(), &MagicSearchModel::searchResultsReceived, this,
|
||||||
[this] { emit magicSearchResultReceived(mMagicSearch->mLastSearch); });
|
[this] { emit magicSearchResultReceived(mMagicSearch->mLastSearch); });
|
||||||
|
mStarted = true;
|
||||||
}
|
}
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool CoreModel::isInitialized() const {
|
||||||
|
return mStarted;
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<CoreModel> CoreModel::getInstance() {
|
std::shared_ptr<CoreModel> CoreModel::getInstance() {
|
||||||
return gCoreModel;
|
return gCoreModel;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include <QSystemTrayIcon>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <linphone++/linphone.hh>
|
#include <linphone++/linphone.hh>
|
||||||
|
|
@ -39,6 +40,9 @@
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
|
class AbstractEventCountNotifier;
|
||||||
|
class EventCountNotifier;
|
||||||
|
|
||||||
class CoreModel : public ::Listener<linphone::Core, linphone::CoreListener>,
|
class CoreModel : public ::Listener<linphone::Core, linphone::CoreListener>,
|
||||||
public linphone::CoreListener,
|
public linphone::CoreListener,
|
||||||
public AbstractObject {
|
public AbstractObject {
|
||||||
|
|
@ -52,6 +56,8 @@ public:
|
||||||
std::shared_ptr<linphone::Core> getCore();
|
std::shared_ptr<linphone::Core> getCore();
|
||||||
std::shared_ptr<LoggerModel> getLogger();
|
std::shared_ptr<LoggerModel> getLogger();
|
||||||
|
|
||||||
|
bool isInitialized() const;
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
void setConfigPath(QString path);
|
void setConfigPath(QString path);
|
||||||
|
|
||||||
|
|
@ -90,6 +96,7 @@ private:
|
||||||
QTimer *mIterateTimer = nullptr;
|
QTimer *mIterateTimer = nullptr;
|
||||||
QMap<QString, OIDCModel *> mOpenIdConnections;
|
QMap<QString, OIDCModel *> mOpenIdConnections;
|
||||||
std::shared_ptr<MagicSearchModel> mMagicSearch;
|
std::shared_ptr<MagicSearchModel> mMagicSearch;
|
||||||
|
bool mStarted = false;
|
||||||
|
|
||||||
void setPathBeforeCreation();
|
void setPathBeforeCreation();
|
||||||
void setPathsAfterCreation();
|
void setPathsAfterCreation();
|
||||||
|
|
|
||||||
|
|
@ -779,11 +779,45 @@ void SettingsModel::setCallForwardToAddress(const QString &data) {
|
||||||
emit(callForwardToAddressChanged(data));
|
emit(callForwardToAddressChanged(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SettingsModel::isSystrayNotificationBlinkEnabled() const {
|
||||||
|
return !!mConfig->getInt(UiSection, "systray_notification_blink", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SettingsModel::isSystrayNotificationGlobal() const {
|
||||||
|
return !!mConfig->getInt(UiSection, "systray_notification_global", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SettingsModel::isSystrayNotificationFiltered() const {
|
||||||
|
return !!mConfig->getInt(UiSection, "systray_notification_filtered", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SettingsModel::getStandardChatEnabled() const {
|
||||||
|
return !getDisableChatFeature() &&
|
||||||
|
!!mConfig->getInt(UiSection, getEntryFullName(UiSection, "standard_chat_enabled"), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SettingsModel::getSecureChatEnabled() const {
|
||||||
|
auto core = CoreModel::getInstance()->getCore();
|
||||||
|
return !getDisableChatFeature() &&
|
||||||
|
!!mConfig->getInt(UiSection, getEntryFullName(UiSection, "secure_chat_enabled"), 1) &&
|
||||||
|
getLimeIsSupported() && core->getDefaultAccount() &&
|
||||||
|
!core->getDefaultAccount()->getParams()->getLimeServerUrl().empty() && getGroupChatEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SettingsModel::getGroupChatEnabled() const {
|
||||||
|
return CoreModel::getInstance()->getCore()->getDefaultAccount() &&
|
||||||
|
!CoreModel::getInstance()->getCore()->getDefaultAccount()->getParams()->getConferenceFactoryUri().empty();
|
||||||
|
}
|
||||||
|
|
||||||
QString SettingsModel::getChatNotificationSoundPath() const {
|
QString SettingsModel::getChatNotificationSoundPath() const {
|
||||||
static const string defaultFile = linphone::Factory::get()->getSoundResourcesDir() + "/incoming_chat.wav";
|
static const string defaultFile = linphone::Factory::get()->getSoundResourcesDir() + "/incoming_chat.wav";
|
||||||
return Utils::coreStringToAppString(mConfig->getString(UiSection, "chat_sound_notification_file", defaultFile));
|
return Utils::coreStringToAppString(mConfig->getString(UiSection, "chat_sound_notification_file", defaultFile));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SettingsModel::getLimeIsSupported() const {
|
||||||
|
return CoreModel::getInstance()->getCore()->limeX3DhAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
void SettingsModel::setChatNotificationSoundPath(const QString &path) {
|
void SettingsModel::setChatNotificationSoundPath(const QString &path) {
|
||||||
QString cleanedPath = QDir::cleanPath(path);
|
QString cleanedPath = QDir::cleanPath(path);
|
||||||
mConfig->setString(UiSection, "chat_sound_notification_file", Utils::appStringToCoreString(cleanedPath));
|
mConfig->setString(UiSection, "chat_sound_notification_file", Utils::appStringToCoreString(cleanedPath));
|
||||||
|
|
|
||||||
|
|
@ -167,6 +167,15 @@ public:
|
||||||
QFont getTextMessageFont() const;
|
QFont getTextMessageFont() const;
|
||||||
int getTextMessageFontSize() const;
|
int getTextMessageFontSize() const;
|
||||||
|
|
||||||
|
bool isSystrayNotificationBlinkEnabled() const;
|
||||||
|
bool isSystrayNotificationGlobal() const;
|
||||||
|
bool isSystrayNotificationFiltered() const;
|
||||||
|
bool getStandardChatEnabled() const;
|
||||||
|
bool getSecureChatEnabled() const;
|
||||||
|
bool getGroupChatEnabled() const;
|
||||||
|
|
||||||
|
bool getLimeIsSupported() const;
|
||||||
|
|
||||||
// UI
|
// UI
|
||||||
DECLARE_GETSET(bool, disableChatFeature, DisableChatFeature)
|
DECLARE_GETSET(bool, disableChatFeature, DisableChatFeature)
|
||||||
DECLARE_GETSET(bool, disableMeetingsFeature, DisableMeetingsFeature)
|
DECLARE_GETSET(bool, disableMeetingsFeature, DisableMeetingsFeature)
|
||||||
|
|
|
||||||
|
|
@ -1726,6 +1726,7 @@ void Utils::runCommandLine(const QString command) {
|
||||||
// Presence
|
// Presence
|
||||||
|
|
||||||
QColor Utils::getDefaultStyleColor(const QString &colorName) {
|
QColor Utils::getDefaultStyleColor(const QString &colorName) {
|
||||||
|
mustBeInMainThread(sLog().arg(Q_FUNC_INFO));
|
||||||
static QObject *defaultStyleSingleton = nullptr;
|
static QObject *defaultStyleSingleton = nullptr;
|
||||||
if (!defaultStyleSingleton) {
|
if (!defaultStyleSingleton) {
|
||||||
QQmlComponent component(App::getInstance()->mEngine, QUrl("qrc:/qt/qml/Linphone/view/Style/DefaultStyle.qml"));
|
QQmlComponent component(App::getInstance()->mEngine, QUrl("qrc:/qt/qml/Linphone/view/Style/DefaultStyle.qml"));
|
||||||
|
|
|
||||||
|
|
@ -466,8 +466,7 @@ Item {
|
||||||
icon.height: Math.round(32 * DefaultStyle.dp)
|
icon.height: Math.round(32 * DefaultStyle.dp)
|
||||||
text: qsTr("settings_title")
|
text: qsTr("settings_title")
|
||||||
icon.source: AppIcons.settings
|
icon.source: AppIcons.settings
|
||||||
onClicked: openContextualMenuComponent(
|
onClicked: openContextualMenuComponent(settingsPageComponent)
|
||||||
settingsPageComponent)
|
|
||||||
KeyNavigation.up: visibleChildren.length
|
KeyNavigation.up: visibleChildren.length
|
||||||
!= 0 ? settingsMenuButton.getPreviousItem(
|
!= 0 ? settingsMenuButton.getPreviousItem(
|
||||||
2) : null
|
2) : null
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue