Files
2026-03-19 00:58:12 +03:00

183 lines
4.5 KiB
C++

// This is the source code of AyuGram for Desktop.
//
// We do not and cannot prevent the use of our code,
// but be respectful and credit the original author.
//
// Copyright @Radolyn, 2026
#include "ayu/ui/components/icon_picker.h"
#include "tray.h"
#include "ayu/ayu_settings.h"
#include "ayu/ui/ayu_logo.h"
#include "core/application.h"
#include "main/main_domain.h"
#include "styles/style_ayu_styles.h"
#include "ui/painter.h"
#include "window/main_window.h"
#ifdef Q_OS_WIN
#include "ayu/utils/windows_utils.h"
#endif
namespace {
const QVector<QString> icons{
AyuAssets::DEFAULT_ICON,
AyuAssets::ALT_ICON,
AyuAssets::DISCORD_ICON,
AyuAssets::SPOTIFY_ICON,
AyuAssets::EXTERA_ICON,
AyuAssets::NOTHING_ICON,
AyuAssets::BARD_ICON,
AyuAssets::YAPLUS_ICON,
AyuAssets::WIN95_ICON,
AyuAssets::CHIBI_ICON,
AyuAssets::CHIBI2_ICON,
AyuAssets::EXTERA2_ICON,
};
const auto rows = static_cast<int>(icons.size()) / IconPicker::kColumns
+ std::min(1, static_cast<int>(icons.size()) % IconPicker::kColumns);
void applyIcon() {
#ifdef Q_OS_WIN
AyuAssets::loadAppIco();
reloadAppIconFromTaskBar();
#endif
Window::OverrideApplicationIcon(AyuAssets::currentAppLogo());
Core::App().refreshApplicationIcon();
Core::App().tray().updateIconCounters();
Core::App().domain().notifyUnreadBadgeChanged();
}
} // namespace
IconPicker::IconPicker(QWidget *parent)
: RpWidget(parent) {
widthValue() | rpl::on_next([=](int w) {
const auto cell = w / kColumns;
const auto iconSize = st::iconPickerIconSize;
const auto contentSize = iconSize + st::iconPickerImagePadding * 2;
const auto h = rows * cell - (cell - contentSize);
resize(w, h);
}, lifetime());
}
void IconPicker::drawIcon(QPainter &p, const QImage &icon, int x, int y, float strokeOpacity) {
{
PainterHighQualityEnabler hq(p);
p.save();
p.setPen(QPen(st::boxDividerBg, 0));
p.setBrush(QBrush(st::boxDividerBg));
p.setOpacity(strokeOpacity);
p.drawRoundedRect(
x + st::iconPickerSelectedPadding,
y + st::iconPickerSelectedPadding,
st::iconPickerIconSize + st::iconPickerSelectedPadding * 2,
st::iconPickerIconSize + st::iconPickerSelectedPadding * 2,
st::iconPickerSelectedRounding,
st::iconPickerSelectedRounding
);
p.restore();
}
const auto rect = QRect(
x + st::iconPickerImagePadding,
y + st::iconPickerImagePadding,
st::iconPickerIconSize,
st::iconPickerIconSize
);
p.drawImage(rect, icon);
}
int IconPicker::cellWidth() const {
return width() / kColumns;
}
void IconPicker::paintEvent(QPaintEvent *e) {
Painter p(this);
const auto cell = cellWidth();
const auto iconSize = st::iconPickerIconSize;
for (int row = 0; row < rows; row++) {
const auto columns = std::min(kColumns, static_cast<int>(icons.size()) - row * kColumns);
for (int i = 0; i < columns; i++) {
auto const idx = i + row * kColumns;
const auto &iconName = icons[idx];
if (iconName.isEmpty()) {
continue;
}
QImage icon;
if (const auto cached = _cachedIcons.find(iconName); cached != _cachedIcons.end()) {
icon = cached->second;
} else {
icon = _cachedIcons[iconName] = AyuAssets::loadPreview(iconName);
}
auto opacity = 0.0f;
if (iconName == _wasSelected) {
opacity = 1.0f - _animation.value(1.0f);
} else if (iconName == AyuAssets::currentAppLogoName()) {
opacity = _wasSelected.isEmpty() ? 1.0f : _animation.value(1.0f);
}
const auto x = i * cell + (cell - iconSize) / 2;
const auto y = row * cell;
drawIcon(p, icon, x, y, opacity);
}
}
}
void IconPicker::mousePressEvent(QMouseEvent *e) {
const auto &settings = AyuSettings::getInstance();
auto changed = false;
const auto cell = cellWidth();
const auto iconSize = st::iconPickerIconSize;
for (int row = 0; row < rows; row++) {
const auto columns = std::min(kColumns, static_cast<int>(icons.size()) - row * kColumns);
for (int i = 0; i < columns; i++) {
auto const idx = i + row * kColumns;
const auto x = i * cell + (cell - iconSize) / 2;
const auto y = row * cell;
if (e->pos().x() >= x && e->pos().x() <= x + iconSize
&& e->pos().y() >= y && e->pos().y() <= y + iconSize) {
const auto &iconName = icons[idx];
if (iconName.isEmpty()) {
break;
}
if (settings.appIcon() != iconName) {
_wasSelected = settings.appIcon();
_animation.start(
[=]
{
update();
},
0.0,
1.0,
200,
anim::easeOutCubic
);
AyuSettings::getInstance().setAppIcon(iconName);
changed = true;
break;
}
}
}
}
if (changed) {
applyIcon();
repaint();
}
}