1
0
Fork 0
mirror of https://git.jami.net/savoirfairelinux/jami-client-qt.git synced 2025-08-04 23:05:48 +02:00

injection: remove the remaining c++ singleton classes

- refactor qml object registration
- inject AppSettingsManager and SystemTray

Gitlab: #320
Change-Id: Ic8232a290003245d09ad9452c9f5518fd260af78
This commit is contained in:
Andreas Traczyk 2021-03-30 15:15:36 -04:00
parent 552c445c8d
commit 4ce208ec33
27 changed files with 362 additions and 249 deletions

View file

@ -69,7 +69,9 @@ set(COMMON_SOURCES
${SRC_DIR}/dbuserrorhandler.cpp ${SRC_DIR}/dbuserrorhandler.cpp
${SRC_DIR}/xrectsel.c ${SRC_DIR}/xrectsel.c
${SRC_DIR}/moderatorlistmodel.cpp ${SRC_DIR}/moderatorlistmodel.cpp
${SRC_DIR}/screensaver.cpp) ${SRC_DIR}/screensaver.cpp
${SRC_DIR}/systemtray.cpp
${SRC_DIR}/appsettingsmanager.cpp)
set(COMMON_HEADERS set(COMMON_HEADERS
${SRC_DIR}/avatarimageprovider.h ${SRC_DIR}/avatarimageprovider.h
@ -82,8 +84,6 @@ set(COMMON_HEADERS
${SRC_DIR}/accountlistmodel.h ${SRC_DIR}/accountlistmodel.h
${SRC_DIR}/runguard.h ${SRC_DIR}/runguard.h
${SRC_DIR}/lrcinstance.h ${SRC_DIR}/lrcinstance.h
${SRC_DIR}/globalsystemtray.h
${SRC_DIR}/appsettingsmanager.h
${SRC_DIR}/webchathelpers.h ${SRC_DIR}/webchathelpers.h
${SRC_DIR}/rendermanager.h ${SRC_DIR}/rendermanager.h
${SRC_DIR}/connectivitymonitor.h ${SRC_DIR}/connectivitymonitor.h
@ -122,7 +122,9 @@ set(COMMON_HEADERS
${SRC_DIR}/dbuserrorhandler.h ${SRC_DIR}/dbuserrorhandler.h
${SRC_DIR}/xrectsel.h ${SRC_DIR}/xrectsel.h
${SRC_DIR}/moderatorlistmodel.h ${SRC_DIR}/moderatorlistmodel.h
${SRC_DIR}/screensaver.h) ${SRC_DIR}/screensaver.h
${SRC_DIR}/systemtray.h
${SRC_DIR}/appsettingsmanager.h)
find_package(PkgConfig REQUIRED) find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBNM libnm) pkg_check_modules(LIBNM libnm)

View file

@ -92,7 +92,7 @@ Variables `QT5_VER` and `QT5_PATH` are used to specify version and path for a cu
If lrc library is installed in a custom directory you can set its path with the variable LRC. Additionally you can specify built library location with `LRCLIB` (otherwise it will seach inside LRC with the suffixes `/lib`, `/build` and `/build-local`). If lrc library is installed in a custom directory you can set its path with the variable LRC. Additionally you can specify built library location with `LRCLIB` (otherwise it will seach inside LRC with the suffixes `/lib`, `/build` and `/build-local`).
After the build has finished, you are finally ready to launch jami-qt in your build directory. After the build has finished, you are finally ready to launch jami-qt in your build directory.
If you want to install it to the path provided by `CMAKE_INSTALL_PREFIX` you can run: If you want to install it to the path provided by `CMAKE_INSTALL_PREFIX` you can run:
@ -162,7 +162,7 @@ Only 64-bit MSVC build can be compiled.
> By default: ```toolset=v141```, ```sdk=10.0.16299.0```, ```qtver=5.9.4``` <br> > By default: ```toolset=v141```, ```sdk=10.0.16299.0```, ```qtver=5.9.4``` <br>
> For example: > For example:
```sh ```sh
python make-ring.py --install --toolset v142 --sdk 10.0.18362.0 --qtver 5.12.0 python make-ring.py --install --toolset v142 --sdk 10.0.18362.0 --qtver 5.14.0
``` ```
### Build Module individually ### Build Module individually

View file

@ -176,8 +176,6 @@ HEADERS += \
src/accountlistmodel.h \ src/accountlistmodel.h \
src/runguard.h \ src/runguard.h \
src/lrcinstance.h \ src/lrcinstance.h \
src/globalsystemtray.h \
src/appsettingsmanager.h \
src/webchathelpers.h \ src/webchathelpers.h \
src/rendermanager.h \ src/rendermanager.h \
src/connectivitymonitor.h \ src/connectivitymonitor.h \
@ -210,7 +208,9 @@ HEADERS += \
src/audiomanagerlistmodel.h \ src/audiomanagerlistmodel.h \
src/qmlregister.h \ src/qmlregister.h \
src/qtutils.h \ src/qtutils.h \
src/utilsadapter.h src/utilsadapter.h \
src/systemtray.h \
src/appsettingsmanager.h
SOURCES += \ SOURCES += \
src/bannedlistmodel.cpp \ src/bannedlistmodel.cpp \
@ -250,7 +250,9 @@ SOURCES += \
src/videoformatresolutionmodel.cpp \ src/videoformatresolutionmodel.cpp \
src/audiomanagerlistmodel.cpp \ src/audiomanagerlistmodel.cpp \
src/qmlregister.cpp \ src/qmlregister.cpp \
src/utilsadapter.cpp src/utilsadapter.cpp \
src/systemtray.cpp \
src/appsettingsmanager.cpp
RESOURCES += \ RESOURCES += \
resources.qrc \ resources.qrc \

View file

@ -23,12 +23,16 @@
#include "accountadapter.h" #include "accountadapter.h"
#include "appsettingsmanager.h"
#include "qtutils.h" #include "qtutils.h"
#include <QtConcurrent/QtConcurrent> #include <QtConcurrent/QtConcurrent>
AccountAdapter::AccountAdapter(LRCInstance* instance, QObject* parent) AccountAdapter::AccountAdapter(AppSettingsManager* settingsManager,
LRCInstance* instance,
QObject* parent)
: QmlAdapterBase(instance, parent) : QmlAdapterBase(instance, parent)
, settingsManager_(settingsManager)
{} {}
void void
@ -100,7 +104,7 @@ AccountAdapter::createJamiAccount(QString registeredName,
lrcInstance_->accountModel().setAccountConfig(accountId, confProps); lrcInstance_->accountModel().setAccountConfig(accountId, confProps);
auto showBackup = isCreating auto showBackup = isCreating
&& !AppSettingsManager::getValue(Settings::Key::NeverShowMeAgain) && !settingsManager_->getValue(Settings::Key::NeverShowMeAgain)
.toBool(); .toBool();
if (!registeredName.isEmpty()) { if (!registeredName.isEmpty()) {
QObject::disconnect(registeredNameSavedConnection_); QObject::disconnect(registeredNameSavedConnection_);

View file

@ -27,6 +27,8 @@
#include "lrcinstance.h" #include "lrcinstance.h"
#include "utils.h" #include "utils.h"
class AppSettingsManager;
class AccountAdapter final : public QmlAdapterBase class AccountAdapter final : public QmlAdapterBase
{ {
Q_OBJECT Q_OBJECT
@ -50,7 +52,9 @@ signals:
void accountListSizeChanged(); void accountListSizeChanged();
public: public:
explicit AccountAdapter(LRCInstance* instance, QObject* parent = nullptr); explicit AccountAdapter(AppSettingsManager* settingsManager,
LRCInstance* instance,
QObject* parent = nullptr);
~AccountAdapter() = default; ~AccountAdapter() = default;
protected: protected:
@ -132,5 +136,7 @@ private:
QMetaObject::Connection addedToConferenceConnection_; QMetaObject::Connection addedToConferenceConnection_;
QMetaObject::Connection contactUnbannedConnection_; QMetaObject::Connection contactUnbannedConnection_;
QMetaObject::Connection registeredNameSavedConnection_; QMetaObject::Connection registeredNameSavedConnection_;
AppSettingsManager* settingsManager_;
}; };
Q_DECLARE_METATYPE(AccountAdapter*) Q_DECLARE_METATYPE(AccountAdapter*)

View file

@ -0,0 +1,50 @@
/*!
* Copyright (C) 2021 by Savoir-faire Linux
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
*
* 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 <https://www.gnu.org/licenses/>.
*
* \file appsettingsmanager.cpp
*/
#include "appsettingsmanager.h"
AppSettingsManager::AppSettingsManager(QObject* parent)
: QObject(parent)
, settings_(new QSettings("jami.net", "Jami", this))
{
for (int i = 0; i < static_cast<int>(Settings::Key::COUNT__); ++i) {
auto key = static_cast<Settings::Key>(i);
if (!settings_->contains(Settings::toString(key)))
setValue(key, Settings::defaultValue(key));
}
}
QVariant
AppSettingsManager::getValue(const Settings::Key key)
{
auto value = settings_->value(Settings::toString(key), Settings::defaultValue(key));
if (QString(value.typeName()) == "QString"
&& (value.toString() == "false" || value.toString() == "true"))
return value.toBool();
return value;
}
void
AppSettingsManager::setValue(const Settings::Key key, const QVariant& value)
{
settings_->setValue(Settings::toString(key), value);
}

View file

@ -1,5 +1,5 @@
/*! /*!
* Copyright (C) 2020 by Savoir-faire Linux * Copyright (C) 2020-2021 by Savoir-faire Linux
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -84,51 +84,16 @@ private:
Q_DECLARE_METATYPE(Settings::Key) Q_DECLARE_METATYPE(Settings::Key)
// clang-format on // clang-format on
/*
* A singleton object to manage settings access.
*/
class AppSettingsManager : public QObject class AppSettingsManager : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
virtual ~AppSettingsManager() = default; explicit AppSettingsManager(QObject* parent = nullptr);
~AppSettingsManager() = default;
static AppSettingsManager& instance() QVariant getValue(const Settings::Key key);
{ void setValue(const Settings::Key key, const QVariant& value);
static AppSettingsManager* instance_ = new AppSettingsManager(nullptr);
return *instance_;
}
static QVariant getValue(const Settings::Key key)
{
auto settings = instance().settings_;
auto value = settings->value(Settings::toString(key), Settings::defaultValue(key));
if (QString(value.typeName()) == "QString"
&& (value.toString() == "false" || value.toString() == "true"))
return value.toBool();
return value;
}
static void setValue(const Settings::Key key, const QVariant& value)
{
instance().settings_->setValue(Settings::toString(key), value);
}
static void initValues()
{
for (int i = 0; i < static_cast<int>(Settings::Key::COUNT__); ++i) {
auto key = static_cast<Settings::Key>(i);
if (!instance().settings_->contains(Settings::toString(key)))
setValue(key, Settings::defaultValue(key));
}
}
private: private:
explicit AppSettingsManager(QObject*)
: settings_(new QSettings("jami.net", "Jami", this))
{}
QSettings* settings_; QSettings* settings_;
}; };

View file

@ -23,13 +23,16 @@
*/ */
#include "calladapter.h" #include "calladapter.h"
#include "systemtray.h"
#include "utils.h" #include "utils.h"
#include <QApplication> #include <QApplication>
CallAdapter::CallAdapter(LRCInstance* instance, QObject* parent) CallAdapter::CallAdapter(SystemTray* systemTray, LRCInstance* instance, QObject* parent)
: QmlAdapterBase(instance, parent) : QmlAdapterBase(instance, parent)
, oneSecondTimer_(new QTimer(this)) , oneSecondTimer_(new QTimer(this))
, systemTray_(systemTray)
{ {
accountId_ = lrcInstance_->getCurrAccId(); accountId_ = lrcInstance_->getCurrAccId();
connectCallModel(accountId_); connectCallModel(accountId_);
@ -335,7 +338,7 @@ CallAdapter::showNotification(const QString& accountId, const QString& convUid)
emit callSetupMainViewRequired(convInfo.accountId, convInfo.uid); emit callSetupMainViewRequired(convInfo.accountId, convInfo.uid);
}; };
emit lrcInstance_->updateSmartList(); emit lrcInstance_->updateSmartList();
Utils::showNotification(tr("is calling you"), from, accountId, convUid, onClicked); systemTray_->showNotification(tr("is calling you"), from, onClicked);
} }
void void

View file

@ -28,6 +28,8 @@
#include <QVariant> #include <QVariant>
#include <QSystemTrayIcon> #include <QSystemTrayIcon>
class SystemTray;
class CallAdapter final : public QmlAdapterBase class CallAdapter final : public QmlAdapterBase
{ {
Q_OBJECT Q_OBJECT
@ -36,7 +38,7 @@ public:
enum MuteStates { UNMUTED, LOCAL_MUTED, MODERATOR_MUTED, BOTH_MUTED }; enum MuteStates { UNMUTED, LOCAL_MUTED, MODERATOR_MUTED, BOTH_MUTED };
Q_ENUM(MuteStates) Q_ENUM(MuteStates)
explicit CallAdapter(LRCInstance* instance, QObject* parent = nullptr); explicit CallAdapter(SystemTray* systemTray, LRCInstance* instance, QObject* parent = nullptr);
~CallAdapter() = default; ~CallAdapter() = default;
protected: protected:
@ -124,4 +126,6 @@ private:
ScreenSaver screenSaver; ScreenSaver screenSaver;
void preventScreenSaver(bool state); void preventScreenSaver(bool state);
SystemTray* systemTray_;
}; };

View file

@ -56,11 +56,8 @@ public:
virtual bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const virtual bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const
{ {
// Accept all contacts in conversation list filtered with account type, except those in a call. // Accept all contacts in conversation list filtered with account type, except those in a call.
auto index = sourceModel()->index(source_row, 0, source_parent); auto index = sourceModel()->index(source_row, 0, source_parent);
if (filterPredicate_) { return filterPredicate_ ? filterPredicate_(index, filterRegExp()) : false;
return filterPredicate_(index, filterRegExp());
}
} }
private: private:

View file

@ -25,11 +25,15 @@
#include "utils.h" #include "utils.h"
#include "qtutils.h" #include "qtutils.h"
#include "systemtray.h"
#include <QApplication> #include <QApplication>
ConversationsAdapter::ConversationsAdapter(LRCInstance* instance, QObject* parent) ConversationsAdapter::ConversationsAdapter(SystemTray* systemTray,
LRCInstance* instance,
QObject* parent)
: QmlAdapterBase(instance, parent) : QmlAdapterBase(instance, parent)
, systemTray_(systemTray)
{ {
connect(this, &ConversationsAdapter::currentTypeFilterChanged, [this]() { connect(this, &ConversationsAdapter::currentTypeFilterChanged, [this]() {
lrcInstance_->getCurrentConversationModel()->setFilter(currentTypeFilter_); lrcInstance_->getCurrentConversationModel()->setFilter(currentTypeFilter_);
@ -163,7 +167,7 @@ ConversationsAdapter::onNewUnreadInteraction(const QString& accountId,
} }
}; };
Utils::showNotification(interaction.body, from, accountId, convUid, onClicked); systemTray_->showNotification(interaction.body, from, onClicked);
return; return;
} }
} }

View file

@ -25,6 +25,8 @@
#include <QObject> #include <QObject>
#include <QString> #include <QString>
class SystemTray;
class ConversationsAdapter final : public QmlAdapterBase class ConversationsAdapter final : public QmlAdapterBase
{ {
Q_OBJECT Q_OBJECT
@ -32,7 +34,9 @@ class ConversationsAdapter final : public QmlAdapterBase
Q_PROPERTY(lrc::api::profile::Type currentTypeFilter MEMBER currentTypeFilter_ NOTIFY Q_PROPERTY(lrc::api::profile::Type currentTypeFilter MEMBER currentTypeFilter_ NOTIFY
currentTypeFilterChanged) currentTypeFilterChanged)
public: public:
explicit ConversationsAdapter(LRCInstance* instance, QObject* parent = nullptr); explicit ConversationsAdapter(SystemTray* systemTray,
LRCInstance* instance,
QObject* parent = nullptr);
~ConversationsAdapter() = default; ~ConversationsAdapter() = default;
protected: protected:
@ -86,4 +90,6 @@ private:
QMetaObject::Connection interactionRemovedConnection_; QMetaObject::Connection interactionRemovedConnection_;
QMetaObject::Connection searchStatusChangedConnection_; QMetaObject::Connection searchStatusChangedConnection_;
QMetaObject::Connection searchResultUpdatedConnection_; QMetaObject::Connection searchResultUpdatedConnection_;
SystemTray* systemTray_;
}; };

View file

@ -26,7 +26,6 @@
#include "updatemanager.h" #include "updatemanager.h"
#include "rendermanager.h" #include "rendermanager.h"
#include "appsettingsmanager.h"
#include "utils.h" #include "utils.h"
#include "api/account.h" #include "api/account.h"

View file

@ -21,15 +21,25 @@
#include "mainapplication.h" #include "mainapplication.h"
#include "qmlregister.h"
#include "appsettingsmanager.h" #include "appsettingsmanager.h"
#include "connectivitymonitor.h" #include "connectivitymonitor.h"
#include "globalsystemtray.h" #include "systemtray.h"
#include "namedirectory.h" #include "namedirectory.h"
#include "qmlregister.h"
#include "qrimageprovider.h" #include "qrimageprovider.h"
#include "tintedbuttonimageprovider.h" #include "tintedbuttonimageprovider.h"
#include "avatarimageprovider.h" #include "avatarimageprovider.h"
#include "accountadapter.h"
#include "avadapter.h"
#include "calladapter.h"
#include "contactadapter.h"
#include "pluginadapter.h"
#include "messagesadapter.h"
#include "settingsadapter.h"
#include "utilsadapter.h"
#include "conversationsadapter.h"
#include <QAction> #include <QAction>
#include <QCommandLineParser> #include <QCommandLineParser>
#include <QCoreApplication> #include <QCoreApplication>
@ -146,6 +156,8 @@ MainApplication::MainApplication(int& argc, char** argv)
: QApplication(argc, argv) : QApplication(argc, argv)
, engine_(new QQmlApplicationEngine()) , engine_(new QQmlApplicationEngine())
, connectivityMonitor_(new ConnectivityMonitor(this)) , connectivityMonitor_(new ConnectivityMonitor(this))
, settingsManager_(new AppSettingsManager(this))
, systemTray_(new SystemTray(settingsManager_, this))
{ {
QObject::connect(this, &QApplication::aboutToQuit, [this] { cleanup(); }); QObject::connect(this, &QApplication::aboutToQuit, [this] { cleanup(); });
} }
@ -233,9 +245,11 @@ MainApplication::init()
vsConsoleDebug(); vsConsoleDebug();
} }
initSettings(); auto downloadPath = settingsManager_->getValue(Settings::Key::DownloadPath);
lrcInstance_->dataTransferModel().downloadDirectory = downloadPath.toString() + "/";
initQmlLayer();
initSystray(); initSystray();
initQmlEngine();
return true; return true;
} }
@ -394,9 +408,37 @@ MainApplication::setApplicationFont()
} }
void void
MainApplication::initQmlEngine() MainApplication::initQmlLayer()
{ {
registerTypes(lrcInstance_.get()); // setup the adapters (their lifetimes are that of MainApplication)
auto callAdapter = new CallAdapter(systemTray_, lrcInstance_.data(), this);
auto messagesAdapter = new MessagesAdapter(settingsManager_, lrcInstance_.data(), this);
auto conversationsAdapter = new ConversationsAdapter(systemTray_, lrcInstance_.data(), this);
auto avAdapter = new AvAdapter(lrcInstance_.data(), this);
auto contactAdapter = new ContactAdapter(lrcInstance_.data(), this);
auto accountAdapter = new AccountAdapter(settingsManager_, lrcInstance_.data(), this);
auto utilsAdapter = new UtilsAdapter(systemTray_, lrcInstance_.data(), this);
auto settingsAdapter = new SettingsAdapter(settingsManager_, lrcInstance_.data(), this);
auto pluginAdapter = new PluginAdapter(lrcInstance_.data(), this);
// qml adapter registration
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, callAdapter, "CallAdapter");
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, messagesAdapter, "MessagesAdapter");
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, conversationsAdapter, "ConversationsAdapter");
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, avAdapter, "AvAdapter");
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, contactAdapter, "ContactAdapter");
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, accountAdapter, "AccountAdapter");
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, utilsAdapter, "UtilsAdapter");
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, settingsAdapter, "SettingsAdapter");
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, pluginAdapter, "PluginAdapter");
// TODO: remove these
QML_REGISTERSINGLETONTYPE_CUSTOM(NS_MODELS, AVModel, &lrcInstance_->avModel())
QML_REGISTERSINGLETONTYPE_CUSTOM(NS_MODELS, PluginModel, &lrcInstance_->pluginModel())
QML_REGISTERSINGLETONTYPE_CUSTOM(NS_HELPERS, UpdateManager, lrcInstance_->getUpdateManager())
// register other types that don't require injection(e.g. uncreatables, c++/qml singletons)
Utils::registerTypes();
engine_->addImageProvider(QLatin1String("qrImage"), new QrImageProvider(lrcInstance_.get())); engine_->addImageProvider(QLatin1String("qrImage"), new QrImageProvider(lrcInstance_.get()));
engine_->addImageProvider(QLatin1String("tintedPixmap"), engine_->addImageProvider(QLatin1String("tintedPixmap"),
@ -416,19 +458,10 @@ MainApplication::initQmlEngine()
engine_->load(QUrl(QStringLiteral("qrc:/src/MainApplicationWindow.qml"))); engine_->load(QUrl(QStringLiteral("qrc:/src/MainApplicationWindow.qml")));
} }
void
MainApplication::initSettings()
{
AppSettingsManager::instance().initValues();
auto downloadPath = AppSettingsManager::instance().getValue(Settings::Key::DownloadPath);
lrcInstance_->dataTransferModel().downloadDirectory = downloadPath.toString() + "/";
}
void void
MainApplication::initSystray() MainApplication::initSystray()
{ {
GlobalSystemTray& sysIcon = GlobalSystemTray::instance(); systemTray_->setIcon(QIcon(":images/jami.png"));
sysIcon.setIcon(QIcon(":images/jami.png"));
QMenu* systrayMenu = new QMenu(); QMenu* systrayMenu = new QMenu();
@ -437,20 +470,21 @@ MainApplication::initSystray()
engine_->quit(); engine_->quit();
cleanup(); cleanup();
}); });
connect(&sysIcon, &QSystemTrayIcon::activated, [this](QSystemTrayIcon::ActivationReason reason) { connect(systemTray_,
if (reason != QSystemTrayIcon::ActivationReason::Context) &QSystemTrayIcon::activated,
restoreApp(); [this](QSystemTrayIcon::ActivationReason reason) {
}); if (reason != QSystemTrayIcon::ActivationReason::Context)
restoreApp();
});
systrayMenu->addAction(exitAction); systrayMenu->addAction(exitAction);
sysIcon.setContextMenu(systrayMenu); systemTray_->setContextMenu(systrayMenu);
sysIcon.show(); systemTray_->show();
} }
void void
MainApplication::cleanup() MainApplication::cleanup()
{ {
GlobalSystemTray::instance().hide();
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
FreeConsole(); FreeConsole();
#endif #endif

View file

@ -32,6 +32,8 @@
#include <memory> #include <memory>
class ConnectivityMonitor; class ConnectivityMonitor;
class AppSettingsManager;
class SystemTray;
// Provides information about the screen the app is displayed on // Provides information about the screen the app is displayed on
class ScreenInfo : public QObject class ScreenInfo : public QObject
@ -81,16 +83,19 @@ private:
void initLrc(const QString& downloadUrl, ConnectivityMonitor* cm); void initLrc(const QString& downloadUrl, ConnectivityMonitor* cm);
const QVariantMap parseArguments(); const QVariantMap parseArguments();
void setApplicationFont(); void setApplicationFont();
void initQmlEngine(); void initQmlLayer();
void initSettings();
void initSystray(); void initSystray();
void cleanup(); void cleanup();
private: private:
QScopedPointer<QFile> debugFile_; QScopedPointer<QFile> debugFile_;
QScopedPointer<QQmlApplicationEngine> engine_; QScopedPointer<QQmlApplicationEngine> engine_;
QScopedPointer<LRCInstance> lrcInstance_; QScopedPointer<LRCInstance> lrcInstance_;
ConnectivityMonitor* connectivityMonitor_ {nullptr};
ConnectivityMonitor* connectivityMonitor_;
AppSettingsManager* settingsManager_;
SystemTray* systemTray_;
ScreenInfo screenInfo_; ScreenInfo screenInfo_;
}; };

View file

@ -23,6 +23,7 @@
#include "messagesadapter.h" #include "messagesadapter.h"
#include "appsettingsmanager.h"
#include "qtutils.h" #include "qtutils.h"
#include "utils.h" #include "utils.h"
#include "webchathelpers.h" #include "webchathelpers.h"
@ -35,8 +36,11 @@
#include <QList> #include <QList>
#include <QUrl> #include <QUrl>
MessagesAdapter::MessagesAdapter(LRCInstance* instance, QObject* parent) MessagesAdapter::MessagesAdapter(AppSettingsManager* settingsManager,
LRCInstance* instance,
QObject* parent)
: QmlAdapterBase(instance, parent) : QmlAdapterBase(instance, parent)
, settingsManager_(settingsManager)
{} {}
void void
@ -94,7 +98,7 @@ MessagesAdapter::setupChatView(const QString& convUid)
connect(lrcInstance_->getCurrentConversationModel(), connect(lrcInstance_->getCurrentConversationModel(),
&ConversationModel::composingStatusChanged, &ConversationModel::composingStatusChanged,
[this](const QString& convUid, const QString& contactUri, bool isComposing) { [this](const QString& convUid, const QString& contactUri, bool isComposing) {
if (!AppSettingsManager::getValue(Settings::Key::EnableTypingIndicator).toBool()) { if (!settingsManager_->getValue(Settings::Key::EnableTypingIndicator).toBool()) {
return; return;
} }
contactIsComposing(convUid, contactUri, isComposing); contactIsComposing(convUid, contactUri, isComposing);
@ -438,7 +442,7 @@ MessagesAdapter::pasteKeyDetected()
void void
MessagesAdapter::onComposing(bool isComposing) MessagesAdapter::onComposing(bool isComposing)
{ {
if (!AppSettingsManager::getValue(Settings::Key::EnableTypingIndicator).toBool()) { if (!settingsManager_->getValue(Settings::Key::EnableTypingIndicator).toBool()) {
return; return;
} }
lrcInstance_->getCurrentConversationModel()->setIsComposing(lrcInstance_->getCurrentConvUid(), lrcInstance_->getCurrentConversationModel()->setIsComposing(lrcInstance_->getCurrentConvUid(),
@ -550,8 +554,7 @@ void
MessagesAdapter::setDisplayLinks() MessagesAdapter::setDisplayLinks()
{ {
QString s = QString::fromLatin1("setDisplayLinks(%1);") QString s = QString::fromLatin1("setDisplayLinks(%1);")
.arg( .arg(settingsManager_->getValue(Settings::Key::DisplayImagesChatview).toBool());
AppSettingsManager::getValue(Settings::Key::DisplayImagesChatview).toBool());
QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s)); QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s));
} }

View file

@ -25,13 +25,17 @@
#include <QObject> #include <QObject>
#include <QString> #include <QString>
class AppSettingsManager;
class MessagesAdapter final : public QmlAdapterBase class MessagesAdapter final : public QmlAdapterBase
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QVariantMap chatviewTranslatedStrings MEMBER chatviewTranslatedStrings_ CONSTANT) Q_PROPERTY(QVariantMap chatviewTranslatedStrings MEMBER chatviewTranslatedStrings_ CONSTANT)
public: public:
explicit MessagesAdapter(LRCInstance* instance, QObject* parent = nullptr); explicit MessagesAdapter(AppSettingsManager* settingsManager,
LRCInstance* instance,
QObject* parent = nullptr);
~MessagesAdapter() = default; ~MessagesAdapter() = default;
protected: protected:
@ -115,4 +119,6 @@ private:
QMetaObject::Connection newInteractionConnection_; QMetaObject::Connection newInteractionConnection_;
QMetaObject::Connection interactionStatusUpdatedConnection_; QMetaObject::Connection interactionStatusUpdatedConnection_;
QMetaObject::Connection interactionRemovedConnection_; QMetaObject::Connection interactionRemovedConnection_;
AppSettingsManager* settingsManager_;
}; };

View file

@ -18,28 +18,22 @@
#include "qmlregister.h" #include "qmlregister.h"
#include "accountadapter.h"
#include "accountlistmodel.h" #include "accountlistmodel.h"
#include "accountstomigratelistmodel.h" #include "accountstomigratelistmodel.h"
#include "mediacodeclistmodel.h" #include "mediacodeclistmodel.h"
#include "audiodevicemodel.h" #include "audiodevicemodel.h"
#include "audiomanagerlistmodel.h" #include "audiomanagerlistmodel.h"
#include "avadapter.h"
#include "bannedlistmodel.h" #include "bannedlistmodel.h"
#include "moderatorlistmodel.h" #include "moderatorlistmodel.h"
#include "calladapter.h"
#include "contactadapter.h"
#include "conversationsadapter.h"
#include "deviceitemlistmodel.h" #include "deviceitemlistmodel.h"
#include "smartlistmodel.h"
#include "appsettingsmanager.h"
#include "distantrenderer.h" #include "distantrenderer.h"
#include "pluginadapter.h"
#include "messagesadapter.h"
#include "namedirectory.h" #include "namedirectory.h"
#include "updatemanager.h" #include "updatemanager.h"
#include "pluginlistpreferencemodel.h" #include "pluginlistpreferencemodel.h"
#include "previewrenderer.h" #include "previewrenderer.h"
#include "settingsadapter.h"
#include "utilsadapter.h"
#include "version.h" #include "version.h"
#include "videoformatfpsmodel.h" #include "videoformatfpsmodel.h"
#include "videoformatresolutionmodel.h" #include "videoformatresolutionmodel.h"
@ -49,116 +43,91 @@
#include <QQmlEngine> #include <QQmlEngine>
// clang-format off // clang-format off
#define QML_REGISTERSINGLETONTYPE_ADAPTER(N, T, MAJ, MIN) \ // TODO: remove this
qmlRegisterSingletonType<T>(N, MAJ, MIN, #T, \ #define QML_REGISTERSINGLETONTYPE_WITH_INSTANCE(T) \
[instance](QQmlEngine* e, QJSEngine* se) -> QObject* { \ qmlRegisterSingletonType<T>(NS_MODELS, VER_MAJ, VER_MIN, #T, \
Q_UNUSED(e); Q_UNUSED(se); \
T* obj = new T(nullptr, instance); return obj; \
});
#define QML_REGISTERSINGLETONTYPE_WITH_INSTANCE(T, MAJ, MIN) \
qmlRegisterSingletonType<T>("net.jami.Models", MAJ, MIN, #T, \
[](QQmlEngine* e, QJSEngine* se) -> QObject* { \ [](QQmlEngine* e, QJSEngine* se) -> QObject* { \
Q_UNUSED(e); Q_UNUSED(se); \ Q_UNUSED(e); Q_UNUSED(se); \
return &(T::instance()); \ return &(T::instance()); \
}); });
#define QML_REGISTERSINGLETONTYPE_CUSTOM(N, T, MAJ, MIN, P) \ #define QML_REGISTERSINGLETONTYPE_URL(NS, URL, T) \
qmlRegisterSingletonType<T>(N, MAJ, MIN, #T, \ qmlRegisterSingletonType(QUrl(QStringLiteral(URL)), NS, VER_MAJ, VER_MIN, #T);
[instance](QQmlEngine* e, QJSEngine* se) -> QObject* { \
Q_UNUSED(e); Q_UNUSED(se); \
return P; \
});
#define QML_REGISTERSINGLETONTYPE_URL(N, URL, T, MAJ, MIN) \ #define QML_REGISTERTYPE(NS, T) qmlRegisterType<T>(NS, VER_MAJ, VER_MIN, #T);
qmlRegisterSingletonType(QUrl(QStringLiteral(URL)), N, MAJ, MIN, #T);
#define QML_REGISTERTYPE(N, T, MAJ, MIN) qmlRegisterType<T>(N, MAJ, MIN, #T); #define QML_REGISTERNAMESPACE(T, NAME) \
qmlRegisterUncreatableMetaObject(T, NS_MODELS, VER_MAJ, VER_MIN, NAME, "")
#define QML_REGISTERNAMESPACE(T, NAME, MAJ, MIN) \ #define QML_REGISTERUNCREATABLE(N, T) \
qmlRegisterUncreatableMetaObject(T, "net.jami.Models", MAJ, MIN, NAME, "") qmlRegisterUncreatableType<T>(N, VER_MAJ, VER_MIN, #T, "Don't try to add to a qml definition of " #T);
#define QML_REGISTERUNCREATABLE(N, T, MAJ, MIN) \ #define QML_REGISTERUNCREATABLE_IN_NAMESPACE(T, NAMESPACE) \
qmlRegisterUncreatableType<T>(N, MAJ, MIN, #T, "Don't try to add to a qml definition of " #T); qmlRegisterUncreatableType<NAMESPACE::T>(NS_MODELS, \
VER_MAJ, VER_MIN, #T, \
#define QML_REGISTERUNCREATABLE_IN_NAMESPACE(T, NAMESPACE, MAJ, MIN) \
qmlRegisterUncreatableType<NAMESPACE::T>("net.jami.Models", \
MAJ, MIN, #T, \
"Don't try to add to a qml definition of " #T); "Don't try to add to a qml definition of " #T);
namespace Utils {
/*! /*!
* This function will expose custom types to the QML engine. * This function will expose custom types to the QML engine.
*/ */
void void
registerTypes(LRCInstance* instance) registerTypes()
{ {
// QAbstractListModels // QAbstractListModels
QML_REGISTERTYPE("net.jami.Models", AccountListModel, 1, 0); QML_REGISTERTYPE(NS_MODELS, AccountListModel);
QML_REGISTERTYPE("net.jami.Models", DeviceItemListModel, 1, 0); QML_REGISTERTYPE(NS_MODELS, DeviceItemListModel);
QML_REGISTERTYPE("net.jami.Models", BannedListModel, 1, 0); QML_REGISTERTYPE(NS_MODELS, BannedListModel);
QML_REGISTERTYPE("net.jami.Models", ModeratorListModel, 1, 0); QML_REGISTERTYPE(NS_MODELS, ModeratorListModel);
QML_REGISTERTYPE("net.jami.Models", MediaCodecListModel, 1, 0); QML_REGISTERTYPE(NS_MODELS, MediaCodecListModel);
QML_REGISTERTYPE("net.jami.Models", AccountsToMigrateListModel, 1, 0); QML_REGISTERTYPE(NS_MODELS, AccountsToMigrateListModel);
QML_REGISTERTYPE("net.jami.Models", AudioDeviceModel, 1, 0); QML_REGISTERTYPE(NS_MODELS, AudioDeviceModel);
QML_REGISTERTYPE("net.jami.Models", AudioManagerListModel, 1, 0); QML_REGISTERTYPE(NS_MODELS, AudioManagerListModel);
QML_REGISTERTYPE("net.jami.Models", VideoInputDeviceModel, 1, 0); QML_REGISTERTYPE(NS_MODELS, VideoInputDeviceModel);
QML_REGISTERTYPE("net.jami.Models", VideoFormatResolutionModel, 1, 0); QML_REGISTERTYPE(NS_MODELS, VideoFormatResolutionModel);
QML_REGISTERTYPE("net.jami.Models", VideoFormatFpsModel, 1, 0); QML_REGISTERTYPE(NS_MODELS, VideoFormatFpsModel);
QML_REGISTERTYPE("net.jami.Models", PluginListPreferenceModel, 1, 0); QML_REGISTERTYPE(NS_MODELS, PluginListPreferenceModel);
QML_REGISTERTYPE("net.jami.Models", SmartListModel, 1, 0); QML_REGISTERTYPE(NS_MODELS, SmartListModel);
// QQuickItems // QQuickItems
QML_REGISTERTYPE("net.jami.Models", PreviewRenderer, 1, 0); QML_REGISTERTYPE(NS_MODELS, PreviewRenderer);
QML_REGISTERTYPE("net.jami.Models", VideoCallPreviewRenderer, 1, 0); QML_REGISTERTYPE(NS_MODELS, VideoCallPreviewRenderer);
QML_REGISTERTYPE("net.jami.Models", DistantRenderer, 1, 0); QML_REGISTERTYPE(NS_MODELS, DistantRenderer);
QML_REGISTERTYPE("net.jami.Models", PhotoboothPreviewRender, 1, 0) QML_REGISTERTYPE(NS_MODELS, PhotoboothPreviewRender)
// Adaptors
QML_REGISTERSINGLETONTYPE_ADAPTER("net.jami.Adapters", CallAdapter, 1, 0);
QML_REGISTERSINGLETONTYPE_ADAPTER("net.jami.Adapters", MessagesAdapter, 1, 0);
QML_REGISTERSINGLETONTYPE_ADAPTER("net.jami.Adapters", ConversationsAdapter, 1, 0);
QML_REGISTERSINGLETONTYPE_ADAPTER("net.jami.Adapters", AvAdapter, 1, 0);
QML_REGISTERSINGLETONTYPE_ADAPTER("net.jami.Adapters", ContactAdapter, 1, 0);
QML_REGISTERSINGLETONTYPE_ADAPTER("net.jami.Adapters", PluginAdapter, 1, 0);
QML_REGISTERSINGLETONTYPE_ADAPTER("net.jami.Adapters", AccountAdapter, 1, 0);
QML_REGISTERSINGLETONTYPE_ADAPTER("net.jami.Adapters", UtilsAdapter, 1, 0);
QML_REGISTERSINGLETONTYPE_ADAPTER("net.jami.Adapters", SettingsAdapter, 1, 0);
QML_REGISTERSINGLETONTYPE_CUSTOM("net.jami.Models", AVModel, 1, 0, &instance->avModel())
QML_REGISTERSINGLETONTYPE_CUSTOM("net.jami.Models", PluginModel, 1, 0, &instance->pluginModel())
QML_REGISTERSINGLETONTYPE_CUSTOM("net.jami.Helpers", UpdateManager, 1, 0, instance->getUpdateManager())
// Qml singleton components // Qml singleton components
QML_REGISTERSINGLETONTYPE_URL("net.jami.Constants", "qrc:/src/constant/JamiTheme.qml", JamiTheme, 1, 0); QML_REGISTERSINGLETONTYPE_URL(NS_CONSTANTS, "qrc:/src/constant/JamiTheme.qml", JamiTheme);
QML_REGISTERSINGLETONTYPE_URL("net.jami.Models", "qrc:/src/constant/JamiQmlUtils.qml", JamiQmlUtils, 1, 0); QML_REGISTERSINGLETONTYPE_URL(NS_MODELS, "qrc:/src/constant/JamiQmlUtils.qml", JamiQmlUtils);
QML_REGISTERSINGLETONTYPE_URL("net.jami.Constants", "qrc:/src/constant/JamiStrings.qml", JamiStrings, 1, 0); QML_REGISTERSINGLETONTYPE_URL(NS_CONSTANTS, "qrc:/src/constant/JamiStrings.qml", JamiStrings);
// C++ singletons // C++ singletons
QML_REGISTERSINGLETONTYPE_WITH_INSTANCE(NameDirectory, 1, 0); // TODO: remove this
QML_REGISTERSINGLETONTYPE_WITH_INSTANCE(NameDirectory);
// Lrc namespaces, models, and singletons // Lrc namespaces, models, and singletons
QML_REGISTERNAMESPACE(lrc::api::staticMetaObject, "Lrc", 1, 0); QML_REGISTERNAMESPACE(lrc::api::staticMetaObject, "Lrc");
QML_REGISTERNAMESPACE(lrc::api::account::staticMetaObject, "Account", 1, 0); QML_REGISTERNAMESPACE(lrc::api::account::staticMetaObject, "Account");
QML_REGISTERNAMESPACE(lrc::api::call::staticMetaObject, "Call", 1, 0); QML_REGISTERNAMESPACE(lrc::api::call::staticMetaObject, "Call");
QML_REGISTERNAMESPACE(lrc::api::datatransfer::staticMetaObject, "Datatransfer", 1, 0); QML_REGISTERNAMESPACE(lrc::api::datatransfer::staticMetaObject, "Datatransfer");
QML_REGISTERNAMESPACE(lrc::api::interaction::staticMetaObject, "Interaction", 1, 0); QML_REGISTERNAMESPACE(lrc::api::interaction::staticMetaObject, "Interaction");
QML_REGISTERNAMESPACE(lrc::api::video::staticMetaObject, "Video", 1, 0); QML_REGISTERNAMESPACE(lrc::api::video::staticMetaObject, "Video");
QML_REGISTERNAMESPACE(lrc::api::profile::staticMetaObject, "Profile", 1, 0); QML_REGISTERNAMESPACE(lrc::api::profile::staticMetaObject, "Profile");
// Same as QML_REGISTERUNCREATABLE but omit the namespace in Qml // Same as QML_REGISTERUNCREATABLE but omit the namespace in Qml
QML_REGISTERUNCREATABLE_IN_NAMESPACE(NewAccountModel, lrc::api, 1, 0); QML_REGISTERUNCREATABLE_IN_NAMESPACE(NewAccountModel, lrc::api);
QML_REGISTERUNCREATABLE_IN_NAMESPACE(BehaviorController, lrc::api, 1, 0); QML_REGISTERUNCREATABLE_IN_NAMESPACE(BehaviorController, lrc::api);
QML_REGISTERUNCREATABLE_IN_NAMESPACE(DataTransferModel, lrc::api, 1, 0); QML_REGISTERUNCREATABLE_IN_NAMESPACE(DataTransferModel, lrc::api);
QML_REGISTERUNCREATABLE_IN_NAMESPACE(ContactModel, lrc::api, 1, 0); QML_REGISTERUNCREATABLE_IN_NAMESPACE(ContactModel, lrc::api);
QML_REGISTERUNCREATABLE_IN_NAMESPACE(ConversationModel, lrc::api, 1, 0); QML_REGISTERUNCREATABLE_IN_NAMESPACE(ConversationModel, lrc::api);
QML_REGISTERUNCREATABLE_IN_NAMESPACE(NewCallModel, lrc::api, 1, 0); QML_REGISTERUNCREATABLE_IN_NAMESPACE(NewCallModel, lrc::api);
QML_REGISTERUNCREATABLE_IN_NAMESPACE(NewDeviceModel, lrc::api, 1, 0); QML_REGISTERUNCREATABLE_IN_NAMESPACE(NewDeviceModel, lrc::api);
QML_REGISTERUNCREATABLE_IN_NAMESPACE(NewCodecModel, lrc::api, 1, 0); QML_REGISTERUNCREATABLE_IN_NAMESPACE(NewCodecModel, lrc::api);
QML_REGISTERUNCREATABLE_IN_NAMESPACE(PeerDiscoveryModel, lrc::api, 1, 0); QML_REGISTERUNCREATABLE_IN_NAMESPACE(PeerDiscoveryModel, lrc::api);
// Enums // Enums
QML_REGISTERUNCREATABLE("net.jami.Enums", Settings, 1, 0); QML_REGISTERUNCREATABLE(NS_ENUMS, Settings);
QML_REGISTERUNCREATABLE("net.jami.Enums", NetWorkManager, 1, 0); QML_REGISTERUNCREATABLE(NS_ENUMS, NetWorkManager);
} }
// clang-format on // clang-format on
} // namespace Utils

View file

@ -18,6 +18,30 @@
#pragma once #pragma once
class LRCInstance; #define NS_MODELS "net.jami.Models"
#define NS_ADAPTERS "net.jami.Adapters"
#define NS_CONSTANTS "net.jami.Constants"
#define NS_HELPERS "net.jami.Helpers"
#define NS_ENUMS "net.jami.Enums"
#define VER_MAJ 1
#define VER_MIN 0
void registerTypes(LRCInstance* instance); // clang-format off
#define QML_REGISTERSINGLETONTYPE_POBJECT(NS, I, N) \
QQmlEngine::setObjectOwnership(I, QQmlEngine::CppOwnership); \
{ using T = std::remove_reference<decltype(*I)>::type; \
qmlRegisterSingletonType<T>(NS, VER_MAJ, VER_MIN, N, \
[I](QQmlEngine*, QJSEngine*) -> QObject* { \
return I; }); }
#define QML_REGISTERSINGLETONTYPE_CUSTOM(NS, T, P) \
qmlRegisterSingletonType<T>(NS, VER_MAJ, VER_MIN, #T, \
[p=P](QQmlEngine* e, QJSEngine* se) -> QObject* { \
Q_UNUSED(e); Q_UNUSED(se); \
return p; \
});
// clang-format on
namespace Utils {
void registerTypes();
}

View file

@ -20,8 +20,11 @@
#include "api/newdevicemodel.h" #include "api/newdevicemodel.h"
SettingsAdapter::SettingsAdapter(LRCInstance* instance, QObject* parent) SettingsAdapter::SettingsAdapter(AppSettingsManager* settingsManager,
LRCInstance* instance,
QObject* parent)
: QmlAdapterBase(instance, parent) : QmlAdapterBase(instance, parent)
, settingsManager_(settingsManager)
{} {}
QString QString
@ -54,13 +57,13 @@ SettingsAdapter::getDir_Download()
QVariant QVariant
SettingsAdapter::getAppValue(const Settings::Key key) SettingsAdapter::getAppValue(const Settings::Key key)
{ {
return AppSettingsManager::getValue(key); return settingsManager_->getValue(key);
} }
void void
SettingsAdapter::setAppValue(const Settings::Key key, const QVariant& value) SettingsAdapter::setAppValue(const Settings::Key key, const QVariant& value)
{ {
AppSettingsManager::setValue(key, value); settingsManager_->setValue(key, value);
} }
void void

View file

@ -19,7 +19,6 @@
#pragma once #pragma once
#include <QObject> #include <QObject>
#include <QSettings>
#include "api/account.h" #include "api/account.h"
#include "api/datatransfermodel.h" #include "api/datatransfermodel.h"
@ -27,12 +26,15 @@
#include "typedefs.h" #include "typedefs.h"
#include "utils.h" #include "utils.h"
#include "qmladapterbase.h" #include "qmladapterbase.h"
#include "appsettingsmanager.h"
class SettingsAdapter : public QmlAdapterBase class SettingsAdapter : public QmlAdapterBase
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit SettingsAdapter(LRCInstance* instance, QObject* parent = nullptr); explicit SettingsAdapter(AppSettingsManager* settingsManager,
LRCInstance* instance,
QObject* parent = nullptr);
void safeInit() override {} void safeInit() override {}
@ -225,5 +227,8 @@ public:
Q_INVOKABLE void enableLocalModerators(const QString& accountID, const bool& isModEnabled); Q_INVOKABLE void enableLocalModerators(const QString& accountID, const bool& isModEnabled);
Q_INVOKABLE bool isLocalModeratorsEnabled(const QString& accountId); Q_INVOKABLE bool isLocalModeratorsEnabled(const QString& accountId);
Q_INVOKABLE bool isAllModeratorsEnabled(const QString& accountId); Q_INVOKABLE bool isAllModeratorsEnabled(const QString& accountId);
private:
AppSettingsManager* settingsManager_;
}; };
Q_DECLARE_METATYPE(SettingsAdapter*) Q_DECLARE_METATYPE(SettingsAdapter*)

57
src/systemtray.cpp Normal file
View file

@ -0,0 +1,57 @@
/*
* Copyright (C) 2021 by Savoir-faire Linux
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
*
* 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 "systemtray.h"
#include "appsettingsmanager.h"
SystemTray::SystemTray(AppSettingsManager* settingsManager, QObject* parent)
: QSystemTrayIcon(parent)
, settingsManager_(settingsManager)
{}
SystemTray::~SystemTray()
{
hide();
}
void
SystemTray::showNotification(const QString& message,
const QString& from,
std::function<void()> const& onClickedCb)
{
if (!settingsManager_->getValue(Settings::Key::EnableNotifications).toBool()) {
qWarning() << "Notifications are disabled";
return;
}
setOnClickedCallback(std::move(onClickedCb));
if (from.isEmpty())
showMessage(message, "", QIcon(":images/jami.png"));
else
showMessage(from, message, QIcon(":images/jami.png"));
}
template<typename Func>
void
SystemTray::setOnClickedCallback(Func&& onClicked)
{
disconnect(messageClicked_);
messageClicked_ = connect(this, &QSystemTrayIcon::messageClicked, onClicked);
}

View file

@ -1,6 +1,6 @@
/* /*
* Copyright (C) 2015-2020 by Savoir-faire Linux * Copyright (C) 2021 by Savoir-faire Linux
* Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com> * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -18,33 +18,26 @@
#pragma once #pragma once
#include "lrcinstance.h"
#include <QSystemTrayIcon> #include <QSystemTrayIcon>
class GlobalSystemTray final : public QSystemTrayIcon class AppSettingsManager;
class SystemTray final : public QSystemTrayIcon
{ {
Q_OBJECT Q_OBJECT
public: public:
~GlobalSystemTray() = default; explicit SystemTray(AppSettingsManager* settingsManager, QObject* parent = nullptr);
static GlobalSystemTray& instance() ~SystemTray();
{
static GlobalSystemTray* instance_ = new GlobalSystemTray(); void showNotification(const QString& message,
return *instance_; const QString& from,
} std::function<void()> const& onClickedCb);
template<typename Func> template<typename Func>
static void connectClicked(Func&& onClicked) void setOnClickedCallback(Func&& onClickedCb);
{
auto& instance_ = instance();
instance_.disconnect(instance_.messageClicked_);
instance_.connect(&instance_, &QSystemTrayIcon::messageClicked, onClicked);
}
private: private:
explicit GlobalSystemTray()
: QSystemTrayIcon() {};
QMetaObject::Connection messageClicked_; QMetaObject::Connection messageClicked_;
AppSettingsManager* settingsManager_;
}; };

View file

@ -22,7 +22,6 @@
#include "utils.h" #include "utils.h"
#include "globalsystemtray.h"
#include "jamiavatartheme.h" #include "jamiavatartheme.h"
#include "lrcinstance.h" #include "lrcinstance.h"
@ -395,31 +394,6 @@ Utils::getCirclePhoto(const QImage original, int sizePhoto)
return target; return target;
} }
void
Utils::showNotification(const QString& message,
const QString& from,
const QString& accountId,
const QString& convUid,
std::function<void()> const& onClicked)
{
if (accountId.isEmpty() || convUid.isEmpty()) {
// This should never happen.
qFatal("Invalid account or conversation.");
}
if (!AppSettingsManager::getValue(Settings::Key::EnableNotifications).toBool()) {
qWarning() << "Notifications are disabled";
return;
}
GlobalSystemTray::connectClicked(std::move(onClicked));
if (from.isEmpty())
GlobalSystemTray::instance().showMessage(message, "", QIcon(":images/jami.png"));
else
GlobalSystemTray::instance().showMessage(from, message, QIcon(":images/jami.png"));
}
QSize QSize
Utils::getRealSize(QScreen* screen) Utils::getRealSize(QScreen* screen)
{ {

View file

@ -66,11 +66,6 @@ const char* WinGetEnv(const char* name);
QString GetRingtonePath(); QString GetRingtonePath();
QString GenGUID(); QString GenGUID();
QString GetISODate(); QString GetISODate();
void showNotification(const QString& message,
const QString& from,
const QString& accountId,
const QString& convUid,
std::function<void()> const& onClicked);
QSize getRealSize(QScreen* screen); QSize getRealSize(QScreen* screen);
void forceDeleteAsync(const QString& path); void forceDeleteAsync(const QString& path);
QString getProjectCredits(); QString getProjectCredits();

View file

@ -22,8 +22,8 @@
#include "utilsadapter.h" #include "utilsadapter.h"
#include "globalsystemtray.h"
#include "lrcinstance.h" #include "lrcinstance.h"
#include "systemtray.h"
#include "utils.h" #include "utils.h"
#include "version.h" #include "version.h"
@ -31,9 +31,10 @@
#include <QClipboard> #include <QClipboard>
#include <QFileInfo> #include <QFileInfo>
UtilsAdapter::UtilsAdapter(LRCInstance* instance, QObject* parent) UtilsAdapter::UtilsAdapter(SystemTray* systemTray, LRCInstance* instance, QObject* parent)
: QmlAdapterBase(instance, parent) : QmlAdapterBase(instance, parent)
, clipboard_(QApplication::clipboard()) , clipboard_(QApplication::clipboard())
, systemTray_(systemTray)
{} {}
const QString const QString
@ -360,5 +361,5 @@ UtilsAdapter::humanFileSize(qint64 fileSize)
void void
UtilsAdapter::setSystemTrayIconVisible(bool visible) UtilsAdapter::setSystemTrayIconVisible(bool visible)
{ {
GlobalSystemTray::instance().setVisible(visible); systemTray_->setVisible(visible);
} }

View file

@ -28,12 +28,13 @@
#include "qmladapterbase.h" #include "qmladapterbase.h"
class QClipboard; class QClipboard;
class SystemTray;
class UtilsAdapter final : public QmlAdapterBase class UtilsAdapter final : public QmlAdapterBase
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit UtilsAdapter(LRCInstance* instance, QObject* parent = nullptr); explicit UtilsAdapter(SystemTray* systemTray, LRCInstance* instance, QObject* parent = nullptr);
~UtilsAdapter() = default; ~UtilsAdapter() = default;
void safeInit() override {} void safeInit() override {}
@ -81,5 +82,6 @@ public:
private: private:
QClipboard* clipboard_; QClipboard* clipboard_;
SystemTray* systemTray_;
}; };
Q_DECLARE_METATYPE(UtilsAdapter*) Q_DECLARE_METATYPE(UtilsAdapter*)