diff --git a/panels/notification/common/dataaccessor.h b/panels/notification/common/dataaccessor.h index b7f201362..362c76f75 100644 --- a/panels/notification/common/dataaccessor.h +++ b/panels/notification/common/dataaccessor.h @@ -35,6 +35,7 @@ class DataAccessor virtual int fetchEntityCount(const QString &appName, int processedType) const { Q_UNUSED(appName); Q_UNUSED(processedType); return 0; } virtual NotifyEntity fetchLastEntity(const QString &appName, int processedType) { Q_UNUSED(appName); Q_UNUSED(processedType); return {}; } virtual NotifyEntity fetchLastEntity(uint notifyId) { Q_UNUSED(notifyId); return {}; } + virtual QList fetchExpiredEntities(qint64 expiredTime) { Q_UNUSED(expiredTime); return {}; } virtual QList fetchEntities(const QString &appName, int processedType, int maxCount) { Q_UNUSED(appName) diff --git a/panels/notification/common/dataaccessorproxy.cpp b/panels/notification/common/dataaccessorproxy.cpp index efe221041..6bbe83588 100644 --- a/panels/notification/common/dataaccessorproxy.cpp +++ b/panels/notification/common/dataaccessorproxy.cpp @@ -116,6 +116,11 @@ NotifyEntity DataAccessorProxy::fetchLastEntity(uint notifyId) return m_source->fetchLastEntity(notifyId); } +QList DataAccessorProxy::fetchExpiredEntities(qint64 expiredTime) +{ + return m_source->fetchExpiredEntities(expiredTime); +} + QList DataAccessorProxy::fetchEntities(const QString &appName, int processedType, int maxCount) { if (processedType == NotifyEntity::NotProcessed) { diff --git a/panels/notification/common/dataaccessorproxy.h b/panels/notification/common/dataaccessorproxy.h index 764ffc86a..adeda6b8d 100644 --- a/panels/notification/common/dataaccessorproxy.h +++ b/panels/notification/common/dataaccessorproxy.h @@ -31,6 +31,7 @@ class DataAccessorProxy : public DataAccessor virtual int fetchEntityCount(const QString &appName, int processedType) const override; virtual NotifyEntity fetchLastEntity(const QString &appName, int processedType) override; virtual NotifyEntity fetchLastEntity(uint notifyId) override; + virtual QList fetchExpiredEntities(qint64 expiredTime) override; virtual QList fetchEntities(const QString &appName, int processedType, int maxCount) override; virtual QList fetchApps(int maxCount) const override; diff --git a/panels/notification/common/dbaccessor.cpp b/panels/notification/common/dbaccessor.cpp index 1d5d17bf2..ee5a87640 100644 --- a/panels/notification/common/dbaccessor.cpp +++ b/panels/notification/common/dbaccessor.cpp @@ -443,6 +443,32 @@ NotifyEntity DBAccessor::fetchLastEntity(uint notifyId) return {}; } +QList DBAccessor::fetchExpiredEntities(qint64 expiredTime) +{ + BENCHMARK(); + + QMutexLocker locker(&m_mutex); + QSqlQuery query(m_connection); + + QString cmd = QString("SELECT %1 FROM notifications2 WHERE CTime < :expiredTime ORDER BY CTime ASC").arg(EntityFields.join(",")); + query.prepare(cmd); + query.bindValue(":expiredTime", expiredTime); + + if (!query.exec()) { + qWarning(notifyDBLog) << "Query execution error:" << query.lastError().text(); + return {}; + } + + QList expiredEntities; + while (query.next()) { + auto entity = parseEntity(query); + if (entity.isValid()) { + expiredEntities.append(entity); + } + } + return expiredEntities; +} + QList DBAccessor::fetchApps(int maxCount) const { BENCHMARK(); diff --git a/panels/notification/common/dbaccessor.h b/panels/notification/common/dbaccessor.h index 5399120aa..2fe69ed62 100644 --- a/panels/notification/common/dbaccessor.h +++ b/panels/notification/common/dbaccessor.h @@ -37,6 +37,7 @@ class DBAccessor : public DataAccessor NotifyEntity fetchLastEntity(const QString &appName, int processedType) override; QList fetchEntities(const QString &appName, int processedType, int maxCount) override; NotifyEntity fetchLastEntity(uint notifyId) override; + QList fetchExpiredEntities(qint64 expiredTime) override; QList fetchApps(int maxCount) const override; void removeEntity(qint64 id) override; diff --git a/panels/notification/common/memoryaccessor.cpp b/panels/notification/common/memoryaccessor.cpp index 6f8a542fa..ef16e359a 100644 --- a/panels/notification/common/memoryaccessor.cpp +++ b/panels/notification/common/memoryaccessor.cpp @@ -4,6 +4,7 @@ #include "memoryaccessor.h" #include +#include namespace notification { @@ -102,6 +103,24 @@ NotifyEntity MemoryAccessor::fetchLastEntity(uint notifyId) return {}; } +QList MemoryAccessor::fetchExpiredEntities(qint64 expiredTime) +{ + QMutexLocker locker(&m_mutex); + QList expiredEntities; + + for (const auto &entity : m_entities) { + if (entity.cTime() < expiredTime) { + expiredEntities.append(entity); + } + } + + std::sort(expiredEntities.begin(), expiredEntities.end(), [](const NotifyEntity &a, const NotifyEntity &b) { + return a.cTime() < b.cTime(); + }); + + return expiredEntities; +} + QList MemoryAccessor::fetchEntities(const QString &appName, int processedType, int maxCount) { QMutexLocker locker(&m_mutex); diff --git a/panels/notification/common/memoryaccessor.h b/panels/notification/common/memoryaccessor.h index 58a3401ee..c7fbcb6bc 100644 --- a/panels/notification/common/memoryaccessor.h +++ b/panels/notification/common/memoryaccessor.h @@ -27,6 +27,7 @@ class MemoryAccessor : public DataAccessor virtual int fetchEntityCount(const QString &appName, int processedType) const override; virtual NotifyEntity fetchLastEntity(const QString &appName, int processedType) override; virtual NotifyEntity fetchLastEntity(uint notifyId) override; + virtual QList fetchExpiredEntities(qint64 expiredTime) override; virtual QList fetchEntities(const QString &appName, int processedType, int maxCount) override; virtual QList fetchApps(int maxCount) const override; diff --git a/panels/notification/common/notifyentity.h b/panels/notification/common/notifyentity.h index 38305dc51..a4d67759d 100644 --- a/panels/notification/common/notifyentity.h +++ b/panels/notification/common/notifyentity.h @@ -30,6 +30,7 @@ class NotifyEntity Dismissed = 2, Closed = 3, Unknown = 4, + Timeout = 5, }; NotifyEntity(); diff --git a/panels/notification/server/configs/org.deepin.dde.shell.notification.json b/panels/notification/server/configs/org.deepin.dde.shell.notification.json index 26d933ea3..d56239c4d 100644 --- a/panels/notification/server/configs/org.deepin.dde.shell.notification.json +++ b/panels/notification/server/configs/org.deepin.dde.shell.notification.json @@ -144,6 +144,17 @@ "description[zh_CN]": "应用名称映射", "permissions": "readwrite", "visibility": "private" + }, + "notificationCleanupDays": { + "value": 7, + "serial": 0, + "flags": [], + "name": "notification cleanup days", + "name[zh_CN]": "通知清理天数", + "description": "Number of days after which notifications will be automatically cleaned up", + "description[zh_CN]": "通知自动清理的天数,超过此天数的通知将被自动删除", + "permissions": "readwrite", + "visibility": "public" } } } diff --git a/panels/notification/server/notificationmanager.cpp b/panels/notification/server/notificationmanager.cpp index 38c0d3f27..8a1db1267 100644 --- a/panels/notification/server/notificationmanager.cpp +++ b/panels/notification/server/notificationmanager.cpp @@ -49,9 +49,14 @@ NotificationManager::NotificationManager(QObject *parent) , m_persistence(DataAccessorProxy::instance()) , m_setting(new NotificationSetting(this)) , m_pendingTimeout(new QTimer(this)) + , m_cleanupTimer(new QTimer(this)) { m_pendingTimeout->setSingleShot(true); connect(m_pendingTimeout, &QTimer::timeout, this, &NotificationManager::onHandingPendingEntities); + + m_cleanupTimer->setInterval(1000); + connect(m_cleanupTimer, &QTimer::timeout, this, &NotificationManager::onCleanupExpiredNotifications); + m_cleanupTimer->start(); DataAccessorProxy::instance()->setSource(DBAccessor::instance()); @@ -77,7 +82,9 @@ NotificationManager::NotificationManager(QObject *parent) m_systemApps = config->value("systemApps").toStringList(); // TODO temporary fix for AppNamesMap m_appNamesMap = config->value("AppNamesMap").toMap(); - + if(!config->value("notificationCleanupDays").isNull()) { + m_cleanupDays = config->value("notificationCleanupDays").toInt(); + } if (QStringLiteral("wayland") != QGuiApplication::platformName()) { initScreenLockedState(); } @@ -457,6 +464,8 @@ void NotificationManager::updateEntityProcessed(qint64 id, uint reason) if (entity.isValid()) { if ((reason == NotifyEntity::Closed || reason == NotifyEntity::Dismissed) && entity.processedType() == NotifyEntity::NotProcessed) { entity.setProcessedType(NotifyEntity::Removed); + } else if (reason == NotifyEntity::Timeout) { + entity.setProcessedType(NotifyEntity::Removed); } else { entity.setProcessedType(NotifyEntity::Processed); } @@ -675,4 +684,14 @@ void NotificationManager::onScreenLockedChanged(bool screenLocked) m_screenLocked = screenLocked; } +void NotificationManager::onCleanupExpiredNotifications() +{ + const qint64 cutoffTime = QDateTime::currentDateTime().addDays(-m_cleanupDays).toMSecsSinceEpoch(); + auto expiredEntities = m_persistence->fetchExpiredEntities(cutoffTime); + + for (const auto &entity : expiredEntities) { + notificationClosed(entity.id(), entity.bubbleId(), NotifyEntity::Timeout); + } +} + } // notification diff --git a/panels/notification/server/notificationmanager.h b/panels/notification/server/notificationmanager.h index efa114ed4..35c2fb798 100644 --- a/panels/notification/server/notificationmanager.h +++ b/panels/notification/server/notificationmanager.h @@ -83,6 +83,7 @@ private slots: void onHandingPendingEntities(); void removePendingEntity(const NotifyEntity &entity); void onScreenLockedChanged(bool); + void onCleanupExpiredNotifications(); private: uint m_replacesCount = 0; @@ -91,10 +92,12 @@ private slots: DataAccessor *m_persistence = nullptr; NotificationSetting *m_setting = nullptr; QTimer *m_pendingTimeout = nullptr; + QTimer *m_cleanupTimer = nullptr; qint64 m_lastTimeoutPoint = std::numeric_limits::max(); QMultiHash m_pendingTimeoutEntities; QStringList m_systemApps; QMap m_appNamesMap; + int m_cleanupDays = 7; }; } // notification