diff --git a/configs/com.deepin.dde.dock.json b/configs/com.deepin.dde.dock.json index 45c0f4b3e..0034a409a 100644 --- a/configs/com.deepin.dde.dock.json +++ b/configs/com.deepin.dde.dock.json @@ -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", diff --git a/debian/dde-dock.install b/debian/dde-dock.install index f10faa542..87a5d51b9 100644 --- a/debian/dde-dock.install +++ b/debian/dde-dock.install @@ -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/ diff --git a/frame/window/quickpluginwindow.cpp b/frame/window/quickpluginwindow.cpp index 7e7bf1e1f..9fa95a0cb 100644 --- a/frame/window/quickpluginwindow.cpp +++ b/frame/window/quickpluginwindow.cpp @@ -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); } diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 074adc668..78d46d085 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -12,3 +12,4 @@ add_subdirectory("show-desktop") add_subdirectory("multitasking") add_subdirectory("bluetooth") add_subdirectory("airplane-mode") +add_subdirectory("notification") diff --git a/plugins/notification/CMakeLists.txt b/plugins/notification/CMakeLists.txt new file mode 100644 index 000000000..02201f5f0 --- /dev/null +++ b/plugins/notification/CMakeLists.txt @@ -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 + $ + $ + $ +) + +target_link_libraries(${PLUGIN_NAME} PRIVATE + Dtk::Widget + Qt5::DBus +) + +install(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION lib/dde-dock/plugins) diff --git a/plugins/notification/icons/notification-off.dci b/plugins/notification/icons/notification-off.dci new file mode 100644 index 000000000..646b32e60 Binary files /dev/null and b/plugins/notification/icons/notification-off.dci differ diff --git a/plugins/notification/icons/notification.dci b/plugins/notification/icons/notification.dci new file mode 100644 index 000000000..2f5b99480 Binary files /dev/null and b/plugins/notification/icons/notification.dci differ diff --git a/plugins/notification/notification.cpp b/plugins/notification/notification.cpp new file mode 100644 index 000000000..157d1cc86 --- /dev/null +++ b/plugins/notification/notification.cpp @@ -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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +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 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); + } +} diff --git a/plugins/notification/notification.h b/plugins/notification/notification.h new file mode 100644 index 000000000..9a7970aee --- /dev/null +++ b/plugins/notification/notification.h @@ -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 + +#include +#include +#include +#include + +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 diff --git a/plugins/notification/notification.json b/plugins/notification/notification.json new file mode 100644 index 000000000..4c9431cc3 --- /dev/null +++ b/plugins/notification/notification.json @@ -0,0 +1,4 @@ +{ + "api": "2.0.0", + "depends-daemon-dbus-service": "org.deepin.dde.Notification1" +} diff --git a/plugins/notification/notification.qrc b/plugins/notification/notification.qrc new file mode 100644 index 000000000..03d62d7c9 --- /dev/null +++ b/plugins/notification/notification.qrc @@ -0,0 +1,6 @@ + + + icons/notification.dci + icons/notification-off.dci + + diff --git a/plugins/notification/notificationplugin.cpp b/plugins/notification/notificationplugin.cpp new file mode 100644 index 000000000..31cde80c5 --- /dev/null +++ b/plugins/notification/notificationplugin.cpp @@ -0,0 +1,149 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later +#include "notificationplugin.h" + +#include + +#include +#include +#include + +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 items; + QMap 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 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(); +} diff --git a/plugins/notification/notificationplugin.h b/plugins/notification/notificationplugin.h new file mode 100644 index 000000000..184113c72 --- /dev/null +++ b/plugins/notification/notificationplugin.h @@ -0,0 +1,53 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later +#ifndef NOTIFICATIONPLUGIN_H +#define NOTIFICATIONPLUGIN_H +#include "pluginsiteminterface.h" +#include "notification.h" +#include "tipswidget.h" + +class NotificationPlugin : public QObject, public PluginsItemInterface +{ + Q_OBJECT + Q_INTERFACES(PluginsItemInterface) + Q_PLUGIN_METADATA(IID "com.deepin.dock.PluginsItemInterface" FILE "notification.json") + +public: + explicit NotificationPlugin(QObject *parent = nullptr); + const QString pluginName() const override { return "notification"; } + const QString pluginDisplayName() const override { return tr("Notification"); } + PluginMode status() const override { return PluginMode::Active; } + PluginType type() override { return PluginType::Normal; } + PluginFlags flags() const override { return PluginFlag::Type_Common | PluginFlag::Attribute_CanSetting; } + QString description() const override { return pluginDisplayName(); } + bool pluginIsAllowDisable() override { return true; } + + void init(PluginProxyInterface *proxyInter) override; + void pluginStateSwitched() override; + bool pluginIsDisable() override; + + QWidget *itemWidget(const QString &itemKey) override; + QWidget *itemTipsWidget(const QString &itemKey) override; + const QString itemCommand(const QString &itemKey) override; + const QString itemContextMenu(const QString &itemKey) override; + void invokedMenuItem(const QString &itemKey, const QString &menuId, const bool checked) override; + + int itemSortKey(const QString &itemKey) override; + void setSortKey(const QString &itemKey, const int order) override; + + void pluginSettingsChanged() override; + QIcon icon(const DockPart &dockPart, DGuiApplicationHelper::ColorType themeType) override; + void refreshIcon(const QString &itemKey) override; + +private: + void loadPlugin(); + void refreshPluginItemsVisible(); + +private: + bool m_pluginLoaded; + QScopedPointer m_notification; + QScopedPointer m_tipsLabel; +}; + +#endif // NOTIFICATIONPLUGIN_H diff --git a/translations/dde-dock.ts b/translations/dde-dock.ts index 843b3bcdd..f6f6ef44f 100644 --- a/translations/dde-dock.ts +++ b/translations/dde-dock.ts @@ -139,26 +139,18 @@ - DateTimeDisplayer - - 12-hour time - 12-hour time - + DBusHandler - 24-hour time - 24-hour time + failed to dock + failed to dock - Time settings - Time settings + Unrecognized application, unable to dock + Unrecognized application, unable to dock - DatetimePlugin - - Datetime - Datetime - + DateTimeDisplayer 12-hour time 12-hour time @@ -172,20 +164,6 @@ Time settings - - DisplayPlugin - - Brightness - - - - - DisplayPlugin - - Brightness - Brightness - - DevCollaborationWidget @@ -212,6 +190,13 @@ This action cannot be restored + + DisplayPlugin + + Brightness + Brightness + + DisplaySettingWidget @@ -226,6 +211,33 @@ The plugin %1 is not compatible with the system. + + Entry + + Open + Open + + + Close All + Close All + + + Force Quit + Force Quit + + + Dock + Dock + + + Undock + Undock + + + All Windows + All Windows + + HomeMonitorPlugin @@ -244,6 +256,13 @@ Launcher + + MediaPlayerModel + + Unknown + + + MenuWorker @@ -310,6 +329,17 @@ Undock + + NotificationPlugin + + Notification + Notification + + + Do Not Disturb + Do Not Disturb + + OnboardPlugin @@ -473,42 +503,4 @@ The Dock is in safe mode, please exit to show it properly - - Entry - - Open - Open - - - Close All - Close All - - - Force Quit - Force Quit - - - Dock - Dock - - - Undock - Undock - - - All Windows - All Windows - - - - DBusHandler - - failed to dock - failed to dock - - - Unrecognized application, unable to dock - Unrecognized application, unable to dock - - diff --git a/translations/dde-dock_en_US.ts b/translations/dde-dock_en_US.ts index 04532a924..00154c336 100644 --- a/translations/dde-dock_en_US.ts +++ b/translations/dde-dock_en_US.ts @@ -301,6 +301,17 @@ Undock + + NotificationPlugin + + Notification + Notification + + + Do Not Disturb + Do Not Disturb + + OnboardPlugin @@ -491,4 +502,4 @@ All Windows - \ No newline at end of file + diff --git a/translations/dde-dock_zh_CN.ts b/translations/dde-dock_zh_CN.ts index 1784a8d67..78de7a197 100644 --- a/translations/dde-dock_zh_CN.ts +++ b/translations/dde-dock_zh_CN.ts @@ -329,6 +329,17 @@ 移除驻留 + + NotificationPlugin + + Notification + 通知 + + + Do Not Disturb + 勿扰模式 + + OnboardPlugin