update icons
@@ -65,10 +65,11 @@
|
||||
<file>controls/text-cursor.svg</file>
|
||||
<file>controls/trash.svg</file>
|
||||
<file>controls/x-circle.svg</file>
|
||||
<file>tray/active.png</file>
|
||||
<file>tray/default.png</file>
|
||||
<file>tray/error.png</file>
|
||||
<file>tray/icon.svg</file>
|
||||
<file>tray/off-black.svg</file>
|
||||
<file>tray/off-light.svg</file>
|
||||
<file>tray/on-black.svg</file>
|
||||
<file>tray/on-white.svg</file>
|
||||
<file>tray/error.svg</file>
|
||||
<file>controls/monitor.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 7.4 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 7.6 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
@@ -32,9 +32,7 @@ void LinuxTrayIconBackend::show()
|
||||
|
||||
void LinuxTrayIconBackend::applyVisual(const TrayIconVisual &visual)
|
||||
{
|
||||
const qreal opacity = TrayIconCommon::opacityForState(visual.connectionState);
|
||||
const QColor indicatorColor = TrayIconCommon::indicatorColorForState(visual.connectionState);
|
||||
const QIcon icon = buildTrayIcon(opacity, visual.darkTheme, indicatorColor);
|
||||
const QIcon icon = buildTrayIcon(visual.connectionState, visual.darkTheme);
|
||||
|
||||
// Some tray implementations cache the first icon; clear before applying an update.
|
||||
if (m_trayIcon.isVisible()) {
|
||||
@@ -47,8 +45,7 @@ void LinuxTrayIconBackend::showMessage(const QString &title, const QString &mess
|
||||
int timerMsec)
|
||||
{
|
||||
m_trayIcon.showMessage(title, message,
|
||||
buildTrayIcon(TrayIconCommon::kConnectedOpacity, visual.darkTheme,
|
||||
TrayIconCommon::indicatorColorForState(Vpn::ConnectionState::Connected)),
|
||||
buildTrayIcon(Vpn::ConnectionState::Connected, visual.darkTheme),
|
||||
timerMsec);
|
||||
}
|
||||
|
||||
@@ -66,11 +63,11 @@ void LinuxTrayIconBackend::setActivatedHandler(std::function<void(QSystemTrayIco
|
||||
[handler](QSystemTrayIcon::ActivationReason reason) { handler(reason); });
|
||||
}
|
||||
|
||||
QIcon LinuxTrayIconBackend::buildTrayIcon(qreal opacity, bool darkTheme, const QColor &indicatorColor) const
|
||||
QIcon LinuxTrayIconBackend::buildTrayIcon(Vpn::ConnectionState state, bool darkTheme) const
|
||||
{
|
||||
QIcon icon;
|
||||
for (int size : kLinuxTrayIconSizes) {
|
||||
icon.addPixmap(TrayIconCommon::buildPixmap(size, opacity, darkTheme, indicatorColor));
|
||||
icon.addPixmap(TrayIconCommon::buildPixmap(size, state, darkTheme));
|
||||
}
|
||||
return icon;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ public:
|
||||
void setActivatedHandler(std::function<void(QSystemTrayIcon::ActivationReason)> handler) override;
|
||||
|
||||
private:
|
||||
QIcon buildTrayIcon(qreal opacity, bool darkTheme, const QColor &indicatorColor) const;
|
||||
QIcon buildTrayIcon(Vpn::ConnectionState state, bool darkTheme) const;
|
||||
|
||||
QSystemTrayIcon m_trayIcon;
|
||||
};
|
||||
|
||||
@@ -23,7 +23,6 @@ class MacOSStatusIcon final : public QObject {
|
||||
public:
|
||||
void setIcon(const QString& iconUrl);
|
||||
void setIconFromData(const QByteArray& imageData);
|
||||
void setIndicatorColor(const QColor& indicatorColor);
|
||||
void setMenu(QMenu* menu);
|
||||
void rebuildNativeMenu();
|
||||
void setToolTip(const QString& tooltip);
|
||||
|
||||
@@ -29,21 +29,17 @@
|
||||
@end
|
||||
|
||||
/**
|
||||
* Creates a NSStatusItem with that can hold an icon. Additionally a NSView is
|
||||
* set as a subview to the button item of the status item. The view serves as
|
||||
* an indicator that can be displayed in color eventhough the icon is set as a
|
||||
* template. In that way we give the system control over it’s effective
|
||||
* appearance.
|
||||
* Creates a NSStatusItem that holds the tray icon. The icon is set as a
|
||||
* template image, so the system controls its effective appearance for the
|
||||
* current menu bar theme. The connection status is baked into the artwork, so
|
||||
* no separate colored indicator is drawn.
|
||||
*/
|
||||
@interface MacOSStatusIconDelegate : NSObject
|
||||
@property(assign) NSStatusItem* statusItem;
|
||||
@property(assign) NSView* statusIndicator;
|
||||
@property(retain) NSMenu* nativeMenu;
|
||||
@property(retain) NSMutableArray* menuActionTargets;
|
||||
|
||||
- (void)setIcon:(NSData*)imageData;
|
||||
- (void)setIndicator;
|
||||
- (void)setIndicatorColor:(NSColor*)color;
|
||||
- (void)setToolTip:(NSString*)tooltip;
|
||||
- (void)rebuildMenuFromQMenu:(QMenu*)menu;
|
||||
@end
|
||||
@@ -62,8 +58,6 @@
|
||||
self.statusItem =
|
||||
[[[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain];
|
||||
self.statusItem.visible = true;
|
||||
// Add the indicator as a subview
|
||||
[self setIndicator];
|
||||
|
||||
return self;
|
||||
}
|
||||
@@ -87,34 +81,6 @@
|
||||
[image release];
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds status indicator as a subview to the status item button.
|
||||
*/
|
||||
- (void)setIndicator {
|
||||
float viewHeight = NSHeight([self.statusItem.button bounds]);
|
||||
float dotSize = viewHeight * 0.35;
|
||||
float dotOrigin = (viewHeight - dotSize) * 0.8;
|
||||
|
||||
NSView* dot = [[NSView alloc] initWithFrame:NSMakeRect(dotOrigin, dotOrigin, dotSize, dotSize)];
|
||||
self.statusIndicator = dot;
|
||||
self.statusIndicator.wantsLayer = true;
|
||||
self.statusIndicator.layer.cornerRadius = dotSize * 0.5;
|
||||
|
||||
[self.statusItem.button addSubview:self.statusIndicator];
|
||||
[dot release];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the color if the indicator.
|
||||
*
|
||||
* @param color The indicator background color.
|
||||
*/
|
||||
- (void)setIndicatorColor:(NSColor*)color {
|
||||
if (self.statusIndicator) {
|
||||
self.statusIndicator.layer.backgroundColor = color.CGColor;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the status bar menu to the status item.
|
||||
*
|
||||
@@ -217,21 +183,6 @@ void MacOSStatusIcon::setIconFromData(const QByteArray& imageData) {
|
||||
[m_statusBarIcon setIcon:data];
|
||||
}
|
||||
|
||||
void MacOSStatusIcon::setIndicatorColor(const QColor& indicatorColor) {
|
||||
logger.debug() << "Set indicator color";
|
||||
|
||||
if (!indicatorColor.isValid()) {
|
||||
[m_statusBarIcon setIndicatorColor:[NSColor clearColor]];
|
||||
return;
|
||||
}
|
||||
|
||||
NSColor* color = [NSColor colorWithCalibratedRed:indicatorColor.red() / 255.0f
|
||||
green:indicatorColor.green() / 255.0f
|
||||
blue:indicatorColor.blue() / 255.0f
|
||||
alpha:indicatorColor.alpha() / 255.0f];
|
||||
[m_statusBarIcon setIndicatorColor:color];
|
||||
}
|
||||
|
||||
void MacOSStatusIcon::setMenu(QMenu* menu) {
|
||||
m_qtMenu = menu;
|
||||
rebuildNativeMenu();
|
||||
|
||||
@@ -23,9 +23,7 @@ void MacTrayIconBackend::show()
|
||||
|
||||
void MacTrayIconBackend::applyVisual(const TrayIconVisual &visual)
|
||||
{
|
||||
const qreal opacity = TrayIconCommon::opacityForState(visual.connectionState);
|
||||
m_statusIcon.setIconFromData(TrayIconCommon::buildTemplatePng(opacity));
|
||||
m_statusIcon.setIndicatorColor(TrayIconCommon::indicatorColorForState(visual.connectionState));
|
||||
m_statusIcon.setIconFromData(TrayIconCommon::buildTemplatePng(visual.connectionState));
|
||||
}
|
||||
|
||||
void MacTrayIconBackend::showMessage(const QString &title, const QString &message, const TrayIconVisual &visual, int timerMsec)
|
||||
|
||||
@@ -6,22 +6,19 @@
|
||||
|
||||
namespace WinTrayIcon
|
||||
{
|
||||
QIcon buildIcon(qreal opacity, bool darkTheme, const QColor &indicatorColor)
|
||||
QIcon buildIcon(Vpn::ConnectionState state, bool darkTheme)
|
||||
{
|
||||
return TrayIconCommon::buildIcon(opacity, darkTheme, indicatorColor);
|
||||
return TrayIconCommon::buildIcon(state, darkTheme);
|
||||
}
|
||||
|
||||
void applyTo(QSystemTrayIcon &trayIcon, Vpn::ConnectionState state, bool darkTheme)
|
||||
{
|
||||
const qreal opacity = TrayIconCommon::opacityForState(state);
|
||||
const QColor indicatorColor = TrayIconCommon::indicatorColorForState(state);
|
||||
trayIcon.setIcon(buildIcon(opacity, darkTheme, indicatorColor));
|
||||
trayIcon.setIcon(buildIcon(state, darkTheme));
|
||||
}
|
||||
|
||||
QIcon buildNotifyIcon(bool darkTheme)
|
||||
{
|
||||
return buildIcon(TrayIconCommon::kConnectedOpacity, darkTheme,
|
||||
TrayIconCommon::indicatorColorForState(Vpn::ConnectionState::Connected));
|
||||
return buildIcon(Vpn::ConnectionState::Connected, darkTheme);
|
||||
}
|
||||
|
||||
void configure(QSystemTrayIcon &trayIcon, QMenu *menu, const QString &tooltip)
|
||||
|
||||
@@ -12,7 +12,7 @@ class QString;
|
||||
|
||||
namespace WinTrayIcon
|
||||
{
|
||||
QIcon buildIcon(qreal opacity, bool darkTheme, const QColor &indicatorColor);
|
||||
QIcon buildIcon(Vpn::ConnectionState state, bool darkTheme);
|
||||
void applyTo(QSystemTrayIcon &trayIcon, Vpn::ConnectionState state, bool darkTheme);
|
||||
QIcon buildNotifyIcon(bool darkTheme);
|
||||
|
||||
|
||||
@@ -7,93 +7,55 @@
|
||||
|
||||
namespace TrayIconCommon
|
||||
{
|
||||
qreal opacityForState(Vpn::ConnectionState state)
|
||||
QString resourcePathForState(Vpn::ConnectionState state, bool darkTheme)
|
||||
{
|
||||
switch (state) {
|
||||
case Vpn::ConnectionState::Error:
|
||||
return QString::fromLatin1(kIconError);
|
||||
case Vpn::ConnectionState::Connected:
|
||||
case Vpn::ConnectionState::Error: return kConnectedOpacity;
|
||||
return QString::fromLatin1(darkTheme ? kIconOnWhite : kIconOnBlack);
|
||||
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 kDisconnectedOpacity;
|
||||
default:
|
||||
return QString::fromLatin1(darkTheme ? kIconOffLight : kIconOffBlack);
|
||||
}
|
||||
}
|
||||
|
||||
QColor indicatorColorForState(Vpn::ConnectionState state)
|
||||
{
|
||||
switch (state) {
|
||||
case Vpn::ConnectionState::Connected: return QColor(52, 199, 89);
|
||||
case Vpn::ConnectionState::Error: return QColor(235, 87, 87);
|
||||
default: return QColor();
|
||||
}
|
||||
}
|
||||
|
||||
QPixmap renderTemplate(const QString &resourcePath, qreal opacity, int size)
|
||||
QPixmap renderIcon(const QString &resourcePath, int size)
|
||||
{
|
||||
QSvgRenderer renderer(resourcePath);
|
||||
QPixmap pixmap(size, size);
|
||||
pixmap.fill(Qt::transparent);
|
||||
|
||||
if (!renderer.isValid()) {
|
||||
qWarning() << "Failed to load tray icon template:" << resourcePath;
|
||||
qWarning() << "Failed to load tray icon:" << resourcePath;
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
QPainter painter(&pixmap);
|
||||
painter.setOpacity(opacity);
|
||||
renderer.render(&painter, QRectF(0, 0, size, size));
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
QPixmap colorizeTemplate(const QPixmap &mask, const QColor &foreground, int size)
|
||||
QPixmap buildPixmap(int size, Vpn::ConnectionState state, bool darkTheme)
|
||||
{
|
||||
QPixmap result(size, size);
|
||||
result.fill(Qt::transparent);
|
||||
|
||||
QPainter painter(&result);
|
||||
painter.fillRect(result.rect(), foreground);
|
||||
painter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
|
||||
painter.drawPixmap(0, 0, mask);
|
||||
return result;
|
||||
return renderIcon(resourcePathForState(state, darkTheme), size);
|
||||
}
|
||||
|
||||
void drawStatusIndicator(QPainter &painter, const QColor &color, int size)
|
||||
{
|
||||
const qreal dotSize = size * 0.35;
|
||||
const qreal dotOrigin = (size - dotSize) * 0.8;
|
||||
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.setBrush(color);
|
||||
painter.drawEllipse(QRectF(dotOrigin, dotOrigin, dotSize, dotSize));
|
||||
}
|
||||
|
||||
QPixmap buildPixmap(int size, qreal opacity, bool darkTheme, const QColor &indicatorColor)
|
||||
{
|
||||
const QPixmap mask = renderTemplate(QString::fromLatin1(kTrayTemplateIconPath), opacity, size);
|
||||
const QColor foreground = darkTheme ? Qt::white : Qt::black;
|
||||
QPixmap pixmap = colorizeTemplate(mask, foreground, size);
|
||||
|
||||
if (indicatorColor.isValid()) {
|
||||
QPainter painter(&pixmap);
|
||||
drawStatusIndicator(painter, indicatorColor, size);
|
||||
}
|
||||
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
QIcon buildIcon(qreal opacity, bool darkTheme, const QColor &indicatorColor)
|
||||
QIcon buildIcon(Vpn::ConnectionState state, bool darkTheme)
|
||||
{
|
||||
QIcon icon;
|
||||
icon.addPixmap(buildPixmap(kDefaultTrayIconSize, opacity, darkTheme, indicatorColor));
|
||||
icon.addPixmap(buildPixmap(kDefaultTrayIconSize, state, darkTheme));
|
||||
return icon;
|
||||
}
|
||||
|
||||
QByteArray buildTemplatePng(qreal opacity)
|
||||
QByteArray buildTemplatePng(Vpn::ConnectionState state)
|
||||
{
|
||||
const QPixmap pixmap = renderTemplate(QString::fromLatin1(kTrayTemplateIconPath), opacity, kDefaultTrayIconSize);
|
||||
const QPixmap pixmap = renderIcon(resourcePathForState(state, /*darkTheme*/ true), kDefaultTrayIconSize);
|
||||
|
||||
QByteArray bytes;
|
||||
QBuffer buffer(&bytes);
|
||||
|
||||
@@ -2,31 +2,29 @@
|
||||
#define TRAYICONCOMMON_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QColor>
|
||||
#include <QIcon>
|
||||
#include <QPainter>
|
||||
#include <QPixmap>
|
||||
#include <QString>
|
||||
|
||||
#include "core/protocols/vpnProtocol.h"
|
||||
|
||||
namespace TrayIconCommon
|
||||
{
|
||||
constexpr int kDefaultTrayIconSize = 128;
|
||||
constexpr char kTrayTemplateIconPath[] = ":/images/tray/icon.svg";
|
||||
|
||||
constexpr qreal kDisconnectedOpacity = 0.5;
|
||||
constexpr qreal kConnectedOpacity = 1.0;
|
||||
constexpr char kIconOffBlack[] = ":/images/tray/off-black.svg";
|
||||
constexpr char kIconOffLight[] = ":/images/tray/off-light.svg";
|
||||
constexpr char kIconOnBlack[] = ":/images/tray/on-black.svg";
|
||||
constexpr char kIconOnWhite[] = ":/images/tray/on-white.svg";
|
||||
constexpr char kIconError[] = ":/images/tray/error.svg";
|
||||
|
||||
qreal opacityForState(Vpn::ConnectionState state);
|
||||
QColor indicatorColorForState(Vpn::ConnectionState state);
|
||||
QString resourcePathForState(Vpn::ConnectionState state, bool darkTheme);
|
||||
|
||||
QPixmap renderTemplate(const QString &resourcePath, qreal opacity, int size);
|
||||
QPixmap colorizeTemplate(const QPixmap &mask, const QColor &foreground, int size);
|
||||
void drawStatusIndicator(QPainter &painter, const QColor &color, int size);
|
||||
QPixmap renderIcon(const QString &resourcePath, int size);
|
||||
|
||||
QPixmap buildPixmap(int size, qreal opacity, bool darkTheme, const QColor &indicatorColor);
|
||||
QIcon buildIcon(qreal opacity, bool darkTheme, const QColor &indicatorColor);
|
||||
QByteArray buildTemplatePng(qreal opacity);
|
||||
QPixmap buildPixmap(int size, Vpn::ConnectionState state, bool darkTheme);
|
||||
QIcon buildIcon(Vpn::ConnectionState state, bool darkTheme);
|
||||
QByteArray buildTemplatePng(Vpn::ConnectionState state);
|
||||
|
||||
} // namespace TrayIconCommon
|
||||
|
||||
|
||||