add new icon

This commit is contained in:
dranik
2026-05-29 15:58:07 +03:00
parent bd0747296e
commit a40bd0d580
5 changed files with 93 additions and 41 deletions
+1
View File
@@ -68,6 +68,7 @@
<file>tray/active.png</file> <file>tray/active.png</file>
<file>tray/default.png</file> <file>tray/default.png</file>
<file>tray/error.png</file> <file>tray/error.png</file>
<file>tray/icon.svg</file>
<file>controls/monitor.svg</file> <file>controls/monitor.svg</file>
</qresource> </qresource>
</RCC> </RCC>
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.4 KiB

+8
View File
@@ -15,6 +15,10 @@
#include "platforms/ios/QtAppDelegate-C-Interface.h" #include "platforms/ios/QtAppDelegate-C-Interface.h"
#endif #endif
#if defined(Q_OS_MAC) && !defined(MACOS_NE)
#include "platforms/macos/macosutils.h"
#endif
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(MACOS_NE) #if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(MACOS_NE)
bool isAnotherInstanceRunning() bool isAnotherInstanceRunning()
{ {
@@ -46,6 +50,10 @@ int main(int argc, char *argv[])
AmneziaApplication app(argc, argv); AmneziaApplication app(argc, argv);
OsSignalHandler::setup(); OsSignalHandler::setup();
#if defined(Q_OS_MAC) && !defined(MACOS_NE)
MacOSUtils::patchNSStatusBarSetImageForBigSur();
#endif
ssh_init(); ssh_init();
QObject::connect(&app, &QCoreApplication::aboutToQuit, []() { QObject::connect(&app, &QCoreApplication::aboutToQuit, []() {
ssh_finalize(); ssh_finalize();
@@ -5,18 +5,51 @@
#include <QDebug> #include <QDebug>
#include "systemTrayNotificationHandler.h" #include "systemTrayNotificationHandler.h"
#ifdef Q_OS_MAC
# include "platforms/macos/macosutils.h"
#endif
#include <QApplication> #include <QApplication>
#include <QDesktopServices> #include <QDesktopServices>
#include <QGuiApplication>
#include <QIcon> #include <QIcon>
#include <QPainter>
#include <QStyleHints>
#include <QSvgRenderer>
#include <QWindow> #include <QWindow>
#include "version.h" #include "version.h"
namespace {
constexpr int kTrayIconSize = 128;
constexpr char kTrayTemplateIconPath[] = ":/images/tray/icon.svg";
QPixmap renderTrayTemplate(const QString &resourcePath, qreal opacity)
{
QSvgRenderer renderer(resourcePath);
QPixmap pixmap(kTrayIconSize, kTrayIconSize);
pixmap.fill(Qt::transparent);
if (!renderer.isValid()) {
qWarning() << "Failed to load tray icon template:" << resourcePath;
return pixmap;
}
QPainter painter(&pixmap);
painter.setOpacity(opacity);
renderer.render(&painter, QRectF(0, 0, kTrayIconSize, kTrayIconSize));
return pixmap;
}
QIcon buildTrayIcon(qreal opacity)
{
const QPixmap pixmap = renderTrayTemplate(QString::fromLatin1(kTrayTemplateIconPath), opacity);
QIcon icon;
icon.addPixmap(pixmap);
icon.setIsMask(true);
return icon;
}
} // namespace
SystemTrayNotificationHandler::SystemTrayNotificationHandler(QObject* parent) : SystemTrayNotificationHandler::SystemTrayNotificationHandler(QObject* parent) :
NotificationHandler(parent), NotificationHandler(parent),
m_systemTrayIcon(parent) m_systemTrayIcon(parent)
@@ -25,7 +58,7 @@ SystemTrayNotificationHandler::SystemTrayNotificationHandler(QObject* parent) :
m_systemTrayIcon.show(); m_systemTrayIcon.show();
connect(&m_systemTrayIcon, &QSystemTrayIcon::activated, this, &SystemTrayNotificationHandler::onTrayActivated); connect(&m_systemTrayIcon, &QSystemTrayIcon::activated, this, &SystemTrayNotificationHandler::onTrayActivated);
m_trayActionShow = m_menu.addAction(QIcon(":/images/tray/application.png"), tr("Show") + " " + APPLICATION_NAME, this, [this](){ m_trayActionShow = m_menu.addAction(tr("Show") + " " + APPLICATION_NAME, this, [this](){
emit raiseRequested(); emit raiseRequested();
}); });
m_menu.addSeparator(); m_menu.addSeparator();
@@ -34,17 +67,22 @@ SystemTrayNotificationHandler::SystemTrayNotificationHandler(QObject* parent) :
m_menu.addSeparator(); m_menu.addSeparator();
m_trayActionVisitWebSite = m_menu.addAction(QIcon(":/images/tray/link.png"), tr("Visit Website"), [&](){ m_trayActionVisitWebSite = m_menu.addAction(tr("Visit Website"), [&](){
QDesktopServices::openUrl(QUrl(websiteUrl)); QDesktopServices::openUrl(QUrl(websiteUrl));
}); });
// Quit action: disconnect VPN first on macOS NE, else quit directly m_trayActionQuit = m_menu.addAction(tr("Quit") + " " + APPLICATION_NAME,
m_trayActionQuit = m_menu.addAction(QIcon(":/images/tray/cancel.png"),
tr("Quit") + " " + APPLICATION_NAME,
this, this,
[&](){ qApp->quit(); }); [&](){ qApp->quit(); });
m_systemTrayIcon.setContextMenu(&m_menu); m_systemTrayIcon.setContextMenu(&m_menu);
if (QStyleHints *styleHints = QGuiApplication::styleHints()) {
connect(styleHints, &QStyleHints::colorSchemeChanged, this, [this]() {
updateTrayIcon();
});
}
setTrayState(Vpn::ConnectionState::Disconnected); setTrayState(Vpn::ConnectionState::Disconnected);
} }
@@ -71,13 +109,27 @@ void SystemTrayNotificationHandler::updateWebsiteUrl(const QString &newWebsiteUr
websiteUrl = newWebsiteUrl; websiteUrl = newWebsiteUrl;
} }
void SystemTrayNotificationHandler::setTrayIcon(const QString &iconPath) qreal SystemTrayNotificationHandler::trayIconOpacityForState(Vpn::ConnectionState state) const
{ {
QIcon trayIconMask(QPixmap(iconPath).scaled(128,128)); switch (state) {
#ifndef Q_OS_MAC case Vpn::ConnectionState::Connected:
trayIconMask.setIsMask(true); case Vpn::ConnectionState::Error:
#endif return kConnectedTrayOpacity;
m_systemTrayIcon.setIcon(trayIconMask); case Vpn::ConnectionState::Disconnected:
case Vpn::ConnectionState::Preparing:
case Vpn::ConnectionState::Connecting:
case Vpn::ConnectionState::Disconnecting:
case Vpn::ConnectionState::Reconnecting:
case Vpn::ConnectionState::Unknown:
default:
return kDisconnectedTrayOpacity;
}
}
void SystemTrayNotificationHandler::updateTrayIcon()
{
const qreal opacity = trayIconOpacityForState(m_trayState);
m_systemTrayIcon.setIcon(buildTrayIcon(opacity));
} }
void SystemTrayNotificationHandler::onTrayActivated(QSystemTrayIcon::ActivationReason reason) void SystemTrayNotificationHandler::onTrayActivated(QSystemTrayIcon::ActivationReason reason)
@@ -91,41 +143,34 @@ void SystemTrayNotificationHandler::onTrayActivated(QSystemTrayIcon::ActivationR
void SystemTrayNotificationHandler::setTrayState(Vpn::ConnectionState state) void SystemTrayNotificationHandler::setTrayState(Vpn::ConnectionState state)
{ {
QString resourcesPath = ":/images/tray/%1"; m_trayState = state;
switch (state) { switch (state) {
case Vpn::ConnectionState::Disconnected: case Vpn::ConnectionState::Disconnected:
setTrayIcon(QString(resourcesPath).arg(DisconnectedTrayIconName));
m_trayActionConnect->setEnabled(true); m_trayActionConnect->setEnabled(true);
m_trayActionDisconnect->setEnabled(false); m_trayActionDisconnect->setEnabled(false);
break; break;
case Vpn::ConnectionState::Preparing: case Vpn::ConnectionState::Preparing:
setTrayIcon(QString(resourcesPath).arg(DisconnectedTrayIconName));
m_trayActionConnect->setEnabled(false); m_trayActionConnect->setEnabled(false);
m_trayActionDisconnect->setEnabled(true); m_trayActionDisconnect->setEnabled(true);
break; break;
case Vpn::ConnectionState::Connecting: case Vpn::ConnectionState::Connecting:
setTrayIcon(QString(resourcesPath).arg(DisconnectedTrayIconName));
m_trayActionConnect->setEnabled(false); m_trayActionConnect->setEnabled(false);
m_trayActionDisconnect->setEnabled(true); m_trayActionDisconnect->setEnabled(true);
break; break;
case Vpn::ConnectionState::Connected: case Vpn::ConnectionState::Connected:
setTrayIcon(QString(resourcesPath).arg(ConnectedTrayIconName));
m_trayActionConnect->setEnabled(false); m_trayActionConnect->setEnabled(false);
m_trayActionDisconnect->setEnabled(true); m_trayActionDisconnect->setEnabled(true);
break; break;
case Vpn::ConnectionState::Disconnecting: case Vpn::ConnectionState::Disconnecting:
setTrayIcon(QString(resourcesPath).arg(DisconnectedTrayIconName));
m_trayActionConnect->setEnabled(false); m_trayActionConnect->setEnabled(false);
m_trayActionDisconnect->setEnabled(true); m_trayActionDisconnect->setEnabled(true);
break; break;
case Vpn::ConnectionState::Reconnecting: case Vpn::ConnectionState::Reconnecting:
setTrayIcon(QString(resourcesPath).arg(DisconnectedTrayIconName));
m_trayActionConnect->setEnabled(false); m_trayActionConnect->setEnabled(false);
m_trayActionDisconnect->setEnabled(true); m_trayActionDisconnect->setEnabled(true);
break; break;
case Vpn::ConnectionState::Error: case Vpn::ConnectionState::Error:
setTrayIcon(QString(resourcesPath).arg(ErrorTrayIconName));
m_trayActionConnect->setEnabled(true); m_trayActionConnect->setEnabled(true);
m_trayActionDisconnect->setEnabled(false); m_trayActionDisconnect->setEnabled(false);
break; break;
@@ -133,16 +178,10 @@ void SystemTrayNotificationHandler::setTrayState(Vpn::ConnectionState state)
default: default:
m_trayActionConnect->setEnabled(false); m_trayActionConnect->setEnabled(false);
m_trayActionDisconnect->setEnabled(true); m_trayActionDisconnect->setEnabled(true);
setTrayIcon(QString(resourcesPath).arg(DisconnectedTrayIconName)); break;
} }
//#ifdef Q_OS_MAC updateTrayIcon();
// // Get theme from current user (note, this app can be launched as root application and in this case this theme can be different from theme of real current user )
// bool darkTaskBar = MacOSFunctions::instance().isMenuBarUseDarkTheme();
// darkTaskBar = forceUseBrightIcons ? true : darkTaskBar;
// resourcesPath = ":/images_mac/tray_icon/%1";
// useIconName = useIconName.replace(".png", darkTaskBar ? "@2x.png" : " dark@2x.png");
//#endif
} }
@@ -152,8 +191,7 @@ void SystemTrayNotificationHandler::notify(NotificationHandler::Message type,
int timerMsec) { int timerMsec) {
Q_UNUSED(type); Q_UNUSED(type);
QIcon icon(ConnectedTrayIconName); m_systemTrayIcon.showMessage(title, message, buildTrayIcon(kConnectedTrayOpacity), timerMsec);
m_systemTrayIcon.showMessage(title, message, icon, timerMsec);
} }
void SystemTrayNotificationHandler::showHideWindow() { void SystemTrayNotificationHandler::showHideWindow() {
@@ -170,4 +208,3 @@ void SystemTrayNotificationHandler::showHideWindow() {
//#endif //#endif
// } // }
} }
@@ -34,7 +34,8 @@ private:
void setTrayState(Vpn::ConnectionState state); void setTrayState(Vpn::ConnectionState state);
void onTrayActivated(QSystemTrayIcon::ActivationReason reason); void onTrayActivated(QSystemTrayIcon::ActivationReason reason);
void setTrayIcon(const QString &iconPath); void updateTrayIcon();
qreal trayIconOpacityForState(Vpn::ConnectionState state) const;
private: private:
QMenu m_menu; QMenu m_menu;
@@ -45,13 +46,15 @@ private:
QAction* m_trayActionDisconnect = nullptr; QAction* m_trayActionDisconnect = nullptr;
QAction* m_trayActionVisitWebSite = nullptr; QAction* m_trayActionVisitWebSite = nullptr;
QAction* m_trayActionQuit = nullptr; QAction* m_trayActionQuit = nullptr;
QAction* m_statusLabel = nullptr; QAction* m_statusLabel = nullptr;
QAction* m_separator = nullptr; QAction* m_separator = nullptr;
const QString ConnectedTrayIconName = "active.png"; Vpn::ConnectionState m_trayState = Vpn::ConnectionState::Unknown;
const QString DisconnectedTrayIconName = "default.png";
const QString ErrorTrayIconName = "error.png"; static constexpr qreal kDisconnectedTrayOpacity = 0.5;
QString websiteUrl = "https://amnezia.org"; static constexpr qreal kConnectedTrayOpacity = 1.0;
QString websiteUrl = "https://amnezia.org";
}; };
#endif // SYSTEMTRAYNOTIFICATIONHANDLER_H #endif // SYSTEMTRAYNOTIFICATIONHANDLER_H