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>
|
2026-04-30 14:53:03 +08:00
|
|
|
#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"), [&](){
|
2025-08-01 07:50:31 +04:00
|
|
|
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,
|
2025-08-10 06:12:19 +03:00
|
|
|
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)
|
|
|
|
|
{
|
2025-08-01 07:50:31 +04:00
|
|
|
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();
|
|
|
|
|
if (isDarkTheme == m_isDarkTheme) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_isDarkTheme = isDarkTheme;
|
2026-05-29 17:01:08 +03:00
|
|
|
updateTrayIcon();
|
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;
|
|
|
|
|
visual.connectionState = m_trayState;
|
|
|
|
|
visual.darkTheme = m_isDarkTheme;
|
|
|
|
|
return visual;
|
2026-05-29 17:01:08 +03:00
|
|
|
}
|
|
|
|
|
|
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-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
|
|
|
}
|