From ecd666cc800d1b856efdb828b91a3a0145bba9c0 Mon Sep 17 00:00:00 2001 From: Mengci Cai Date: Fri, 27 Feb 2026 13:34:07 +0800 Subject: [PATCH] fix: add wait mechanism for app icons 1. Implemented a pending check mechanism for app icons with absolute paths 2. When an app is added, check if the icon file exists immediately 3. If the file is missing, place the app in a pending queue and start a 1-second timer 4. Periodically check pending items to see if the icon file has become available 5. Added a 60-second timeout to force processing if files never appear 6. This resolves race conditions where app registration happens before icon data is fully synchronized to disk or mounted Log: Added delayed loading mechanism for application icons to handle temporary file unavailability Influence: 1. Install an application where the icon file exists immediately; verify the icon displays instantly 2. Install an application where the icon file is missing at first but appears within 60 seconds; verify the icon displays once the file is detected 3. Install an application with a non-existent icon path; verify the application is processed after the 60-second timeout 4. Test adding multiple applications with delayed icons simultaneously 5. Verify system resource usage and memory cleanup when the timer stops PMS: BUG-347859 --- src/ddeintegration/appmgr.cpp | 87 ++++++++++++++++++++++++++++++++++- src/ddeintegration/appmgr.h | 11 ++++- 2 files changed, 96 insertions(+), 2 deletions(-) diff --git a/src/ddeintegration/appmgr.cpp b/src/ddeintegration/appmgr.cpp index 2492631c..de003166 100644 --- a/src/ddeintegration/appmgr.cpp +++ b/src/ddeintegration/appmgr.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2023-2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: GPL-3.0-or-later @@ -127,7 +127,11 @@ AppMgr::AppMgr(QObject *parent) , m_objectManager(new AppManager1ApplicationObjectManager("org.desktopspec.ApplicationManager1", "/org/desktopspec/ApplicationManager1", QDBusConnection::sessionBus(), this)) + , m_checkTimer(new QTimer(this)) + , m_checkCount(0) { + m_checkTimer->setInterval(3000); // 3 second interval + connect(m_checkTimer, &QTimer::timeout, this, &AppMgr::checkPendingAppItems); initObjectManager(); } @@ -430,6 +434,8 @@ void AppMgr::initObjectManager() qWarning() << "App already exists for the path:" << key; return; } + // Reset check count when new app is added + m_checkCount = 0; if (auto appItem = parseDBus2AppItem(interfacesAndProperties)) { qCDebug(logDdeIntegration) << "App item added, desktopId" << appItem->id; watchingAppItemAdded(key, appItem); @@ -503,6 +509,22 @@ void AppMgr::fetchAppItems() void AppMgr::watchingAppItemAdded(const QString &key, AppItem *appItem) { + // Check if iconName is an absolute path and if the file exists + if (isAbsolutePathIcon(appItem->iconName)) { + QFileInfo fileInfo(appItem->iconName); + if (!fileInfo.exists()) { + // File doesn't exist, add to pending container + m_pendingAppItems[key] = appItem; + + // Start timer if not already running + if (!m_checkTimer->isActive()) { + m_checkTimer->start(); + } + return; + } + } + + // Icon exists or is a system icon, proceed with normal logic m_appItems[key] = appItem; watchingAppItemPropertyChanged(key, appItem); Q_EMIT changed(); @@ -527,6 +549,69 @@ void AppMgr::watchingAppItemRemoved(const QString &key) Q_EMIT changed(); } +void AppMgr::checkPendingAppItems() +{ + m_checkCount++; + if (m_pendingAppItems.isEmpty()) { + m_checkTimer->stop(); + return; + } + + QList> itemsToProcess; + + // Check all pending items + for (auto it = m_pendingAppItems.begin(); it != m_pendingAppItems.end(); ) { + const QString &key = it.key(); + AppItem *appItem = it.value(); + + if (isAbsolutePathIcon(appItem->iconName)) { + QFileInfo fileInfo(appItem->iconName); + if (fileInfo.exists()) { + // File now exists, add to main container + itemsToProcess.append(qMakePair(key, appItem)); + it = m_pendingAppItems.erase(it); + continue; + } + } + ++it; + } + + // Process items whose icons now exist + for (const auto &itemPair : itemsToProcess) { + const QString &key = itemPair.first; + AppItem *appItem = itemPair.second; + + m_appItems[key] = appItem; + watchingAppItemPropertyChanged(key, appItem); + Q_EMIT changed(); + } + + // Check if timeout reached (60 seconds) + if (m_checkCount >= 20 && !m_pendingAppItems.isEmpty()) { + // Force process all remaining pending items + for (auto it = m_pendingAppItems.begin(); it != m_pendingAppItems.end(); ) { + const QString &key = it.key(); + AppItem *appItem = it.value(); + + m_appItems[key] = appItem; + watchingAppItemPropertyChanged(key, appItem); + Q_EMIT changed(); + + it = m_pendingAppItems.erase(it); + } + + m_checkTimer->stop(); + } else if (m_pendingAppItems.isEmpty()) { + m_checkTimer->stop(); + } +} + +bool AppMgr::isAbsolutePathIcon(const QString &iconName) const +{ + // Check if the icon name is an absolute path (starts with /) + return iconName.startsWith('/'); +} + AppMgr *AppMgr::instance() { static AppMgr gInstance; return &gInstance; diff --git a/src/ddeintegration/appmgr.h b/src/ddeintegration/appmgr.h index 64bb231b..1f060883 100644 --- a/src/ddeintegration/appmgr.h +++ b/src/ddeintegration/appmgr.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2023-2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: GPL-3.0-or-later @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include DCORE_BEGIN_NAMESPACE @@ -56,6 +58,9 @@ class AppMgr : public QObject void changed(); void itemDataChanged(const QString &id); +private slots: + void checkPendingAppItems(); + private: void initObjectManager(); void fetchAppItems(); @@ -63,8 +68,12 @@ class AppMgr : public QObject void watchingAppItemRemoved(const QString &key); void watchingAppItemPropertyChanged(const QString &key, AppMgr::AppItem *appItem); void updateAppsLaunchedTimes(const QVariantMap &appsLaunchedTimes); + bool isAbsolutePathIcon(const QString &iconName) const; private: __AppManager1ApplicationObjectManager *m_objectManager; QMap m_appItems; + QMap m_pendingAppItems; + QTimer *m_checkTimer; + int m_checkCount; };