dde-dock/frame/util/themeappicon.cpp
Fan PengCheng ed5ae88ae2 feat: 修复应用升级后任务栏驻留的图标可能显示异常的问题
应用升级后,其desktop文件中对应的Icon字段可能发生变更,任务栏会重新获取当前的Icon,
当这个Icon对应的图片还没有放到指定的位置时,此时获取的图标就是异常的,且后续再获取时,及时图标已经正常,
但因为qt的缓存机制,也会导致获取的图标仍然是第一次获取的异常图标

Log: 修复应用升级后任务栏驻留的图标可能显示异常的问题
Task: https://pms.uniontech.com/zentao/task-view-64795.html
Change-Id: I955108d04af65b2ca9cc1e6347a4c390b9ec9d77
2021-04-22 17:10:55 +08:00

201 lines
6.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd.
*
* Author: sbw <sbw@sbw.so>
*
* Maintainer: sbw <sbw@sbw.so>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "themeappicon.h"
#include "imageutil.h"
#include <QIcon>
#include <QFile>
#include <QDebug>
#include <QApplication>
#include <QPixmapCache>
#include <QCryptographicHash>
#include <QHBoxLayout>
#include <QLabel>
#include <QDate>
#include <private/qguiapplication_p.h>
#include <private/qiconloader_p.h>
#include <qpa/qplatformtheme.h>
ThemeAppIcon::ThemeAppIcon(QObject *parent) : QObject(parent)
{
}
ThemeAppIcon::~ThemeAppIcon()
{
}
/**
* @brief ThemeAppIcon::getIcon 根据传入的\a name 参数重新从系统主题中获取一次图标
* @param name 图标名
* @return 获取到的图标
* @note 之所以不使用QIcon::fromTheme是因为这个函数中有缓存机制获取系统主题中的图标的时候第一次获取不到下一次也是获取不到
*/
QIcon ThemeAppIcon::getIcon(const QString &name)
{
QIcon icon;
QPlatformTheme * const platformTheme = QGuiApplicationPrivate::platformTheme();
bool hasUserTheme = QIconLoader::instance()->hasUserTheme();
if (!platformTheme || hasUserTheme)
return QIcon::fromTheme(name);
QIconEngine * const engine = platformTheme->createIconEngine(name);
QIcon *cachedIcon = new QIcon(engine);
icon = *cachedIcon;
return icon;
}
bool ThemeAppIcon::getIcon(QPixmap &pix, const QString iconName, const int size, const qreal ratio, bool reObtain)
{
QString key;
QIcon icon;
bool ret = true;
// 把size改为小于size的最大偶数 :)
const int s = int(size * ratio) & ~1;
const float iconZoom = size / 64.0 * 0.8;
if (iconName == "dde-calendar") {
QDate const date(QDate::currentDate());
auto calendar = new QWidget() ;
calendar->setFixedSize(s, s);
calendar->setAutoFillBackground(true);
QPalette palette = calendar->palette();
palette.setBrush(QPalette::Window,
QBrush(QPixmap(":/indicator/resources/calendar_bg.svg").scaled(
calendar->size(),
Qt::IgnoreAspectRatio,
Qt::SmoothTransformation)));
calendar->setPalette(palette);
QVBoxLayout *layout = new QVBoxLayout;
layout->setSpacing(0);
auto month = new QLabel();
auto monthPix = ImageUtil::loadSvg(QString(":/icons/resources/month%1.svg").arg(date.month()), QSize(36, 16)*iconZoom, ratio);
month->setPixmap(monthPix.scaled(monthPix.width()*ratio,monthPix.height()*ratio, Qt::KeepAspectRatio, Qt::SmoothTransformation));
month->setFixedHeight(month->pixmap()->height());
month->setAlignment(Qt::AlignCenter);
month->setFixedWidth(s - 5 * iconZoom);
layout->addWidget(month, Qt::AlignVCenter);
auto day = new QLabel();
auto dayPix =ImageUtil::loadSvg(QString(":/icons/resources/day%1.svg").arg(date.day()), QSize(32, 30)*iconZoom, ratio);
day->setPixmap(dayPix.scaled(dayPix.width()*ratio,dayPix.height()*ratio, Qt::KeepAspectRatio, Qt::SmoothTransformation));
day->setAlignment(Qt::AlignCenter);
day->setFixedHeight(day->pixmap()->height()/ratio);
day->raise();
layout->addWidget(day, Qt::AlignVCenter);
auto week = new QLabel();
auto weekPix = ImageUtil::loadSvg(QString(":/icons/resources/week%1.svg").arg(date.dayOfWeek()), QSize(26, 13)*iconZoom, ratio);
week->setPixmap(weekPix.scaled(weekPix.width()*ratio,weekPix.height()*ratio, Qt::KeepAspectRatio, Qt::SmoothTransformation));
week->setFixedHeight(week->pixmap()->height());
week->setAlignment(Qt::AlignCenter);
week->setFixedWidth(s + 5 * iconZoom);
layout->addWidget(week, Qt::AlignVCenter);
layout->setSpacing(0);
layout->setContentsMargins(0, 10 * iconZoom, 0, 10 * iconZoom);
calendar->setLayout(layout);
pix = calendar->grab(calendar->rect());
delete calendar;
calendar = nullptr;
if (pix.size().width() != s) {
pix = pix.scaled(s, s, Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
return ret;
}
do {
// load pixmap from our Cache
if (iconName.startsWith("data:image/")) {
key = QCryptographicHash::hash(iconName.toUtf8(), QCryptographicHash::Md5).toHex();
// FIXME(hualet): The cache can reduce memory usage,
// that is ~2M on HiDPI enabled machine with 9 icons loaded,
// but I don't know why since QIcon has its own cache and all of the
// icons loaded are loaded by QIcon::fromTheme, really strange here.
if (QPixmapCache::find(key, &pix))
break;
}
// load pixmap from Byte-Data
if (iconName.startsWith("data:image/")) {
const QStringList strs = iconName.split("base64,");
if (strs.size() == 2)
pix.loadFromData(QByteArray::fromBase64(strs.at(1).toLatin1()));
if (!pix.isNull())
break;
}
// load pixmap from File
if (QFile::exists(iconName)) {
pix = QPixmap(iconName);
if (!pix.isNull())
break;
}
// 重新从主题中获取一次
if (reObtain)
icon = getIcon(iconName);
else
icon = QIcon::fromTheme(iconName);
if(icon.isNull()) {
icon = QIcon::fromTheme("application-x-desktop");
ret = false;
}
// load pixmap from Icon-Theme
const int fakeSize = std::max(48, s); // cannot use 16x16, cause 16x16 is label icon
pix = icon.pixmap(QSize(fakeSize, fakeSize));
if (!pix.isNull())
break;
// fallback to a Default pixmap
pix = QPixmap(":/icons/resources/application-x-desktop.svg");
if (!pix.isNull())
break;
Q_UNREACHABLE();
} while (false);
if (!key.isEmpty()) {
QPixmapCache::insert(key, pix);
}
if (pix.size().width() != s) {
pix = pix.scaled(s, s, Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
pix.setDevicePixelRatio(ratio);
return ret;
}