Files
amnezia-client/client/ui/utils/systemTrayNotificationHandler.cpp
T

209 lines
6.4 KiB
C++
Raw Normal View History

2021-11-26 17:43:02 +03:00
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <QDebug>
#include "systemTrayNotificationHandler.h"
2021-11-26 17:43:02 +03:00
2026-05-29 17:01:08 +03:00
#include "platformTheme.h"
2026-05-30 10:53:44 +03:00
#include "platformTrayTheme.h"
#include "trayIconBackend.h"
2026-05-29 17:01:08 +03:00
2021-11-28 17:28:25 +03:00
#include <QApplication>
#include <QDesktopServices>
2026-05-29 22:22:53 +03:00
2023-05-16 07:34:06 +07:00
#include "version.h"
2021-11-26 17:43:02 +03:00
2021-11-28 17:28:25 +03:00
SystemTrayNotificationHandler::SystemTrayNotificationHandler(QObject* parent) :
2026-05-29 17:01:08 +03:00
NotificationHandler(parent)
2021-11-28 17:28:25 +03:00
{
2026-05-30 10:53:44 +03:00
m_trayIcon = createTrayIconBackend(this);
m_trayIcon->setMenu(&m_menu);
m_trayIcon->setToolTip(APPLICATION_NAME);
m_trayIcon->setActivatedHandler([this](QSystemTrayIcon::ActivationReason reason) {
onTrayActivated(reason);
});
2021-11-26 17:43:02 +03:00
2026-05-29 15:58:07 +03:00
m_trayActionShow = m_menu.addAction(tr("Show") + " " + APPLICATION_NAME, this, [this](){
2021-11-28 17:28:25 +03:00
emit raiseRequested();
});
m_menu.addSeparator();
m_trayActionConnect = m_menu.addAction(tr("Connect"), this, [this](){ emit connectRequested(); });
m_trayActionDisconnect = m_menu.addAction(tr("Disconnect"), this, [this](){ emit disconnectRequested(); });
2021-11-26 17:43:02 +03:00
2021-11-28 17:28:25 +03:00
m_menu.addSeparator();
2021-11-26 17:43:02 +03:00
2026-05-29 15:58:07 +03:00
m_trayActionVisitWebSite = m_menu.addAction(tr("Visit Website"), [&](){
QDesktopServices::openUrl(QUrl(websiteUrl));
2021-11-28 17:28:25 +03:00
});
2021-11-26 17:43:02 +03:00
2026-05-29 15:58:07 +03:00
m_trayActionQuit = m_menu.addAction(tr("Quit") + " " + APPLICATION_NAME,
this,
[&](){ qApp->quit(); });
2021-11-26 17:43:02 +03:00
2026-05-30 10:53:44 +03:00
installTrayThemeObserver([this]() { refreshTheme(); }, this);
2026-05-29 17:01:08 +03:00
2026-05-29 22:22:53 +03:00
m_isDarkTheme = platformIsDarkTheme();
2023-05-14 21:11:19 +08:00
setTrayState(Vpn::ConnectionState::Disconnected);
2026-05-30 10:53:44 +03:00
m_trayIcon->show();
2021-11-26 17:43:02 +03:00
}
2026-05-30 10:53:44 +03:00
SystemTrayNotificationHandler::~SystemTrayNotificationHandler() = default;
2021-11-26 17:43:02 +03:00
2023-05-14 21:11:19 +08:00
void SystemTrayNotificationHandler::setConnectionState(Vpn::ConnectionState state)
2021-11-28 17:28:25 +03:00
{
setTrayState(state);
NotificationHandler::setConnectionState(state);
}
2023-10-06 13:43:32 +08:00
void SystemTrayNotificationHandler::onTranslationsUpdated()
{
m_trayActionShow->setText(tr("Show") + " " + APPLICATION_NAME);
m_trayActionConnect->setText(tr("Connect"));
m_trayActionDisconnect->setText(tr("Disconnect"));
m_trayActionVisitWebSite->setText(tr("Visit Website"));
2026-05-30 10:53:44 +03:00
m_trayActionQuit->setText(tr("Quit") + " " + APPLICATION_NAME);
2026-05-29 17:01:08 +03:00
2026-05-30 10:53:44 +03:00
if (m_trayIcon) {
m_trayIcon->rebuildMenu();
2026-05-29 17:01:08 +03:00
}
2023-10-06 13:43:32 +08:00
}
2026-05-30 10:53:44 +03:00
void SystemTrayNotificationHandler::updateWebsiteUrl(const QString &newWebsiteUrl)
{
qDebug() << "Updated website URL:" << newWebsiteUrl;
websiteUrl = newWebsiteUrl;
}
2026-05-29 17:01:08 +03:00
void SystemTrayNotificationHandler::refreshTheme()
{
2026-05-29 22:22:53 +03:00
const bool isDarkTheme = platformIsDarkTheme();
2026-05-30 12:55:27 +03:00
const bool themeChanged = (isDarkTheme != m_isDarkTheme);
2026-05-29 22:22:53 +03:00
m_isDarkTheme = isDarkTheme;
2026-05-30 12:55:27 +03:00
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
2026-05-29 17:01:08 +03:00
updateTrayIcon();
2026-05-30 12:55:27 +03:00
#else
if (themeChanged) {
updateTrayIcon();
}
#endif
2026-05-29 15:58:07 +03:00
}
2026-05-30 10:53:44 +03:00
TrayIconVisual SystemTrayNotificationHandler::currentTrayVisual() const
2026-05-29 17:01:08 +03:00
{
2026-05-30 10:53:44 +03:00
TrayIconVisual visual;
2026-06-05 16:13:06 +03:00
visual.connectionState = m_errorLatched ? Vpn::ConnectionState::Error : m_trayState;
2026-05-30 10:53:44 +03:00
visual.darkTheme = m_isDarkTheme;
return visual;
2026-05-29 17:01:08 +03:00
}
2026-06-05 16:13:06 +03:00
void SystemTrayNotificationHandler::setConnectionError()
{
m_errorLatched = true;
updateTrayIcon();
}
void SystemTrayNotificationHandler::clearConnectionError()
{
if (!m_errorLatched) {
return;
}
m_errorLatched = false;
updateTrayIcon();
}
2026-05-29 15:58:07 +03:00
void SystemTrayNotificationHandler::updateTrayIcon()
{
2026-05-30 10:53:44 +03:00
if (!m_trayIcon) {
return;
}
2026-05-29 17:01:08 +03:00
2026-05-30 10:53:44 +03:00
m_trayIcon->applyVisual(currentTrayVisual());
2021-11-28 17:28:25 +03:00
}
void SystemTrayNotificationHandler::onTrayActivated(QSystemTrayIcon::ActivationReason reason)
{
#ifndef Q_OS_MAC
if(reason == QSystemTrayIcon::DoubleClick || reason == QSystemTrayIcon::Trigger) {
emit raiseRequested();
}
#endif
}
2023-05-14 21:11:19 +08:00
void SystemTrayNotificationHandler::setTrayState(Vpn::ConnectionState state)
2021-11-28 17:28:25 +03:00
{
2026-06-05 16:13:06 +03:00
if (state == Vpn::ConnectionState::Error || state == Vpn::ConnectionState::Unknown) {
// Latch the error icon. Both Error and Unknown surface the error message
// in the UI. The connection is torn down to Disconnected right after, so
// treat the real state as Disconnected and let the latch keep the error
// icon visible until the error is acknowledged.
m_errorLatched = true;
state = Vpn::ConnectionState::Disconnected;
} else if (state != Vpn::ConnectionState::Disconnected) {
// A new (re)connecting/connected lifecycle clears a previous error.
// Plain Disconnected leaves the latch untouched so the auto-Disconnected
// that immediately follows an error does not drop the error icon.
m_errorLatched = false;
}
2026-05-29 15:58:07 +03:00
m_trayState = state;
2021-11-28 17:28:25 +03:00
switch (state) {
2023-05-14 21:11:19 +08:00
case Vpn::ConnectionState::Disconnected:
2021-11-28 17:28:25 +03:00
m_trayActionConnect->setEnabled(true);
m_trayActionDisconnect->setEnabled(false);
break;
2023-05-14 21:11:19 +08:00
case Vpn::ConnectionState::Preparing:
2021-11-28 17:28:25 +03:00
m_trayActionConnect->setEnabled(false);
m_trayActionDisconnect->setEnabled(true);
break;
2023-05-14 21:11:19 +08:00
case Vpn::ConnectionState::Connecting:
2021-11-28 17:28:25 +03:00
m_trayActionConnect->setEnabled(false);
m_trayActionDisconnect->setEnabled(true);
break;
2023-05-14 21:11:19 +08:00
case Vpn::ConnectionState::Connected:
2021-11-28 17:28:25 +03:00
m_trayActionConnect->setEnabled(false);
m_trayActionDisconnect->setEnabled(true);
break;
2023-05-14 21:11:19 +08:00
case Vpn::ConnectionState::Disconnecting:
2021-11-28 17:28:25 +03:00
m_trayActionConnect->setEnabled(false);
m_trayActionDisconnect->setEnabled(true);
break;
2023-05-14 21:11:19 +08:00
case Vpn::ConnectionState::Reconnecting:
2021-11-28 17:28:25 +03:00
m_trayActionConnect->setEnabled(false);
m_trayActionDisconnect->setEnabled(true);
break;
2023-05-14 21:11:19 +08:00
case Vpn::ConnectionState::Error:
2021-11-28 17:28:25 +03:00
m_trayActionConnect->setEnabled(true);
m_trayActionDisconnect->setEnabled(false);
break;
2023-05-14 21:11:19 +08:00
case Vpn::ConnectionState::Unknown:
2021-11-28 17:28:25 +03:00
default:
m_trayActionConnect->setEnabled(false);
m_trayActionDisconnect->setEnabled(true);
2026-05-29 15:58:07 +03:00
break;
2021-11-28 17:28:25 +03:00
}
2026-05-29 15:58:07 +03:00
updateTrayIcon();
2021-11-28 17:28:25 +03:00
2026-05-30 10:53:44 +03:00
if (m_trayIcon) {
m_trayIcon->rebuildMenu();
2026-05-29 17:01:08 +03:00
}
2026-05-29 22:22:53 +03:00
}
2021-11-28 17:28:25 +03:00
2021-11-26 17:43:02 +03:00
void SystemTrayNotificationHandler::notify(NotificationHandler::Message type,
const QString& title,
const QString& message,
2026-05-30 10:53:44 +03:00
int timerMsec)
{
Q_UNUSED(type);
2021-11-26 17:43:02 +03:00
2026-05-30 10:53:44 +03:00
if (!m_trayIcon) {
return;
}
2021-11-26 17:43:02 +03:00
2026-05-30 10:53:44 +03:00
m_trayIcon->showMessage(title, message, currentTrayVisual(), timerMsec);
2021-11-26 17:43:02 +03:00
}