Fix blurry tray icon with svg themes

QIcon::actualSize doesn't work as expected with svg themes, get actual pixmap and check its size instead.
This commit is contained in:
Ilya Fedin 2020-12-24 18:32:26 +04:00 committed by John Preston
parent 1951b7a8a1
commit 56728a066e

View file

@ -209,6 +209,10 @@ QIcon TrayIconGen(int counter, bool muted) {
48, 48,
}; };
static const auto dprSize = [](const QImage &image) {
return image.size() / image.devicePixelRatio();
};
for (const auto iconSize : iconSizes) { for (const auto iconSize : iconSizes) {
auto &currentImageBack = TrayIconImageBack[iconSize]; auto &currentImageBack = TrayIconImageBack[iconSize];
const auto desiredSize = QSize(iconSize, iconSize); const auto desiredSize = QSize(iconSize, iconSize);
@ -221,11 +225,17 @@ QIcon TrayIconGen(int counter, bool muted) {
systemIcon = QIcon::fromTheme(iconName); systemIcon = QIcon::fromTheme(iconName);
} }
if (systemIcon.actualSize(desiredSize) == desiredSize) { // We can't use QIcon::actualSize here
currentImageBack = systemIcon // since it works incorrectly with svg icon themes
.pixmap(desiredSize) currentImageBack = systemIcon
.toImage(); .pixmap(desiredSize)
} else { .toImage();
const auto firstAttemptSize = dprSize(currentImageBack);
// 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
if (firstAttemptSize.width() < desiredSize.width()) {
const auto availableSizes = systemIcon.availableSizes(); const auto availableSizes = systemIcon.availableSizes();
const auto biggestSize = ranges::max_element( const auto biggestSize = ranges::max_element(
@ -233,18 +243,17 @@ QIcon TrayIconGen(int counter, bool muted) {
std::less<>(), std::less<>(),
&QSize::width); &QSize::width);
currentImageBack = systemIcon if ((*biggestSize).width() > firstAttemptSize.width()) {
.pixmap(*biggestSize) currentImageBack = systemIcon
.toImage(); .pixmap(*biggestSize)
.toImage();
}
} }
} else { } else {
currentImageBack = Core::App().logo(); currentImageBack = Core::App().logo();
} }
const auto currentImageBackSize = currentImageBack.size() if (dprSize(currentImageBack) != desiredSize) {
/ currentImageBack.devicePixelRatio();
if (currentImageBackSize != desiredSize) {
currentImageBack = currentImageBack.scaled( currentImageBack = currentImageBack.scaled(
desiredSize * currentImageBack.devicePixelRatio(), desiredSize * currentImageBack.devicePixelRatio(),
Qt::IgnoreAspectRatio, Qt::IgnoreAspectRatio,
@ -331,17 +340,33 @@ std::unique_ptr<QTemporaryFile> TrayIconFile(
static const auto templateName = AppRuntimeDirectory() static const auto templateName = AppRuntimeDirectory()
+ kTrayIconFilename.utf16(); + kTrayIconFilename.utf16();
static const auto dprSize = [](const QPixmap &pixmap) {
return pixmap.size() / pixmap.devicePixelRatio();
};
static const auto desiredSize = QSize(22, 22); static const auto desiredSize = QSize(22, 22);
static const auto scalePixmap = [=](const QPixmap &pixmap) {
if (dprSize(pixmap) != desiredSize) {
return pixmap.scaled(
desiredSize * pixmap.devicePixelRatio(),
Qt::IgnoreAspectRatio,
Qt::SmoothTransformation);
} else {
return pixmap;
}
};
auto ret = std::make_unique<QTemporaryFile>( auto ret = std::make_unique<QTemporaryFile>(
templateName, templateName,
parent); parent);
ret->open(); ret->open();
if (icon.actualSize(desiredSize) == desiredSize) { const auto firstAttempt = icon.pixmap(desiredSize);
icon.pixmap(desiredSize).save(ret.get()); const auto firstAttemptSize = dprSize(firstAttempt);
} else {
if (firstAttemptSize.width() < desiredSize.width()) {
const auto availableSizes = icon.availableSizes(); const auto availableSizes = icon.availableSizes();
const auto biggestSize = ranges::max_element( const auto biggestSize = ranges::max_element(
@ -349,14 +374,13 @@ std::unique_ptr<QTemporaryFile> TrayIconFile(
std::less<>(), std::less<>(),
&QSize::width); &QSize::width);
const auto iconPixmap = icon.pixmap(*biggestSize); if ((*biggestSize).width() > firstAttemptSize.width()) {
scalePixmap(icon.pixmap(*biggestSize)).save(ret.get());
iconPixmap } else {
.scaled( scalePixmap(firstAttempt).save(ret.get());
desiredSize * iconPixmap.devicePixelRatio(), }
Qt::IgnoreAspectRatio, } else {
Qt::SmoothTransformation) scalePixmap(firstAttempt).save(ret.get());
.save(ret.get());
} }
ret->close(); ret->close();