notifications in navigation bar

This commit is contained in:
Gaelle Braud 2025-08-20 10:58:26 +02:00 committed by gaelle
parent 8566f830d1
commit 836d0b1da3
15 changed files with 489 additions and 12 deletions

View file

@ -109,6 +109,12 @@
#include "tool/thread/Thread.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)
#ifdef Q_OS_LINUX
@ -279,6 +285,7 @@ App::App(int &argc, char *argv[])
// Do not use APPLICATION_NAME here.
// The EXECUTABLE_NAME will be used in qt standard paths. It's our goal.
QThread::currentThread()->setPriority(QThread::HighPriority);
qDebug() << "app thread is" << QThread::currentThread();
QCoreApplication::setApplicationName(EXECUTABLE_NAME);
QApplication::setOrganizationDomain(EXECUTABLE_NAME);
QCoreApplication::setApplicationVersion(APPLICATION_SEMVER);
@ -307,6 +314,7 @@ App::App(int &argc, char *argv[])
emit currentDateChanged();
}
});
mEventCountNotifier = new EventCountNotifier(this);
mDateUpdateTimer.start();
}
@ -402,6 +410,16 @@ void App::setSelf(QSharedPointer<App>(me)) {
auto state = CoreModel::getInstance()->getCore()->getGlobalState();
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->makeConnectToCore(&App::receivedMessage, [this](int, const QByteArray &byteArray) {
@ -430,6 +448,15 @@ QThread *App::getLinphoneThread() {
Notifier *App::getNotifier() const {
return mNotifier;
}
EventCountNotifier *App::getEventCountNotifier() {
return mEventCountNotifier;
}
int App::getEventCount() const {
return mEventCountNotifier ? mEventCountNotifier->getEventCount() : 0;
}
//-----------------------------------------------------------
// Initializations
//-----------------------------------------------------------
@ -474,7 +501,7 @@ void App::initCore() {
CoreModel::create("", mLinphoneThread);
if (mParser->isSet("verbose")) QtLogger::enableVerbose(true);
if (mParser->isSet("qt-logs-only")) QtLogger::enableQtOnly(true);
qDebug() << "linphone thread is" << mLinphoneThread;
QMetaObject::invokeMethod(
mLinphoneThread->getThreadId(),
[this, settings = mSettings]() mutable {
@ -629,7 +656,6 @@ static inline bool installLocale(App &app, QTranslator &translator, const QLocal
}
void App::initLocale() {
// Try to use preferred locale.
QString locale;
@ -644,9 +670,9 @@ void App::initLocale() {
// Try to use system locale.
// #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
// the current system language on QLocale::system(). So we need to get it from user settings and overwrite its
// Locale.
// Use this workaround if there is still an issue about detecting wrong language from system on Mac. Qt doesn't
// use the current system language on QLocale::system(). So we need to get it from user settings and overwrite
// its Locale.
// QSettings settings;
// QString preferredLanguage = settings.value("AppleLanguages").toStringList().first();
// QStringList qtLocale = QLocale::system().name().split('_');
@ -656,9 +682,9 @@ void App::initLocale() {
// }
// QLocale sysLocale = QLocale(qtLocale.join('_'));
// #else
QLocale sysLocale(QLocale::system().name()); // Use Locale from name because Qt has a bug where it didn't use the
// QLocale::language (aka : translator.language != locale.language) on
// Mac. #endif
QLocale sysLocale(QLocale::system().name()); // Use Locale from name because Qt has a bug where it didn't use
// the QLocale::language (aka : translator.language !=
// locale.language) on Mac. #endif
if (installLocale(*this, *mTranslatorCore, sysLocale)) {
qDebug() << "installed sys locale" << sysLocale.name();
setLocale(sysLocale.name());
@ -879,7 +905,8 @@ void App::createCommandParser() {
// tr("command_line_option_config_arg")},
{"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),
//: "URL, path or file"
tr("command_line_option_config_to_fetch_arg")},

View file

@ -54,6 +54,9 @@ public:
static QThread *getLinphoneThread();
Notifier *getNotifier() const;
EventCountNotifier *getEventCountNotifier();
int getEventCount() const;
// App::postModelAsync(<lambda>) => run lambda in model thread and continue.
// App::postModelSync(<lambda>) => run lambda in current thread and block connection.
template <typename Func, typename... Args>
@ -119,6 +122,10 @@ public:
void restart();
bool autoStartEnabled();
void setSysTrayIcon();
QSystemTrayIcon *getSystemTrayIcon() const {
return mSystemTrayIcon;
}
void updateSysTrayCount(int n);
QLocale getLocale();
void onLoggerInitialized();
@ -187,6 +194,7 @@ private:
QCommandLineParser *mParser = nullptr;
Thread *mLinphoneThread = nullptr;
Notifier *mNotifier = nullptr;
EventCountNotifier *mEventCountNotifier = nullptr;
QSystemTrayIcon *mSystemTrayIcon = nullptr;
QQuickWindow *mMainWindow = nullptr;
QQuickWindow *mCallsWindow = nullptr;

View file

@ -40,6 +40,8 @@ list(APPEND _LINPHONEAPP_SOURCES
core/emoji/EmojiList.cpp
core/emoji/EmojiModel.cpp
core/emoji/EmojiProxy.cpp
core/event-count-notifier/AbstractEventCountNotifier.cpp
core/event-count-notifier/EventCountNotifierSystemTrayIcon.cpp
core/fps-counter/FPSCounter.cpp
core/friend/FriendCore.cpp
core/friend/FriendGui.cpp
@ -128,5 +130,7 @@ else() # Use QDBus for Linux
core/singleapplication/SingleApplicationDBusPrivate.hpp
core/singleapplication/SingleApplicationDBus.cpp)
endif()
if(APPLE)
list(APPEND _LINPHONEAPP_SOURCES core/event-count-notifier/EventCountNotifierMacOs.m)
endif()
set(_LINPHONEAPP_SOURCES ${_LINPHONEAPP_SOURCES} PARENT_SCOPE)

View file

@ -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;
}
}

View file

@ -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_

View file

@ -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_

View 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];
}

View file

@ -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;
}

View file

@ -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_

View file

@ -34,6 +34,12 @@
#include "model/tool/ToolModel.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)
@ -124,9 +130,14 @@ void CoreModel::start() {
mMagicSearch->setSelf(mMagicSearch);
connect(mMagicSearch.get(), &MagicSearchModel::searchResultsReceived, this,
[this] { emit magicSearchResultReceived(mMagicSearch->mLastSearch); });
mStarted = true;
}
// -----------------------------------------------------------------------------
bool CoreModel::isInitialized() const {
return mStarted;
}
std::shared_ptr<CoreModel> CoreModel::getInstance() {
return gCoreModel;
}

View file

@ -25,6 +25,7 @@
#include <QObject>
#include <QSharedPointer>
#include <QString>
#include <QSystemTrayIcon>
#include <QThread>
#include <QTimer>
#include <linphone++/linphone.hh>
@ -39,6 +40,9 @@
// =============================================================================
class AbstractEventCountNotifier;
class EventCountNotifier;
class CoreModel : public ::Listener<linphone::Core, linphone::CoreListener>,
public linphone::CoreListener,
public AbstractObject {
@ -52,6 +56,8 @@ public:
std::shared_ptr<linphone::Core> getCore();
std::shared_ptr<LoggerModel> getLogger();
bool isInitialized() const;
void start();
void setConfigPath(QString path);
@ -90,6 +96,7 @@ private:
QTimer *mIterateTimer = nullptr;
QMap<QString, OIDCModel *> mOpenIdConnections;
std::shared_ptr<MagicSearchModel> mMagicSearch;
bool mStarted = false;
void setPathBeforeCreation();
void setPathsAfterCreation();

View file

@ -779,11 +779,45 @@ void SettingsModel::setCallForwardToAddress(const QString &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 {
static const string defaultFile = linphone::Factory::get()->getSoundResourcesDir() + "/incoming_chat.wav";
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) {
QString cleanedPath = QDir::cleanPath(path);
mConfig->setString(UiSection, "chat_sound_notification_file", Utils::appStringToCoreString(cleanedPath));

View file

@ -167,6 +167,15 @@ public:
QFont getTextMessageFont() 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
DECLARE_GETSET(bool, disableChatFeature, DisableChatFeature)
DECLARE_GETSET(bool, disableMeetingsFeature, DisableMeetingsFeature)

View file

@ -1726,6 +1726,7 @@ void Utils::runCommandLine(const QString command) {
// Presence
QColor Utils::getDefaultStyleColor(const QString &colorName) {
mustBeInMainThread(sLog().arg(Q_FUNC_INFO));
static QObject *defaultStyleSingleton = nullptr;
if (!defaultStyleSingleton) {
QQmlComponent component(App::getInstance()->mEngine, QUrl("qrc:/qt/qml/Linphone/view/Style/DefaultStyle.qml"));

View file

@ -466,8 +466,7 @@ Item {
icon.height: Math.round(32 * DefaultStyle.dp)
text: qsTr("settings_title")
icon.source: AppIcons.settings
onClicked: openContextualMenuComponent(
settingsPageComponent)
onClicked: openContextualMenuComponent(settingsPageComponent)
KeyNavigation.up: visibleChildren.length
!= 0 ? settingsMenuButton.getPreviousItem(
2) : null