Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add plugin notification #946

Merged
merged 1 commit into from
Jan 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion configs/com.deepin.dde.dock.json
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@
"visibility":"public"
},
"Dock_Quick_Plugins": {
"value": ["power", "network", "shutdown", "show-desktop", "multitasking"],
"value": ["power", "network", "shutdown", "show-desktop", "multitasking", "notification"],
"serial": 0,
"flags": [],
"name": "Quick Plugins show on dock",
Expand Down
1 change: 1 addition & 0 deletions debian/dde-dock.install
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ usr/lib/dde-dock/plugins/quick-trays
usr/lib/dde-dock/plugins/libmultitasking.so
usr/lib/dde-dock/plugins/libshow-desktop.so
usr/lib/dde-dock/plugins/libkeyboard-layout.so
usr/lib/dde-dock/plugins/libnotification.so
usr/share/dsg/configs/dde-dock/
2 changes: 1 addition & 1 deletion frame/window/quickpluginwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1068,5 +1068,5 @@ QPoint QuickDockItem::popupMarkPoint() const

void QuickDockItem::onMenuActionClicked(QAction *action)
{
m_pluginItem->invokedMenuItem(m_itemKey, action->data().toString(), true);
m_pluginItem->invokedMenuItem(m_itemKey, action->data().toString(), action->isCheckable() ? action->isChecked() : true);
}
1 change: 1 addition & 0 deletions plugins/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ add_subdirectory("show-desktop")
add_subdirectory("multitasking")
add_subdirectory("bluetooth")
add_subdirectory("airplane-mode")
add_subdirectory("notification")
28 changes: 28 additions & 0 deletions plugins/notification/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
set(PLUGIN_NAME "notification")
find_package(Qt5 REQUIRED COMPONENTS DBus)
find_package(Dtk REQUIRED COMPONENTS Widget)

add_library(${PLUGIN_NAME} SHARED
notification.h
notification.cpp
notificationplugin.h
notificationplugin.cpp
${CMAKE_SOURCE_DIR}/widgets/tipswidget.h
${CMAKE_SOURCE_DIR}/widgets/tipswidget.cpp
notification.qrc
)
target_compile_definitions(${PLUGIN_NAME} PRIVATE QT_PLUGIN)
set_target_properties(${PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins)

target_include_directories(${PLUGIN_NAME} PRIVATE
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/interfaces>
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/widgets>
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/frame/qtdbusextended>
)

target_link_libraries(${PLUGIN_NAME} PRIVATE
Dtk::Widget
Qt5::DBus
)

install(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION lib/dde-dock/plugins)
Binary file added plugins/notification/icons/notification-off.dci
Binary file not shown.
Binary file added plugins/notification/icons/notification.dci
Binary file not shown.
90 changes: 90 additions & 0 deletions plugins/notification/notification.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#include "notification.h"
#include "constants.h"

#include <QPainter>
#include <QPainterPath>
#include <QMouseEvent>
#include <QApplication>
#include <QIcon>
#include <QDBusInterface>
#include <QDBusReply>
#include <QtConcurrent/QtConcurrent>

#include <DStyle>
#include <DGuiApplicationHelper>

Q_DECLARE_LOGGING_CATEGORY(qLcPluginNotification)

DWIDGET_USE_NAMESPACE;
DCORE_USE_NAMESPACE;
Notification::Notification(QWidget *parent)
: QWidget(parent)
, m_icon(QIcon::fromTheme("notification"))
, m_dbus(nullptr)
, m_dndMode(false)
{
setMinimumSize(PLUGIN_BACKGROUND_MIN_SIZE, PLUGIN_BACKGROUND_MIN_SIZE);
connect(this, &Notification::dndModeChanged, this, &Notification::refreshIcon);
QtConcurrent::run([this](){
m_dbus = new QDBusInterface("org.deepin.dde.Notification1", "/org/deepin/dde/Notification1", "org.deepin.dde.Notification1", QDBusConnection::sessionBus(), this);
// Refresh icon for the first time, cause org.deepin.dde.Notification1 might depend on dock's DBus,
// we should not call org.deepin.dde.Notification1 in the main thread before dock's dbus is initialized.
// Just refresh icon in the other thread.
QDBusReply<QDBusVariant> dnd = m_dbus->call(QLatin1String("GetSystemInfo"), QVariant::fromValue(0u));
if (!dnd.isValid()) {
qCWarning(qLcPluginNotification) << dnd.error();
return ;
}
m_dndMode = dnd.value().variant().toBool();
refreshIcon();
QDBusConnection::sessionBus().connect("org.deepin.dde.Notification1",
"/org/deepin/dde/Notification1",
"org.deepin.dde.Notification1",
"SystemInfoChanged",
this,
SLOT(onSystemInfoChanged(quint32,QDBusVariant))
);
});
}

QIcon Notification::icon() const
{
return m_icon;
}

void Notification::refreshIcon()
{
m_icon = QIcon::fromTheme(m_dndMode ? "notification-off" : "notification");
Q_EMIT iconRefreshed();
}

bool Notification::dndMode() const
{
return m_dndMode;
}

void Notification::setDndMode(bool dnd)
{
if (m_dbus) {
m_dbus->call(QLatin1String("SetSystemInfo"), QVariant::fromValue(0u), QVariant::fromValue(QDBusVariant(dnd)));
}
}

void Notification::paintEvent(QPaintEvent *e)
{
Q_UNUSED(e)
QPainter p(this);
m_icon.paint(&p, rect());
}

void Notification::onSystemInfoChanged(quint32 info, QDBusVariant value)
{
if (info == 0) {
// DND mode
m_dndMode = value.variant().toBool();
Q_EMIT dndModeChanged(m_dndMode);
}
}
44 changes: 44 additions & 0 deletions plugins/notification/notification.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#ifndef NOTIFICATION_H
#define NOTIFICATION_H

#include <DGuiApplicationHelper>

#include <QWidget>
#include <QIcon>
#include <QDBusVariant>
#include <QDBusInterface>

class Notification : public QWidget
{
Q_OBJECT

public:
explicit Notification(QWidget *parent = nullptr);
QIcon icon() const;

bool dndMode() const;
void setDndMode(bool dnd);

Q_SIGNALS:
void iconRefreshed();
void dndModeChanged(bool dnd);

public Q_SLOTS:
void refreshIcon();

private Q_SLOTS:
void onSystemInfoChanged(quint32 info, QDBusVariant value);

protected:
void paintEvent(QPaintEvent *e) override;

private:
QIcon m_icon;
QDBusInterface *m_dbus;
bool m_dndMode;
};

#endif // NOTIFICATION_H
4 changes: 4 additions & 0 deletions plugins/notification/notification.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"api": "2.0.0",
"depends-daemon-dbus-service": "org.deepin.dde.Notification1"
}
6 changes: 6 additions & 0 deletions plugins/notification/notification.qrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<RCC>
<qresource prefix="/dsg/built-in-icons">
<file alias="notification.dci">icons/notification.dci</file>
<file alias="notification-off.dci">icons/notification-off.dci</file>
</qresource>
</RCC>
149 changes: 149 additions & 0 deletions plugins/notification/notificationplugin.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#include "notificationplugin.h"

#include <DGuiApplicationHelper>

#include <QIcon>
#include <QSettings>
#include <QPainter>

Q_LOGGING_CATEGORY(qLcPluginNotification, "dock.plugin.notification")

#define PLUGIN_STATE_KEY "enable"
#define TOGGLE_DND "toggle-dnd"

DGUI_USE_NAMESPACE
using namespace Dock;

NotificationPlugin::NotificationPlugin(QObject *parent)
: QObject(parent)
, m_pluginLoaded(false)
, m_notification(nullptr)
, m_tipsLabel(new TipsWidget)
{
m_tipsLabel->setText(tr("Notification"));
m_tipsLabel->setVisible(false);
m_tipsLabel->setAccessibleName("Notification");
m_tipsLabel->setObjectName("NotificationTipsLabel");
}

QWidget *NotificationPlugin::itemWidget(const QString &itemKey)
{
Q_UNUSED(itemKey)
return m_notification.data();
}

QWidget *NotificationPlugin::itemTipsWidget(const QString &itemKey)
{
Q_UNUSED(itemKey);
return m_tipsLabel.data();
}

void NotificationPlugin::init(PluginProxyInterface *proxyInter)
{
m_proxyInter = proxyInter;

if (!pluginIsDisable()) {
loadPlugin();
}
}

void NotificationPlugin::pluginStateSwitched()
{
m_proxyInter->saveValue(this, PLUGIN_STATE_KEY, pluginIsDisable());
refreshPluginItemsVisible();
}

bool NotificationPlugin::pluginIsDisable()
{
return !(m_proxyInter->getValue(this, PLUGIN_STATE_KEY, true).toBool());
}

const QString NotificationPlugin::itemCommand(const QString &itemKey)
{
Q_UNUSED(itemKey);
return QString("dbus-send --session --print-reply --dest=org.deepin.dde.Widgets1 /org/deepin/dde/Widgets1 org.deepin.dde.Widgets1.Toggle");
}

const QString NotificationPlugin::itemContextMenu(const QString &itemKey)
{
QList<QVariant> items;
QMap<QString, QVariant> toggleDnd;
toggleDnd["itemId"] = TOGGLE_DND;
toggleDnd["itemText"] = tr("Do Not Disturb");
toggleDnd["isCheckable"] = true;
toggleDnd["isActive"] = true;
toggleDnd["checked"] = m_notification->dndMode();
items.push_back(toggleDnd);
QMap<QString, QVariant> menu;
menu["items"] = items;
menu["checkableMenu"] = true;
menu["singleCheck"] = false;
return QJsonDocument::fromVariant(menu).toJson();
}

void NotificationPlugin::invokedMenuItem(const QString &itemKey, const QString &menuId, const bool checked)
{
Q_UNUSED(itemKey)
if (menuId == TOGGLE_DND) {
m_notification->setDndMode(checked);
}
}

int NotificationPlugin::itemSortKey(const QString &itemKey)
{
const QString key = QString("pos_%1_%2").arg(itemKey).arg(Dock::Efficient);
return m_proxyInter->getValue(this, key, 3).toInt();
}

void NotificationPlugin::setSortKey(const QString &itemKey, const int order)
{
const QString key = QString("pos_%1_%2").arg(itemKey).arg(Dock::Efficient);
m_proxyInter->saveValue(this, key, order);
}

void NotificationPlugin::pluginSettingsChanged()
{
refreshPluginItemsVisible();
}

QIcon NotificationPlugin::icon(const DockPart &dockPart, DGuiApplicationHelper::ColorType themeType)
{
Q_UNUSED(themeType)
if (dockPart == DockPart::DCCSetting)
return QIcon::fromTheme("notification");
return m_notification->icon();
}

void NotificationPlugin::loadPlugin()
{
if (m_pluginLoaded) {
return;
}
m_pluginLoaded = true;
m_notification.reset(new Notification);
connect(m_notification.data(), &Notification::iconRefreshed, this, [this]() { m_proxyInter->itemUpdate(this, pluginName()); });
m_proxyInter->itemAdded(this, pluginName());
}

void NotificationPlugin::refreshPluginItemsVisible()
{
if (pluginIsDisable())
{
m_proxyInter->itemRemoved(this, pluginName());
} else {
if (!m_pluginLoaded) {
loadPlugin();
return;
}
m_proxyInter->itemAdded(this, pluginName());
}
}

void NotificationPlugin::refreshIcon(const QString &itemKey)
{
Q_UNUSED(itemKey)
m_notification->refreshIcon();
}
Loading