mirror of
https://github.com/linuxdeepin/dde-dock.git
synced 2025-06-04 09:23:03 +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}
|
${DFrameworkDBus_LIBRARIES}
|
||||||
${DtkWidget_LIBRARIES}
|
${DtkWidget_LIBRARIES}
|
||||||
${Qt5Widgets_LIBRARIES}
|
${Qt5Widgets_LIBRARIES}
|
||||||
|
${Qt5Gui_LIBRARIES}
|
||||||
${Qt5Concurrent_LIBRARIES}
|
${Qt5Concurrent_LIBRARIES}
|
||||||
${Qt5X11Extras_LIBRARIES}
|
${Qt5X11Extras_LIBRARIES}
|
||||||
${Qt5DBus_LIBRARIES}
|
${Qt5DBus_LIBRARIES}
|
||||||
|
@ -61,6 +61,7 @@ AppItem::AppItem(const QGSettings *appSettings, const QGSettings *activeAppSetti
|
|||||||
, m_dragging(false)
|
, m_dragging(false)
|
||||||
, m_retryTimes(0)
|
, m_retryTimes(0)
|
||||||
, m_lastShowDay(0)
|
, m_lastShowDay(0)
|
||||||
|
, m_iconValid(false)
|
||||||
, m_lastclickTimes(0)
|
, m_lastclickTimes(0)
|
||||||
, m_appIcon(QPixmap())
|
, m_appIcon(QPixmap())
|
||||||
, m_updateIconGeometryTimer(new QTimer(this))
|
, m_updateIconGeometryTimer(new QTimer(this))
|
||||||
@ -600,20 +601,27 @@ void AppItem::refreshIcon()
|
|||||||
const int iconSize = qMin(width(), height());
|
const int iconSize = qMin(width(), height());
|
||||||
|
|
||||||
if (DockDisplayMode == Efficient)
|
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
|
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") {
|
if (!m_refershIconTimer->isActive() && m_itemEntryInter->icon() == "dde-calendar") {
|
||||||
m_refershIconTimer->start();
|
m_refershIconTimer->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_appIcon.isNull()) {
|
if (!m_iconValid) {
|
||||||
if (m_retryTimes < 5) {
|
if (m_retryTimes < 5) {
|
||||||
m_retryTimes++;
|
m_retryTimes++;
|
||||||
qDebug() << m_itemEntryInter->name() << "obtain app icon(" << icon << ")failed, retry times:" << m_retryTimes;
|
qDebug() << m_itemEntryInter->name() << "obtain app icon(" << icon << ")failed, retry times:" << m_retryTimes;
|
||||||
m_retryObtainIconTimer->start();
|
m_retryObtainIconTimer->start();
|
||||||
|
} else {
|
||||||
|
// 如果图标获取失败,没隔10秒刷新一次
|
||||||
|
if (!m_iconValid)
|
||||||
|
QTimer::singleShot(10 * 1000, this, [ = ] { m_retryObtainIconTimer->start(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} else if (m_retryTimes > 0) {
|
} else if (m_retryTimes > 0) {
|
||||||
// reset times
|
// reset times
|
||||||
|
@ -121,6 +121,7 @@ private:
|
|||||||
bool m_active;
|
bool m_active;
|
||||||
int m_retryTimes;
|
int m_retryTimes;
|
||||||
int m_lastShowDay;
|
int m_lastShowDay;
|
||||||
|
bool m_iconValid;
|
||||||
unsigned long m_lastclickTimes;
|
unsigned long m_lastclickTimes;
|
||||||
|
|
||||||
WindowInfoMap m_windowInfos;
|
WindowInfoMap m_windowInfos;
|
||||||
|
@ -51,11 +51,10 @@ LauncherItem::LauncherItem(QWidget *parent)
|
|||||||
void LauncherItem::refreshIcon()
|
void LauncherItem::refreshIcon()
|
||||||
{
|
{
|
||||||
const int iconSize = qMin(width(), height());
|
const int iconSize = qMin(width(), height());
|
||||||
if (DockDisplayMode == Efficient)
|
if (DockDisplayMode == Efficient) {
|
||||||
{
|
ThemeAppIcon::getIcon(m_icon, "deepin-launcher", iconSize * 0.7, devicePixelRatioF());
|
||||||
m_icon = ThemeAppIcon::getIcon("deepin-launcher", iconSize * 0.7, devicePixelRatioF());
|
|
||||||
} else {
|
} else {
|
||||||
m_icon = ThemeAppIcon::getIcon("deepin-launcher", iconSize * 0.8, devicePixelRatioF());
|
ThemeAppIcon::getIcon(m_icon, "deepin-launcher", iconSize * 0.8, devicePixelRatioF());
|
||||||
}
|
}
|
||||||
|
|
||||||
update();
|
update();
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "themeappicon.h"
|
#include "themeappicon.h"
|
||||||
|
#include "imageutil.h"
|
||||||
|
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
@ -31,7 +32,9 @@
|
|||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QDate>
|
#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)
|
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;
|
QString key;
|
||||||
QIcon icon;
|
QIcon icon;
|
||||||
|
bool ret = true;
|
||||||
// 把size改为小于size的最大偶数 :)
|
// 把size改为小于size的最大偶数 :)
|
||||||
const int s = int(size * ratio) & ~1;
|
const int s = int(size * ratio) & ~1;
|
||||||
const float iconZoom = size / 64.0 * 0.8;
|
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->setSpacing(0);
|
||||||
layout->setContentsMargins(0, 10 * iconZoom, 0, 10 * iconZoom);
|
layout->setContentsMargins(0, 10 * iconZoom, 0, 10 * iconZoom);
|
||||||
calendar->setLayout(layout);
|
calendar->setLayout(layout);
|
||||||
pixmap = calendar->grab(calendar->rect());
|
pix = calendar->grab(calendar->rect());
|
||||||
|
|
||||||
delete calendar;
|
delete calendar;
|
||||||
calendar = nullptr;
|
calendar = nullptr;
|
||||||
|
|
||||||
if (pixmap.size().width() != s) {
|
if (pix.size().width() != s) {
|
||||||
pixmap = pixmap.scaled(s, s, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
pix = pix.scaled(s, s, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||||
}
|
}
|
||||||
return pixmap;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
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,
|
// 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
|
// 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.
|
// icons loaded are loaded by QIcon::fromTheme, really strange here.
|
||||||
if (QPixmapCache::find(key, &pixmap))
|
if (QPixmapCache::find(key, &pix))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,40 +148,39 @@ const QPixmap ThemeAppIcon::getIcon(const QString iconName, const int size, cons
|
|||||||
if (iconName.startsWith("data:image/")) {
|
if (iconName.startsWith("data:image/")) {
|
||||||
const QStringList strs = iconName.split("base64,");
|
const QStringList strs = iconName.split("base64,");
|
||||||
if (strs.size() == 2)
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// load pixmap from File
|
// load pixmap from File
|
||||||
if (QFile::exists(iconName)) {
|
if (QFile::exists(iconName)) {
|
||||||
pixmap = QPixmap(iconName);
|
pix = QPixmap(iconName);
|
||||||
if (!pixmap.isNull())
|
if (!pix.isNull())
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
icon = QIcon::fromTheme(iconName);
|
// 重新从主题中获取一次
|
||||||
if (icon.isNull()) {
|
if (reObtain)
|
||||||
//手动更新图标缓存
|
icon = getIcon(iconName);
|
||||||
system("gtk-update-icon-cache /usr/share/icons/hicolor/");
|
else
|
||||||
|
|
||||||
icon = QIcon::fromTheme(iconName);
|
icon = QIcon::fromTheme(iconName);
|
||||||
}
|
|
||||||
|
|
||||||
if(icon.isNull()) {
|
if(icon.isNull()) {
|
||||||
icon = QIcon::fromTheme("application-x-desktop");
|
icon = QIcon::fromTheme("application-x-desktop");
|
||||||
|
ret = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// load pixmap from Icon-Theme
|
// load pixmap from Icon-Theme
|
||||||
const int fakeSize = std::max(48, s); // cannot use 16x16, cause 16x16 is label icon
|
const int fakeSize = std::max(48, s); // cannot use 16x16, cause 16x16 is label icon
|
||||||
pixmap = icon.pixmap(QSize(fakeSize, fakeSize));
|
pix = icon.pixmap(QSize(fakeSize, fakeSize));
|
||||||
if (!pixmap.isNull())
|
if (!pix.isNull())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// fallback to a Default pixmap
|
// fallback to a Default pixmap
|
||||||
pixmap = QPixmap(":/icons/resources/application-x-desktop.svg");
|
pix = QPixmap(":/icons/resources/application-x-desktop.svg");
|
||||||
if (!pixmap.isNull())
|
if (!pix.isNull())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
Q_UNREACHABLE();
|
Q_UNREACHABLE();
|
||||||
@ -164,12 +188,13 @@ const QPixmap ThemeAppIcon::getIcon(const QString iconName, const int size, cons
|
|||||||
} while (false);
|
} while (false);
|
||||||
|
|
||||||
if (!key.isEmpty()) {
|
if (!key.isEmpty()) {
|
||||||
QPixmapCache::insert(key, pixmap);
|
QPixmapCache::insert(key, pix);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pixmap.size().width() != s) {
|
if (pix.size().width() != s) {
|
||||||
pixmap = pixmap.scaled(s, s, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
pix = pix.scaled(s, s, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||||
}
|
}
|
||||||
pixmap.setDevicePixelRatio(ratio);
|
pix.setDevicePixelRatio(ratio);
|
||||||
return pixmap;
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,8 @@ public:
|
|||||||
explicit ThemeAppIcon(QObject *parent = 0);
|
explicit ThemeAppIcon(QObject *parent = 0);
|
||||||
~ThemeAppIcon();
|
~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
|
#endif // THEMEAPPICON_H
|
||||||
|
@ -34,6 +34,7 @@ add_library(${PLUGIN_NAME} SHARED ${SRCS} tray.qrc)
|
|||||||
set_target_properties(${PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../)
|
set_target_properties(${PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../)
|
||||||
target_include_directories(${PLUGIN_NAME} PUBLIC ${DtkWidget_INCLUDE_DIRS}
|
target_include_directories(${PLUGIN_NAME} PUBLIC ${DtkWidget_INCLUDE_DIRS}
|
||||||
${Qt5DBus_INCLUDE_DIRS}
|
${Qt5DBus_INCLUDE_DIRS}
|
||||||
|
${Qt5Gui_PRIVATE_INCLUDE_DIRS}
|
||||||
${XCB_LIBS_INCLUDE_DIRS}
|
${XCB_LIBS_INCLUDE_DIRS}
|
||||||
${DDE-Network-Utils_INCLUDE_DIRS}
|
${DDE-Network-Utils_INCLUDE_DIRS}
|
||||||
${DFrameworkDBus_INCLUDE_DIRS}
|
${DFrameworkDBus_INCLUDE_DIRS}
|
||||||
|
@ -542,7 +542,7 @@ QPixmap SNITrayWidget::newIconPixmap(IconType iconType)
|
|||||||
// so, it should be the last fallback
|
// so, it should be the last fallback
|
||||||
if (!iconName.isEmpty()) {
|
if (!iconName.isEmpty()) {
|
||||||
// ThemeAppIcon::getIcon 会处理高分屏缩放问题
|
// ThemeAppIcon::getIcon 会处理高分屏缩放问题
|
||||||
pixmap = ThemeAppIcon::getIcon(iconName, IconSize, devicePixelRatioF());
|
ThemeAppIcon::getIcon(pixmap, iconName, IconSize, devicePixelRatioF());
|
||||||
if (!pixmap.isNull()) {
|
if (!pixmap.isNull()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -44,11 +44,18 @@ void Ut_ThemeAppIcon::TearDown()
|
|||||||
TEST_F(Ut_ThemeAppIcon, getIcon_test)
|
TEST_F(Ut_ThemeAppIcon, getIcon_test)
|
||||||
{
|
{
|
||||||
ThemeAppIcon appIcon;
|
ThemeAppIcon appIcon;
|
||||||
const QPixmap &pix1 = appIcon.getIcon("", 50, 1.0);
|
QPixmap pix1;
|
||||||
|
appIcon.getIcon(pix1, "", 50, 1.0);
|
||||||
ASSERT_FALSE(pix1.isNull());
|
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());
|
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());
|
ASSERT_FALSE(pix3.isNull());
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user