mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-06 15:13:57 +02:00
Have a state struct in Linux tray
This commit is contained in:
parent
0d7175058b
commit
e60d501e4a
1 changed files with 67 additions and 138 deletions
|
@ -44,66 +44,49 @@ public:
|
||||||
explicit IconGraphic();
|
explicit IconGraphic();
|
||||||
~IconGraphic();
|
~IconGraphic();
|
||||||
|
|
||||||
[[nodiscard]] bool isRefreshNeeded(
|
void updateState();
|
||||||
const QIcon &systemIcon,
|
[[nodiscard]] bool isRefreshNeeded() const;
|
||||||
const QString &iconThemeName,
|
[[nodiscard]] QIcon trayIcon();
|
||||||
int counter,
|
|
||||||
bool muted) const;
|
|
||||||
[[nodiscard]] QIcon systemIcon(
|
|
||||||
const QString &iconThemeName,
|
|
||||||
bool monochrome,
|
|
||||||
int counter,
|
|
||||||
bool muted) const;
|
|
||||||
[[nodiscard]] QIcon trayIcon(
|
|
||||||
const QIcon &systemIcon,
|
|
||||||
const QString &iconThemeName,
|
|
||||||
bool monochrome,
|
|
||||||
int counter,
|
|
||||||
bool muted);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct State {
|
||||||
|
QIcon systemIcon;
|
||||||
|
QString iconThemeName;
|
||||||
|
bool monochrome = false;
|
||||||
|
int32 counter = 0;
|
||||||
|
bool muted = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] QIcon systemIcon() const;
|
||||||
[[nodiscard]] int counterSlice(int counter) const;
|
[[nodiscard]] int counterSlice(int counter) const;
|
||||||
void updateIconRegenerationNeeded(
|
|
||||||
const QIcon &icon,
|
|
||||||
const QIcon &systemIcon,
|
|
||||||
const QString &iconThemeName,
|
|
||||||
bool monochrome,
|
|
||||||
int counter,
|
|
||||||
bool muted);
|
|
||||||
[[nodiscard]] QSize dprSize(const QImage &image) const;
|
[[nodiscard]] QSize dprSize(const QImage &image) const;
|
||||||
|
|
||||||
const int _iconSizes[7];
|
const int _iconSizes[7];
|
||||||
|
|
||||||
bool _muted = true;
|
|
||||||
int32 _count = 0;
|
|
||||||
base::flat_map<int, QImage> _imageBack;
|
base::flat_map<int, QImage> _imageBack;
|
||||||
QIcon _trayIcon;
|
QIcon _trayIcon;
|
||||||
QIcon _systemIcon;
|
State _current;
|
||||||
QString _themeName;
|
State _new;
|
||||||
bool _monochrome;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
IconGraphic::IconGraphic()
|
IconGraphic::IconGraphic()
|
||||||
: _iconSizes{ 16, 22, 32, 48, 64, 128, 256 } {
|
: _iconSizes{ 16, 22, 32, 48, 64, 128, 256 } {
|
||||||
|
updateState();
|
||||||
}
|
}
|
||||||
|
|
||||||
IconGraphic::~IconGraphic() = default;
|
IconGraphic::~IconGraphic() = default;
|
||||||
|
|
||||||
QIcon IconGraphic::systemIcon(
|
QIcon IconGraphic::systemIcon() const {
|
||||||
const QString &iconThemeName,
|
if (_new.iconThemeName == _current.iconThemeName
|
||||||
bool monochrome,
|
&& _new.monochrome == _current.monochrome
|
||||||
int counter,
|
&& (_new.counter > 0) == (_current.counter > 0)
|
||||||
bool muted) const {
|
&& _new.muted == _current.muted) {
|
||||||
if (iconThemeName == _themeName
|
return _current.systemIcon;
|
||||||
&& monochrome == _monochrome
|
|
||||||
&& (counter > 0) == (_count > 0)
|
|
||||||
&& muted == _muted) {
|
|
||||||
return _systemIcon;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto candidates = {
|
const auto candidates = {
|
||||||
monochrome ? PanelIconName(counter, muted) : QString(),
|
_new.monochrome ? PanelIconName(_new.counter, _new.muted) : QString(),
|
||||||
base::IconName(),
|
base::IconName(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -120,80 +103,63 @@ QIcon IconGraphic::systemIcon(
|
||||||
return QIcon();
|
return QIcon();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int IconGraphic::counterSlice(int counter) const {
|
int IconGraphic::counterSlice(int counter) const {
|
||||||
return (counter >= 1000)
|
return (counter >= 1000)
|
||||||
? (1000 + (counter % 100))
|
? (1000 + (counter % 100))
|
||||||
: counter;
|
: counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IconGraphic::isRefreshNeeded(
|
|
||||||
const QIcon &systemIcon,
|
|
||||||
const QString &iconThemeName,
|
|
||||||
int counter,
|
|
||||||
bool muted) const {
|
|
||||||
return _trayIcon.isNull()
|
|
||||||
|| iconThemeName != _themeName
|
|
||||||
|| systemIcon.name() != _systemIcon.name()
|
|
||||||
|| (systemIcon.name() != PanelIconName(counter, muted)
|
|
||||||
? muted != _muted || counterSlice(counter) != _count
|
|
||||||
: false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IconGraphic::updateIconRegenerationNeeded(
|
|
||||||
const QIcon &icon,
|
|
||||||
const QIcon &systemIcon,
|
|
||||||
const QString &iconThemeName,
|
|
||||||
bool monochrome,
|
|
||||||
int counter,
|
|
||||||
bool muted) {
|
|
||||||
_trayIcon = icon;
|
|
||||||
_systemIcon = systemIcon;
|
|
||||||
_themeName = iconThemeName;
|
|
||||||
_monochrome = monochrome;
|
|
||||||
_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(
|
void IconGraphic::updateState() {
|
||||||
const QIcon &systemIcon,
|
_new.iconThemeName = QIcon::themeName();
|
||||||
const QString &iconThemeName,
|
_new.monochrome = Core::App().settings().trayIconMonochrome();
|
||||||
bool monochrome,
|
_new.counter = Core::App().unreadBadge();
|
||||||
int counter,
|
_new.muted = Core::App().unreadBadgeMuted();
|
||||||
bool muted) {
|
_new.systemIcon = systemIcon();
|
||||||
if (!isRefreshNeeded(systemIcon, iconThemeName, counter, muted)) {
|
}
|
||||||
|
|
||||||
|
bool IconGraphic::isRefreshNeeded() const {
|
||||||
|
return _trayIcon.isNull()
|
||||||
|
|| _new.iconThemeName != _current.iconThemeName
|
||||||
|
|| _new.systemIcon.name() != _current.systemIcon.name()
|
||||||
|
|| (_new.systemIcon.name() != PanelIconName(_new.counter, _new.muted)
|
||||||
|
? _new.muted != _current.muted
|
||||||
|
|| counterSlice(_new.counter) != counterSlice(
|
||||||
|
_current.counter)
|
||||||
|
: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
QIcon IconGraphic::trayIcon() {
|
||||||
|
if (!isRefreshNeeded()) {
|
||||||
return _trayIcon;
|
return _trayIcon;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (systemIcon.name() == PanelIconName(counter, muted)) {
|
const auto guard = gsl::finally([&] {
|
||||||
updateIconRegenerationNeeded(
|
_current = _new;
|
||||||
systemIcon,
|
});
|
||||||
systemIcon,
|
|
||||||
iconThemeName,
|
|
||||||
monochrome,
|
|
||||||
counter,
|
|
||||||
muted);
|
|
||||||
|
|
||||||
return systemIcon;
|
if (_new.systemIcon.name() == PanelIconName(
|
||||||
|
_new.counter,
|
||||||
|
_new.muted)) {
|
||||||
|
_trayIcon = _new.systemIcon;
|
||||||
|
return _trayIcon;
|
||||||
}
|
}
|
||||||
|
|
||||||
QIcon result;
|
QIcon result;
|
||||||
|
|
||||||
for (const auto iconSize : _iconSizes) {
|
for (const auto iconSize : _iconSizes) {
|
||||||
auto ¤tImageBack = _imageBack[iconSize];
|
auto ¤tImageBack = _imageBack[iconSize];
|
||||||
const auto desiredSize = QSize(iconSize, iconSize);
|
const auto desiredSize = QSize(iconSize, iconSize);
|
||||||
|
|
||||||
if (currentImageBack.isNull()
|
if (currentImageBack.isNull()
|
||||||
|| iconThemeName != _themeName
|
|| _new.iconThemeName != _current.iconThemeName
|
||||||
|| systemIcon.name() != _systemIcon.name()) {
|
|| _new.systemIcon.name() != _current.systemIcon.name()) {
|
||||||
if (!systemIcon.isNull()) {
|
if (!_new.systemIcon.isNull()) {
|
||||||
// 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 = _new.systemIcon
|
||||||
.pixmap(desiredSize)
|
.pixmap(desiredSize)
|
||||||
.toImage();
|
.toImage();
|
||||||
|
|
||||||
|
@ -202,7 +168,8 @@ QIcon IconGraphic::trayIcon(
|
||||||
// if current icon theme is not a svg one, Qt can return
|
// if current icon theme is not a svg one, Qt can return
|
||||||
// a pixmap that less in size even if there are a bigger one
|
// a pixmap that less in size even if there are a bigger one
|
||||||
if (firstAttemptSize.width() < desiredSize.width()) {
|
if (firstAttemptSize.width() < desiredSize.width()) {
|
||||||
const auto availableSizes = systemIcon.availableSizes();
|
const auto availableSizes
|
||||||
|
= _new.systemIcon.availableSizes();
|
||||||
|
|
||||||
const auto biggestSize = ranges::max_element(
|
const auto biggestSize = ranges::max_element(
|
||||||
availableSizes,
|
availableSizes,
|
||||||
|
@ -210,7 +177,7 @@ QIcon IconGraphic::trayIcon(
|
||||||
&QSize::width);
|
&QSize::width);
|
||||||
|
|
||||||
if (biggestSize->width() > firstAttemptSize.width()) {
|
if (biggestSize->width() > firstAttemptSize.width()) {
|
||||||
currentImageBack = systemIcon
|
currentImageBack = _new.systemIcon
|
||||||
.pixmap(*biggestSize)
|
.pixmap(*biggestSize)
|
||||||
.toImage();
|
.toImage();
|
||||||
}
|
}
|
||||||
|
@ -227,24 +194,17 @@ QIcon IconGraphic::trayIcon(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result.addPixmap(Ui::PixmapFromImage(counter > 0
|
result.addPixmap(Ui::PixmapFromImage(_new.counter > 0
|
||||||
? Window::WithSmallCounter(std::move(currentImageBack), {
|
? Window::WithSmallCounter(std::move(currentImageBack), {
|
||||||
.size = iconSize,
|
.size = iconSize,
|
||||||
.count = counter,
|
.count = _new.counter,
|
||||||
.bg = muted ? st::trayCounterBgMute : st::trayCounterBg,
|
.bg = _new.muted ? st::trayCounterBgMute : st::trayCounterBg,
|
||||||
.fg = st::trayCounterFg,
|
.fg = st::trayCounterFg,
|
||||||
}) : std::move(currentImageBack)));
|
}) : std::move(currentImageBack)));
|
||||||
}
|
}
|
||||||
|
|
||||||
updateIconRegenerationNeeded(
|
_trayIcon = result;
|
||||||
result,
|
return _trayIcon;
|
||||||
systemIcon,
|
|
||||||
iconThemeName,
|
|
||||||
monochrome,
|
|
||||||
counter,
|
|
||||||
muted);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class TrayEventFilter final : public QObject {
|
class TrayEventFilter final : public QObject {
|
||||||
|
@ -321,22 +281,8 @@ void Tray::createIcon() {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto iconThemeName = QIcon::themeName();
|
|
||||||
const auto monochrome = Core::App().settings().trayIconMonochrome();
|
|
||||||
const auto counter = Core::App().unreadBadge();
|
|
||||||
const auto muted = Core::App().unreadBadgeMuted();
|
|
||||||
|
|
||||||
_icon = base::make_unique_q<QSystemTrayIcon>(nullptr);
|
_icon = base::make_unique_q<QSystemTrayIcon>(nullptr);
|
||||||
_icon->setIcon(_iconGraphic->trayIcon(
|
_icon->setIcon(_iconGraphic->trayIcon());
|
||||||
_iconGraphic->systemIcon(
|
|
||||||
iconThemeName,
|
|
||||||
monochrome,
|
|
||||||
counter,
|
|
||||||
muted),
|
|
||||||
iconThemeName,
|
|
||||||
monochrome,
|
|
||||||
counter,
|
|
||||||
muted));
|
|
||||||
_icon->setToolTip(AppName.utf16());
|
_icon->setToolTip(AppName.utf16());
|
||||||
|
|
||||||
using Reason = QSystemTrayIcon::ActivationReason;
|
using Reason = QSystemTrayIcon::ActivationReason;
|
||||||
|
@ -375,27 +321,10 @@ void Tray::updateIcon() {
|
||||||
if (!_icon || !_iconGraphic) {
|
if (!_icon || !_iconGraphic) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto counter = Core::App().unreadBadge();
|
|
||||||
const auto muted = Core::App().unreadBadgeMuted();
|
|
||||||
const auto monochrome = Core::App().settings().trayIconMonochrome();
|
|
||||||
const auto iconThemeName = QIcon::themeName();
|
|
||||||
const auto systemIcon = _iconGraphic->systemIcon(
|
|
||||||
iconThemeName,
|
|
||||||
monochrome,
|
|
||||||
counter,
|
|
||||||
muted);
|
|
||||||
|
|
||||||
if (_iconGraphic->isRefreshNeeded(
|
_iconGraphic->updateState();
|
||||||
systemIcon,
|
if (_iconGraphic->isRefreshNeeded()) {
|
||||||
iconThemeName,
|
_icon->setIcon(_iconGraphic->trayIcon());
|
||||||
counter,
|
|
||||||
muted)) {
|
|
||||||
_icon->setIcon(_iconGraphic->trayIcon(
|
|
||||||
systemIcon,
|
|
||||||
iconThemeName,
|
|
||||||
monochrome,
|
|
||||||
counter,
|
|
||||||
muted));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue