Skip to content

Commit

Permalink
feat: Move notification server to worker thread
Browse files Browse the repository at this point in the history
Move notification server to other thread to avoid blocking gui
thread.
notification server has a DB connection to update DataBase, and
it provids update's interface for other applets, notification center
and notification bubble have a default DB connection, then only
query data by DBAccessor.
Add Mutex when getting app infomations, because those interface is
exposed by notification server.

task: https://pms.uniontech.com/task-view-365219.html
  • Loading branch information
18202781743 authored and deepin-bot[bot] committed Oct 15, 2024
1 parent 58e945c commit b9e2667
Show file tree
Hide file tree
Showing 10 changed files with 165 additions and 66 deletions.
2 changes: 2 additions & 0 deletions panels/notification/center/NotifyItemContent.qml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ NotifyItem {
right: parent.right
rightMargin: -width / 2
}
width: 20
height: 20
contentItem: Loader {
active: root.closeVisible || closePlaceHolder.hovered || closePlaceHolder.activeFocus || activeFocus
sourceComponent: SettingActionButton {
Expand Down
59 changes: 58 additions & 1 deletion panels/notification/center/notificationcenterpanel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,51 @@
#include "notificationcenterproxy.h"
#include "notifyaccessor.h"
#include "dbaccessor.h"
#include "pluginfactory.h"

#include <pluginfactory.h>
#include <pluginloader.h>
#include <applet.h>
#include <containment.h>

#include <QQueue>
#include <QDBusConnection>
#include <QDBusInterface>
#include <QLoggingCategory>

DS_USE_NAMESPACE

namespace notification {
Q_LOGGING_CATEGORY(notificationCenterLog, "dde.shell.notificationcenter")

static const QString DDENotifyDBusServer = "org.deepin.dde.Notification1";
static const QString DDENotifyDBusInterface = "org.deepin.dde.Notification1";
static const QString DDENotifyDBusPath = "/org/deepin/dde/Notification1";

static QDBusInterface notifyCenterInterface()
{
return QDBusInterface(DDENotifyDBusServer, DDENotifyDBusPath, DDENotifyDBusInterface);
}
static QList<DApplet *> appletList(const QString &pluginId)
{
QList<DApplet *> ret;
auto rootApplet = DPluginLoader::instance()->rootApplet();
auto root = qobject_cast<DContainment *>(rootApplet);

QQueue<DContainment *> containments;
containments.enqueue(root);
while (!containments.isEmpty()) {
DContainment *containment = containments.dequeue();
for (const auto applet : containment->applets()) {
if (auto item = qobject_cast<DContainment *>(applet)) {
containments.enqueue(item);
}
if (applet->pluginId() == pluginId)
ret << applet;
}
}
return ret;
}

NotificationCenterPanel::NotificationCenterPanel(QObject *parent)
: DPanel(parent)
, m_proxy(new NotificationCenterProxy(this))
Expand Down Expand Up @@ -47,6 +83,27 @@ bool NotificationCenterPanel::init()
auto accessor = notification::DBAccessor::instance();
notifycenter::NotifyAccessor::instance()->setDataAccessor(accessor);

auto applets = appletList("org.deepin.ds.notificationserver");
bool valid = false;
if (!applets.isEmpty()) {
if (auto server = applets.first()) {
valid = QObject::connect(server,
SIGNAL(notificationStateChanged(qint64, int)),
notifycenter::NotifyAccessor::instance(),
SLOT(onReceivedRecordStateChanged(qint64, int)),
Qt::QueuedConnection);
notifycenter::NotifyAccessor::instance()->setDataUpdater(server);
}
} else {
// old interface by dbus
auto connection = QDBusConnection::sessionBus();
valid = connection.connect(DDENotifyDBusServer, DDENotifyDBusPath, DDENotifyDBusInterface,
"RecordAdded", this, SLOT(onReceivedRecord(const QString &)));
}
if (!valid) {
qWarning() << "NotifyConnection is invalid, and can't receive RecordAdded signal.";
}

return true;
}

Expand Down
81 changes: 22 additions & 59 deletions panels/notification/center/notifyaccessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,36 +11,22 @@
#include <QDBusPendingReply>
#include <QProcess>
#include <QDBusReply>
#include <QQueue>

#include <DConfig>

#include <pluginloader.h>
#include <applet.h>
#include <containment.h>

#include "dataaccessor.h"

DS_USE_NAMESPACE
DCORE_USE_NAMESPACE

namespace notifycenter {
namespace {
Q_LOGGING_CATEGORY(notifyLog, "notify")
}

static const QString DDENotifyDBusServer = "org.deepin.dde.Notification1";
static const QString DDENotifyDBusInterface = "org.deepin.dde.Notification1";
static const QString DDENotifyDBusPath = "/org/deepin/dde/Notification1";
static const uint ShowNotificationTop = 7;
static const QString InvalidApp {"DS-Invalid-Apps"};
static const QStringList InvalidPinnedApps {InvalidApp};

static QDBusInterface notifyCenterInterface()
{
return QDBusInterface(DDENotifyDBusServer, DDENotifyDBusPath, DDENotifyDBusInterface);
}

static QDBusInterface controlCenterInterface()
{
return QDBusInterface("org.deepin.dde.ControlCenter1",
Expand All @@ -62,50 +48,9 @@ class EventFilter : public QObject
}
};

static QList<DApplet *> appletList(const QString &pluginId)
{
QList<DApplet *> ret;
auto rootApplet = DPluginLoader::instance()->rootApplet();
auto root = qobject_cast<DContainment *>(rootApplet);

QQueue<DContainment *> containments;
containments.enqueue(root);
while (!containments.isEmpty()) {
DContainment *containment = containments.dequeue();
for (const auto applet : containment->applets()) {
if (auto item = qobject_cast<DContainment *>(applet)) {
containments.enqueue(item);
}
if (applet->pluginId() == pluginId)
ret << applet;
}
}
return ret;
}

NotifyAccessor::NotifyAccessor(QObject *parent)
: m_pinnedApps(InvalidPinnedApps)
{
auto applets = appletList("org.deepin.ds.notificationserver");
bool valid = false;
if (!applets.isEmpty()) {
if (auto server = applets.first()) {
valid = QObject::connect(server,
SIGNAL(notificationStateChanged(qint64, int)),
this,
SLOT(onReceivedRecordStateChanged(qint64, int)),
Qt::QueuedConnection);
}
} else {
// old interface by dbus
auto connection = QDBusConnection::sessionBus();
valid = connection.connect(DDENotifyDBusServer, DDENotifyDBusPath, DDENotifyDBusInterface,
"RecordAdded", this, SLOT(onReceivedRecord(const QString &)));
}
if (!valid) {
qWarning() << "NotifyConnection is invalid, and can't receive RecordAdded signal.";
}

if (!qEnvironmentVariableIsEmpty("DS_NOTIFICATION_DEBUG")) {
const int value = qEnvironmentVariableIntValue("DS_NOTIFICATION_DEBUG");
m_debugging = value;
Expand Down Expand Up @@ -141,6 +86,11 @@ void NotifyAccessor::setDataAccessor(DataAccessor *accessor)
m_accessor = accessor;
}

void NotifyAccessor::setDataUpdater(QObject *updater)
{
m_dataUpdater = updater;
}

NotifyEntity NotifyAccessor::fetchEntity(qint64 id) const
{
qDebug(notifyLog) << "Fetch entity" << id;
Expand Down Expand Up @@ -179,22 +129,35 @@ QStringList NotifyAccessor::fetchApps(int maxCount) const
void NotifyAccessor::removeEntity(qint64 id)
{
qDebug(notifyLog) << "Remove notify" << id;

m_accessor->removeEntity(id);
if (m_dataUpdater) {
QMetaObject::invokeMethod(m_dataUpdater, "removeNotification", Qt::DirectConnection,
Q_ARG(qint64, id));
} else {
m_accessor->removeEntity(id);
}
}

void NotifyAccessor::removeEntityByApp(const QString &appName)
{
qDebug(notifyLog) << "Remove notifies for the application" << appName;

m_accessor->removeEntityByApp(appName);
if (m_dataUpdater) {
QMetaObject::invokeMethod(m_dataUpdater, "removeNotifications", Qt::DirectConnection,
Q_ARG(const QString &, appName));
} else {
m_accessor->removeEntityByApp(appName);
}
}

void NotifyAccessor::clear()
{
qDebug(notifyLog) << "Remove all notify";

m_accessor->clear();
if (m_dataUpdater) {
QMetaObject::invokeMethod(m_dataUpdater, "removeNotifications", Qt::DirectConnection);
} else {
m_accessor->clear();
}
}

// don't need to emit ActionInvoked of protocol.
Expand Down
2 changes: 2 additions & 0 deletions panels/notification/center/notifyaccessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class NotifyAccessor : public QObject
static NotifyAccessor *create(QQmlEngine *, QJSEngine *);

void setDataAccessor(DataAccessor *accessor);
void setDataUpdater(QObject *updater);

void invokeAction(const NotifyEntity &entity, const QString &actionId);
void pinApplication(const QString &appName, bool pin);
Expand Down Expand Up @@ -73,6 +74,7 @@ private slots:

private:
DataAccessor *m_accessor = nullptr;
QObject *m_dataUpdater = nullptr;
QStringList m_pinnedApps;
QStringList m_apps;
bool m_debugging = false;
Expand Down
25 changes: 23 additions & 2 deletions panels/notification/server/notificationmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace notification {
Q_LOGGING_CATEGORY(notifyServerLog, "dde.shell.notification.server")

static const uint NoReplacesId = 0;
const int DefaultTimeOutMSecs = 5000;
static const int DefaultTimeOutMSecs = 5000;
static const QString NotificationsDBusService = "org.freedesktop.Notifications";
static const QString NotificationsDBusPath = "/org/freedesktop/Notifications";
static const QString DDENotifyDBusServer = "org.deepin.dde.Notification1";
Expand Down Expand Up @@ -58,7 +58,7 @@ static QList<DApplet *> appletList(const QString &pluginId)

NotificationManager::NotificationManager(QObject *parent)
: QObject(parent)
, m_persistence(DBAccessor::instance())
, m_persistence(new DBAccessor("Manager"))
, m_setting(new NotificationSetting(this))
, m_userSessionManager(new UserSessionManager(SessionDBusService, SessionDaemonDBusPath, QDBusConnection::sessionBus(), this))
, m_pendingTimeout(new QTimer(this))
Expand Down Expand Up @@ -137,6 +137,27 @@ void NotificationManager::notificationReplaced(qint64 id)
updateEntityProcessed(id, NotifyEntity::Closed);
}

void NotificationManager::removeNotification(qint64 id)
{
m_persistence->removeEntity(id);

emitRecordCountChanged();
}

void NotificationManager::removeNotifications(const QString &appName)
{
m_persistence->removeEntityByApp(appName);

emitRecordCountChanged();
}

void NotificationManager::removeNotifications()
{
m_persistence->clear();

emitRecordCountChanged();
}

QStringList NotificationManager::GetCapabilities()
{
QStringList result;
Expand Down
4 changes: 4 additions & 0 deletions panels/notification/server/notificationmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ class NotificationManager : public QObject, public QDBusContext
void notificationClosed(qint64 id, uint bubbleId, uint reason);
void notificationReplaced(qint64 id);

void removeNotification(qint64 id);
void removeNotifications(const QString &appName);
void removeNotifications();

Q_SIGNALS:
// Standard Notifications dbus implementation
void ActionInvoked(uint id, const QString &actionKey);
Expand Down
15 changes: 12 additions & 3 deletions panels/notification/server/notificationsetting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,11 @@ void NotificationSetting::setAppValue(const QString &id, AppConfigItem item, con
break;
}

m_appsInfo[id] = info;
m_impl->setValue("appsInfo", m_appsInfo);
{
QMutexLocker locker(&m_appsInfoMutex);
m_appsInfo[id] = info;
m_impl->setValue("appsInfo", m_appsInfo);
}

Q_EMIT appValueChanged(id, item, value);
}
Expand Down Expand Up @@ -210,6 +213,7 @@ NotificationSetting::AppItem NotificationSetting::appItem(const QString &id) con

QList<NotificationSetting::AppItem> NotificationSetting::appItems() const
{
QMutexLocker locker(&(const_cast<NotificationSetting *>(this)->m_appItemsMutex));
if (!m_appItems.isEmpty())
return m_appItems;

Expand Down Expand Up @@ -246,6 +250,7 @@ QList<NotificationSetting::AppItem> NotificationSetting::appItemsImpl() const

QVariantMap NotificationSetting::appInfo(const QString &id) const
{
QMutexLocker locker(&(const_cast<NotificationSetting *>(this)->m_appsInfoMutex));
if (m_appsInfo.contains(InvalidApp)) {
const_cast<NotificationSetting *>(this)->m_appsInfo = m_impl->value("appsInfo").toMap();
}
Expand Down Expand Up @@ -290,11 +295,15 @@ void NotificationSetting::onAppsChanged()
Q_EMIT appRemoved(item.id);
}

m_appItems = current;
{
QMutexLocker locker(&m_appItemsMutex);
m_appItems = current;
}
}

void NotificationSetting::invalidAppItemCached()
{
QMutexLocker locker(&m_appsInfoMutex);
m_appsInfo.clear();
m_appsInfo[InvalidApp] = QVariant();
}
Expand Down
3 changes: 3 additions & 0 deletions panels/notification/server/notificationsetting.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#pragma once

#include <QMutex>
#include <QObject>
#include <QTimer>
#include <QVariantMap>
Expand Down Expand Up @@ -84,7 +85,9 @@ private slots:
Dtk::Core::DConfig *m_impl = nullptr;
QAbstractListModel *m_appAccessor = nullptr;
QList<AppItem> m_appItems;
QMutex m_appItemsMutex;
QVariantMap m_appsInfo;
QMutex m_appsInfoMutex;
QVariantMap m_systemInfo;
};

Expand Down
Loading

0 comments on commit b9e2667

Please sign in to comment.