mirror of
https://github.com/linuxdeepin/dde-dock.git
synced 2025-06-02 15:45:21 +00:00
feat: 修复应用升级后任务栏驻留的图标可能显示异常的问题
应用升级后,其desktop文件中对应的Icon字段可能发生变更,任务栏会重新获取当前的Icon, 当这个Icon对应的图片还没有放到指定的位置时,此时获取的图标就是异常的,且后续再获取时,及时图标已经正常, 但因为qt的缓存机制,也会导致获取的图标仍然是第一次获取的异常图标 Log: 修复应用升级后任务栏驻留的图标可能显示异常的问题 Task: https://pms.uniontech.com/zentao/task-view-64795.html Change-Id: I955108d04af65b2ca9cc1e6347a4c390b9ec9d77
This commit is contained in:
parent
0eb877e733
commit
ed5ae88ae2
@ -61,6 +61,7 @@ target_link_libraries(${BIN_NAME} PRIVATE
|
||||
${DFrameworkDBus_LIBRARIES}
|
||||
${DtkWidget_LIBRARIES}
|
||||
${Qt5Widgets_LIBRARIES}
|
||||
${Qt5Gui_LIBRARIES}
|
||||
${Qt5Concurrent_LIBRARIES}
|
||||
${Qt5X11Extras_LIBRARIES}
|
||||
${Qt5DBus_LIBRARIES}
|
||||
|
@ -61,6 +61,7 @@ AppItem::AppItem(const QGSettings *appSettings, const QGSettings *activeAppSetti
|
||||
, m_dragging(false)
|
||||
, m_retryTimes(0)
|
||||
, m_lastShowDay(0)
|
||||
, m_iconValid(false)
|
||||
, m_lastclickTimes(0)
|
||||
, m_appIcon(QPixmap())
|
||||
, m_updateIconGeometryTimer(new QTimer(this))
|
||||
@ -600,20 +601,27 @@ void AppItem::refreshIcon()
|
||||
const int iconSize = qMin(width(), height());
|
||||
|
||||
if (DockDisplayMode == Efficient)
|
||||
m_appIcon = ThemeAppIcon::getIcon(icon, iconSize * 0.7, devicePixelRatioF());
|
||||
m_iconValid = ThemeAppIcon::getIcon(m_appIcon, icon, iconSize * 0.7, devicePixelRatioF(), !m_iconValid);
|
||||
else
|
||||
m_appIcon = ThemeAppIcon::getIcon(icon, iconSize * 0.8, devicePixelRatioF());
|
||||
m_iconValid = ThemeAppIcon::getIcon(m_appIcon, icon, iconSize * 0.8, devicePixelRatioF(), !m_iconValid);
|
||||
|
||||
if (!m_refershIconTimer->isActive() && m_itemEntryInter->icon() == "dde-calendar") {
|
||||
m_refershIconTimer->start();
|
||||
}
|
||||
|
||||
if (m_appIcon.isNull()) {
|
||||
if (!m_iconValid) {
|
||||
if (m_retryTimes < 5) {
|
||||
m_retryTimes++;
|
||||
qDebug() << m_itemEntryInter->name() << "obtain app icon(" << icon << ")failed, retry times:" << m_retryTimes;
|
||||
m_retryObtainIconTimer->start();
|
||||
} else {
|
||||
// 如果图标获取失败,没隔10秒刷新一次
|
||||
if (!m_iconValid)
|
||||
QTimer::singleShot(10 * 1000, this, [ = ] { m_retryObtainIconTimer->start(); });
|
||||
}
|
||||
|
||||
update();
|
||||
|
||||
return;
|
||||
} else if (m_retryTimes > 0) {
|
||||
// reset times
|
||||
|
@ -121,6 +121,7 @@ private:
|
||||
bool m_active;
|
||||
int m_retryTimes;
|
||||
int m_lastShowDay;
|
||||
bool m_iconValid;
|
||||
unsigned long m_lastclickTimes;
|
||||
|
||||
WindowInfoMap m_windowInfos;
|
||||
|
@ -51,11 +51,10 @@ LauncherItem::LauncherItem(QWidget *parent)
|
||||
void LauncherItem::refreshIcon()
|
||||
{
|
||||
const int iconSize = qMin(width(), height());
|
||||
if (DockDisplayMode == Efficient)
|
||||
{
|
||||
m_icon = ThemeAppIcon::getIcon("deepin-launcher", iconSize * 0.7, devicePixelRatioF());
|
||||
if (DockDisplayMode == Efficient) {
|
||||
ThemeAppIcon::getIcon(m_icon, "deepin-launcher", iconSize * 0.7, devicePixelRatioF());
|
||||
} else {
|
||||
m_icon = ThemeAppIcon::getIcon("deepin-launcher", iconSize * 0.8, devicePixelRatioF());
|
||||
ThemeAppIcon::getIcon(m_icon, "deepin-launcher", iconSize * 0.8, devicePixelRatioF());
|
||||
}
|
||||
|
||||
update();
|
||||
|
@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
#include "themeappicon.h"
|
||||
#include "imageutil.h"
|
||||
|
||||
#include <QIcon>
|
||||
#include <QFile>
|
||||
@ -31,7 +32,9 @@
|
||||
#include <QLabel>
|
||||
#include <QDate>
|
||||
|
||||
#include "imageutil.h"
|
||||
#include <private/qguiapplication_p.h>
|
||||
#include <private/qiconloader_p.h>
|
||||
#include <qpa/qplatformtheme.h>
|
||||
|
||||
ThemeAppIcon::ThemeAppIcon(QObject *parent) : QObject(parent)
|
||||
{
|
||||
@ -43,11 +46,33 @@ ThemeAppIcon::~ThemeAppIcon()
|
||||
|
||||
}
|
||||
|
||||
const QPixmap ThemeAppIcon::getIcon(const QString iconName, const int size, const qreal ratio)
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
QPixmap pixmap;
|
||||
QString key;
|
||||
QIcon icon;
|
||||
bool ret = true;
|
||||
// 把size改为小于size的最大偶数 :)
|
||||
const int s = int(size * ratio) & ~1;
|
||||
const float iconZoom = size / 64.0 * 0.8;
|
||||
@ -95,15 +120,15 @@ const QPixmap ThemeAppIcon::getIcon(const QString iconName, const int size, cons
|
||||
layout->setSpacing(0);
|
||||
layout->setContentsMargins(0, 10 * iconZoom, 0, 10 * iconZoom);
|
||||
calendar->setLayout(layout);
|
||||
pixmap = calendar->grab(calendar->rect());
|
||||
pix = calendar->grab(calendar->rect());
|
||||
|
||||
delete calendar;
|
||||
calendar = nullptr;
|
||||
|
||||
if (pixmap.size().width() != s) {
|
||||
pixmap = pixmap.scaled(s, s, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
if (pix.size().width() != s) {
|
||||
pix = pix.scaled(s, s, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
}
|
||||
return pixmap;
|
||||
return ret;
|
||||
}
|
||||
|
||||
do {
|
||||
@ -115,7 +140,7 @@ const QPixmap ThemeAppIcon::getIcon(const QString iconName, const int size, cons
|
||||
// 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, &pixmap))
|
||||
if (QPixmapCache::find(key, &pix))
|
||||
break;
|
||||
}
|
||||
|
||||
@ -123,40 +148,39 @@ const QPixmap ThemeAppIcon::getIcon(const QString iconName, const int size, cons
|
||||
if (iconName.startsWith("data:image/")) {
|
||||
const QStringList strs = iconName.split("base64,");
|
||||
if (strs.size() == 2)
|
||||
pixmap.loadFromData(QByteArray::fromBase64(strs.at(1).toLatin1()));
|
||||
pix.loadFromData(QByteArray::fromBase64(strs.at(1).toLatin1()));
|
||||
|
||||
if (!pixmap.isNull())
|
||||
if (!pix.isNull())
|
||||
break;
|
||||
}
|
||||
|
||||
// load pixmap from File
|
||||
if (QFile::exists(iconName)) {
|
||||
pixmap = QPixmap(iconName);
|
||||
if (!pixmap.isNull())
|
||||
pix = QPixmap(iconName);
|
||||
if (!pix.isNull())
|
||||
break;
|
||||
}
|
||||
|
||||
icon = QIcon::fromTheme(iconName);
|
||||
if (icon.isNull()) {
|
||||
//手动更新图标缓存
|
||||
system("gtk-update-icon-cache /usr/share/icons/hicolor/");
|
||||
|
||||
// 重新从主题中获取一次
|
||||
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
|
||||
pixmap = icon.pixmap(QSize(fakeSize, fakeSize));
|
||||
if (!pixmap.isNull())
|
||||
pix = icon.pixmap(QSize(fakeSize, fakeSize));
|
||||
if (!pix.isNull())
|
||||
break;
|
||||
|
||||
// fallback to a Default pixmap
|
||||
pixmap = QPixmap(":/icons/resources/application-x-desktop.svg");
|
||||
if (!pixmap.isNull())
|
||||
pix = QPixmap(":/icons/resources/application-x-desktop.svg");
|
||||
if (!pix.isNull())
|
||||
break;
|
||||
|
||||
Q_UNREACHABLE();
|
||||
@ -164,12 +188,13 @@ const QPixmap ThemeAppIcon::getIcon(const QString iconName, const int size, cons
|
||||
} while (false);
|
||||
|
||||
if (!key.isEmpty()) {
|
||||
QPixmapCache::insert(key, pixmap);
|
||||
QPixmapCache::insert(key, pix);
|
||||
}
|
||||
|
||||
if (pixmap.size().width() != s) {
|
||||
pixmap = pixmap.scaled(s, s, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
if (pix.size().width() != s) {
|
||||
pix = pix.scaled(s, s, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
}
|
||||
pixmap.setDevicePixelRatio(ratio);
|
||||
return pixmap;
|
||||
pix.setDevicePixelRatio(ratio);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -31,7 +31,8 @@ public:
|
||||
explicit ThemeAppIcon(QObject *parent = 0);
|
||||
~ThemeAppIcon();
|
||||
|
||||
static const QPixmap getIcon(const QString iconName, const int size, const qreal ratio);
|
||||
static QIcon getIcon(const QString &name);
|
||||
static bool getIcon(QPixmap &pix, const QString iconName, const int size, const qreal ratio, bool reObtain = false);
|
||||
};
|
||||
|
||||
#endif // THEMEAPPICON_H
|
||||
|
@ -34,6 +34,7 @@ add_library(${PLUGIN_NAME} SHARED ${SRCS} tray.qrc)
|
||||
set_target_properties(${PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../)
|
||||
target_include_directories(${PLUGIN_NAME} PUBLIC ${DtkWidget_INCLUDE_DIRS}
|
||||
${Qt5DBus_INCLUDE_DIRS}
|
||||
${Qt5Gui_PRIVATE_INCLUDE_DIRS}
|
||||
${XCB_LIBS_INCLUDE_DIRS}
|
||||
${DDE-Network-Utils_INCLUDE_DIRS}
|
||||
${DFrameworkDBus_INCLUDE_DIRS}
|
||||
|
@ -542,7 +542,7 @@ QPixmap SNITrayWidget::newIconPixmap(IconType iconType)
|
||||
// so, it should be the last fallback
|
||||
if (!iconName.isEmpty()) {
|
||||
// ThemeAppIcon::getIcon 会处理高分屏缩放问题
|
||||
pixmap = ThemeAppIcon::getIcon(iconName, IconSize, devicePixelRatioF());
|
||||
ThemeAppIcon::getIcon(pixmap, iconName, IconSize, devicePixelRatioF());
|
||||
if (!pixmap.isNull()) {
|
||||
break;
|
||||
}
|
||||
|
@ -44,11 +44,18 @@ void Ut_ThemeAppIcon::TearDown()
|
||||
TEST_F(Ut_ThemeAppIcon, getIcon_test)
|
||||
{
|
||||
ThemeAppIcon appIcon;
|
||||
const QPixmap &pix1 = appIcon.getIcon("", 50, 1.0);
|
||||
QPixmap pix1;
|
||||
appIcon.getIcon(pix1, "", 50, 1.0);
|
||||
ASSERT_FALSE(pix1.isNull());
|
||||
appIcon.getIcon("dde-calendar", 50, 1.0);
|
||||
const QPixmap &pix2 = appIcon.getIcon("data:image/test", 50, 1.0);
|
||||
|
||||
QPixmap pix;
|
||||
appIcon.getIcon(pix, "dde-calendar", 50, 1.0);
|
||||
|
||||
QPixmap pix2;
|
||||
appIcon.getIcon(pix2, "data:image/test", 50, 1.0);
|
||||
ASSERT_FALSE(pix2.isNull());
|
||||
const QPixmap &pix3 = appIcon.getIcon(":/res/all_settings_on.png", 50, 1.0);
|
||||
|
||||
QPixmap pix3;
|
||||
appIcon.getIcon(pix3, ":/res/all_settings_on.png", 50, 1.0);
|
||||
ASSERT_FALSE(pix3.isNull());
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user