Cache system icon in Linux tray

This commit is contained in:
Ilya Fedin 2022-12-09 14:50:20 +04:00 committed by John Preston
parent 5101ea2a96
commit 2565b948d9

View file

@ -38,20 +38,29 @@ public:
~IconGraphic(); ~IconGraphic();
[[nodiscard]] bool isRefreshNeeded( [[nodiscard]] bool isRefreshNeeded(
const QIcon &systemIcon,
const QString &iconThemeName,
int counter, int counter,
bool muted, bool muted) const;
const QString &iconThemeName) const; [[nodiscard]] QIcon systemIcon(
[[nodiscard]] QIcon trayIcon(int counter, bool muted); const QString &iconThemeName,
int counter,
bool muted) const;
[[nodiscard]] QIcon trayIcon(
const QIcon &systemIcon,
const QString &iconThemeName,
int counter,
bool muted);
private: private:
[[nodiscard]] QString panelIconName(int counter, bool muted) const; [[nodiscard]] QString panelIconName(int counter, bool muted) const;
[[nodiscard]] QString trayIconName(int counter, bool muted) const;
[[nodiscard]] int counterSlice(int counter) const; [[nodiscard]] int counterSlice(int counter) const;
void updateIconRegenerationNeeded( void updateIconRegenerationNeeded(
const QIcon &icon, const QIcon &icon,
const QIcon &systemIcon,
const QString &iconThemeName,
int counter, int counter,
bool muted, bool muted);
const QString &iconThemeName);
[[nodiscard]] QSize dprSize(const QImage &image) const; [[nodiscard]] QSize dprSize(const QImage &image) const;
const QString _panelTrayIconName; const QString _panelTrayIconName;
@ -64,8 +73,8 @@ private:
int32 _count = 0; int32 _count = 0;
base::flat_map<int, QImage> _imageBack; base::flat_map<int, QImage> _imageBack;
QIcon _trayIcon; QIcon _trayIcon;
QIcon _systemIcon;
QString _themeName; QString _themeName;
QString _name;
}; };
@ -86,17 +95,29 @@ QString IconGraphic::panelIconName(int counter, bool muted) const {
: _panelTrayIconName; : _panelTrayIconName;
} }
QString IconGraphic::trayIconName(int counter, bool muted) const { QIcon IconGraphic::systemIcon(
const auto iconName = base::IconName(); const QString &iconThemeName,
const auto panelName = panelIconName(counter, muted); int counter,
bool muted) const {
if (QIcon::hasThemeIcon(panelName)) { if (iconThemeName == _themeName
return panelName; && counterSlice(counter) == _count
} else if (QIcon::hasThemeIcon(iconName)) { && muted == _muted) {
return iconName; return _systemIcon;
} }
return QString(); const auto candidates = {
panelIconName(counter, muted),
base::IconName(),
};
for (const auto candidate : candidates) {
const auto icon = QIcon::fromTheme(candidate);
if (icon.name() == candidate) {
return icon;
}
}
return QIcon();
} }
@ -107,53 +128,56 @@ int IconGraphic::counterSlice(int counter) const {
} }
bool IconGraphic::isRefreshNeeded( bool IconGraphic::isRefreshNeeded(
const QIcon &systemIcon,
const QString &iconThemeName,
int counter, int counter,
bool muted, bool muted) const {
const QString &iconThemeName) const {
const auto iconName = trayIconName(counter, muted);
return _trayIcon.isNull() return _trayIcon.isNull()
|| iconThemeName != _themeName || iconThemeName != _themeName
|| iconName != _name || systemIcon.name() != _systemIcon.name()
|| muted != _muted || muted != _muted
|| counterSlice(counter) != _count; || counterSlice(counter) != _count;
} }
void IconGraphic::updateIconRegenerationNeeded( void IconGraphic::updateIconRegenerationNeeded(
const QIcon &icon, const QIcon &icon,
const QIcon &systemIcon,
const QString &iconThemeName,
int counter, int counter,
bool muted, bool muted) {
const QString &iconThemeName) {
const auto iconName = trayIconName(counter, muted);
_trayIcon = icon; _trayIcon = icon;
_muted = muted; _systemIcon = systemIcon;
_count = counterSlice(counter);
_themeName = iconThemeName; _themeName = iconThemeName;
_name = iconName; _count = counterSlice(counter);
_muted = muted;
} }
QSize IconGraphic::dprSize(const QImage &image) const { QSize IconGraphic::dprSize(const QImage &image) const {
return image.size() / image.devicePixelRatio(); return image.size() / image.devicePixelRatio();
} }
QIcon IconGraphic::trayIcon(int counter, bool muted) { QIcon IconGraphic::trayIcon(
const auto iconThemeName = QIcon::themeName(); const QIcon &systemIcon,
const QString &iconThemeName,
if (!isRefreshNeeded(counter, muted, iconThemeName)) { int counter,
bool muted) {
if (!isRefreshNeeded(systemIcon, iconThemeName, counter, muted)) {
return _trayIcon; return _trayIcon;
} }
const auto iconName = trayIconName(counter, muted);
if (iconName == panelIconName(counter, muted)) { if (systemIcon.name() == panelIconName(counter, muted)) {
const auto result = QIcon::fromTheme(iconName); updateIconRegenerationNeeded(
updateIconRegenerationNeeded(result, counter, muted, iconThemeName); systemIcon,
return result; systemIcon,
iconThemeName,
counter,
muted);
return systemIcon;
} }
QIcon result; QIcon result;
QIcon systemIcon;
for (const auto iconSize : _iconSizes) { for (const auto iconSize : _iconSizes) {
auto &currentImageBack = _imageBack[iconSize]; auto &currentImageBack = _imageBack[iconSize];
@ -161,12 +185,8 @@ QIcon IconGraphic::trayIcon(int counter, bool muted) {
if (currentImageBack.isNull() if (currentImageBack.isNull()
|| iconThemeName != _themeName || iconThemeName != _themeName
|| iconName != _name) { || systemIcon.name() != _systemIcon.name()) {
if (!iconName.isEmpty()) { if (!systemIcon.isNull()) {
if (systemIcon.isNull()) {
systemIcon = QIcon::fromTheme(iconName);
}
// We can't use QIcon::actualSize here // We can't use QIcon::actualSize here
// since it works incorrectly with svg icon themes // since it works incorrectly with svg icon themes
currentImageBack = systemIcon currentImageBack = systemIcon
@ -243,7 +263,12 @@ QIcon IconGraphic::trayIcon(int counter, bool muted) {
result.addPixmap(Ui::PixmapFromImage(std::move(iconImage))); result.addPixmap(Ui::PixmapFromImage(std::move(iconImage)));
} }
updateIconRegenerationNeeded(result, counter, muted, iconThemeName); updateIconRegenerationNeeded(
result,
systemIcon,
iconThemeName,
counter,
muted);
return result; return result;
} }
@ -304,10 +329,19 @@ void Tray::createIcon() {
}); });
}; };
const auto iconThemeName = QIcon::themeName();
const auto counter = Core::App().unreadBadge();
const auto muted = Core::App().unreadBadgeMuted();
_icon = base::make_unique_q<QSystemTrayIcon>(Parent()); _icon = base::make_unique_q<QSystemTrayIcon>(Parent());
_icon->setIcon(_iconGraphic->trayIcon( _icon->setIcon(_iconGraphic->trayIcon(
Core::App().unreadBadge(), _iconGraphic->systemIcon(
Core::App().unreadBadgeMuted())); iconThemeName,
counter,
muted),
iconThemeName,
counter,
muted));
_icon->setToolTip(AppName.utf16()); _icon->setToolTip(AppName.utf16());
using Reason = QSystemTrayIcon::ActivationReason; using Reason = QSystemTrayIcon::ActivationReason;
@ -348,9 +382,22 @@ void Tray::updateIcon() {
} }
const auto counter = Core::App().unreadBadge(); const auto counter = Core::App().unreadBadge();
const auto muted = Core::App().unreadBadgeMuted(); const auto muted = Core::App().unreadBadgeMuted();
const auto iconThemeName = QIcon::themeName();
const auto systemIcon = _iconGraphic->systemIcon(
iconThemeName,
counter,
muted);
if (_iconGraphic->isRefreshNeeded(counter, muted, QIcon::themeName())) { if (_iconGraphic->isRefreshNeeded(
_icon->setIcon(_iconGraphic->trayIcon(counter, muted)); systemIcon,
iconThemeName,
counter,
muted)) {
_icon->setIcon(_iconGraphic->trayIcon(
systemIcon,
iconThemeName,
counter,
muted));
} }
} }