diff --git a/debian/dde-dock.install b/debian/dde-dock.install index a5406de26..a6744ffca 100644 --- a/debian/dde-dock.install +++ b/debian/dde-dock.install @@ -9,5 +9,6 @@ usr/lib/dde-dock/plugins/liboverlay-warning.so usr/lib/dde-dock/plugins/system-trays usr/lib/dde-dock/plugins/libmultitasking.so usr/lib/dde-dock/plugins/libshow-desktop.so +usr/lib/dde-dock/plugins/libnotifications.so usr/share etc/dde-dock diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index b98574c6c..b7314426d 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -12,3 +12,4 @@ add_subdirectory("onboard") add_subdirectory("overlay-warning") add_subdirectory("show-desktop") add_subdirectory("multitasking") +add_subdirectory("notifications") diff --git a/plugins/notifications/CMakeLists.txt b/plugins/notifications/CMakeLists.txt new file mode 100644 index 000000000..b10c36329 --- /dev/null +++ b/plugins/notifications/CMakeLists.txt @@ -0,0 +1,32 @@ + +set(PLUGIN_NAME "notifications") + +project(${PLUGIN_NAME}) + +# Sources files +file(GLOB_RECURSE SRCS "*.h" "*.cpp" "../../widgets/*.h" "../../widgets/*.cpp") + +find_package(PkgConfig REQUIRED) +find_package(Qt5Widgets REQUIRED) +find_package(Qt5Svg REQUIRED) +find_package(Qt5DBus REQUIRED) +find_package(DtkWidget REQUIRED) + +if (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64") + add_definitions("-DDISABLE_POWER_OPTIONS") +endif() + +add_definitions("${QT_DEFINITIONS} -DQT_PLUGIN") +add_library(${PLUGIN_NAME} SHARED ${SRCS} resources.qrc) +set_target_properties(${PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../) +target_include_directories(${PLUGIN_NAME} PUBLIC ${DtkWidget_INCLUDE_DIRS} + ${Qt5DBus_INCLUDE_DIRS} + ../../interfaces) +target_link_libraries(${PLUGIN_NAME} PRIVATE + ${DtkWidget_LIBRARIES} + ${Qt5Widgets_LIBRARIES} + ${Qt5Svg_LIBRARIES} + ${Qt5DBus_LIBRARIES} +) + +install(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION lib/dde-dock/plugins) diff --git a/plugins/notifications/notifications.json b/plugins/notifications/notifications.json new file mode 100644 index 000000000..ad498eeb3 --- /dev/null +++ b/plugins/notifications/notifications.json @@ -0,0 +1,3 @@ +{ + "api": "1.1.1" +} diff --git a/plugins/notifications/notificationsplugin.cpp b/plugins/notifications/notificationsplugin.cpp new file mode 100644 index 000000000..937a024cf --- /dev/null +++ b/plugins/notifications/notificationsplugin.cpp @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. + * + * Author: sbw + * + * Maintainer: sbw + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "notificationsplugin.h" + +#include +#include +#include + +#define PLUGIN_STATE_KEY "enable" + +NotificationsPlugin::NotificationsPlugin(QObject *parent) + : QObject(parent) + , m_pluginLoaded(false) + , m_tipsLabel(new TipsWidget) +{ + m_tipsLabel->setVisible(false); + getNotifyInterface(); +} + +QDBusInterface *NotificationsPlugin::getNotifyInterface() +{ + if (!m_interface && QDBusConnection::sessionBus().interface()->isServiceRegistered("com.deepin.dde.Notification")) + m_interface = new QDBusInterface("com.deepin.dde.Notification", "/com/deepin/dde/Notification", "com.deepin.dde.Notification"); + + return m_interface; +} + +const QString NotificationsPlugin::pluginName() const +{ + return "notifications"; +} + +const QString NotificationsPlugin::pluginDisplayName() const +{ + return tr("Notifications"); +} + +QWidget *NotificationsPlugin::itemWidget(const QString &itemKey) +{ + Q_UNUSED(itemKey); + + return m_itemWidget; +} + +QWidget *NotificationsPlugin::itemTipsWidget(const QString &itemKey) +{ + Q_UNUSED(itemKey); + + if (!getNotifyInterface()) + return nullptr; + + QDBusMessage msg = m_interface->call("recordCount"); + uint recordCount = msg.arguments()[0].toUInt(); + + if (recordCount) + m_tipsLabel->setText(QString(tr("%1 Notifications")).arg(recordCount)); + else + m_tipsLabel->setText(tr("Notifications")); + + return m_tipsLabel; +} + +void NotificationsPlugin::init(PluginProxyInterface *proxyInter) +{ + m_proxyInter = proxyInter; + + if (!pluginIsDisable()) { + loadPlugin(); + } +} + +void NotificationsPlugin::pluginStateSwitched() +{ + m_proxyInter->saveValue(this, PLUGIN_STATE_KEY, !m_proxyInter->getValue(this, PLUGIN_STATE_KEY, true).toBool()); + + refreshPluginItemsVisible(); +} + +bool NotificationsPlugin::pluginIsDisable() +{ + return !m_proxyInter->getValue(this, PLUGIN_STATE_KEY, true).toBool(); +} + +const QString NotificationsPlugin::itemCommand(const QString &itemKey) +{ + Q_UNUSED(itemKey); + + if (getNotifyInterface()) + m_interface->call("Toggle"); + + return ""; +} + +void NotificationsPlugin::displayModeChanged(const Dock::DisplayMode displayMode) +{ + Q_UNUSED(displayMode); + + if (!pluginIsDisable()) { + m_itemWidget->update(); + } +} + +int NotificationsPlugin::itemSortKey(const QString &itemKey) +{ + Dock::DisplayMode mode = displayMode(); + const QString key = QString("pos_%1_%2").arg(itemKey).arg(mode); + + if (mode == Dock::DisplayMode::Fashion) { + return m_proxyInter->getValue(this, key, 2).toInt(); + } else { + return m_proxyInter->getValue(this, key, 5).toInt(); + } +} + +void NotificationsPlugin::setSortKey(const QString &itemKey, const int order) +{ + const QString key = QString("pos_%1_%2").arg(itemKey).arg(displayMode()); + m_proxyInter->saveValue(this, key, order); +} + +void NotificationsPlugin::pluginSettingsChanged() +{ + refreshPluginItemsVisible(); +} + +void NotificationsPlugin::loadPlugin() +{ + if (m_pluginLoaded) + return; + + m_pluginLoaded = true; + + m_itemWidget = new NotificationsWidget; + + m_proxyInter->itemAdded(this, pluginName()); + displayModeChanged(displayMode()); +} + +bool NotificationsPlugin::checkSwap() +{ + QFile file("/proc/swaps"); + if (file.open(QIODevice::Text | QIODevice::ReadOnly)) { + const QString &body = file.readAll(); + file.close(); + QRegularExpression re("\\spartition\\s"); + QRegularExpressionMatch match = re.match(body); + return match.hasMatch(); + } + + return false; +} + +void NotificationsPlugin::refreshPluginItemsVisible() +{ + if (pluginIsDisable()) { + m_proxyInter->itemRemoved(this, pluginName()); + } else { + if (!m_pluginLoaded) { + loadPlugin(); + return; + } + m_proxyInter->itemAdded(this, pluginName()); + } +} diff --git a/plugins/notifications/notificationsplugin.h b/plugins/notifications/notificationsplugin.h new file mode 100644 index 000000000..1b3c24103 --- /dev/null +++ b/plugins/notifications/notificationsplugin.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. + * + * Author: sbw + * + * Maintainer: sbw + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef NOTIFITIONPLUGIN_H +#define NOTIFITIONPLUGIN_H + +#include "pluginsiteminterface.h" +#include "notificationswidget.h" +#include "../widgets/tipswidget.h" + +#include + +class NotificationsPlugin : public QObject, PluginsItemInterface +{ + Q_OBJECT + Q_INTERFACES(PluginsItemInterface) + Q_PLUGIN_METADATA(IID "com.deepin.dock.PluginsItemInterface" FILE "notifications.json") + +public: + explicit NotificationsPlugin(QObject *parent = 0); + + const QString pluginName() const override; + const QString pluginDisplayName() const override; + void init(PluginProxyInterface *proxyInter) override; + void pluginStateSwitched() override; + bool pluginIsAllowDisable() override { return true; } + bool pluginIsDisable() override; + QWidget *itemWidget(const QString &itemKey) override; + QWidget *itemTipsWidget(const QString &itemKey) override; + const QString itemCommand(const QString &itemKey) override; + void displayModeChanged(const Dock::DisplayMode displayMode) override; + int itemSortKey(const QString &itemKey) Q_DECL_OVERRIDE; + void setSortKey(const QString &itemKey, const int order) Q_DECL_OVERRIDE; + void pluginSettingsChanged() override; + QDBusInterface *getNotifyInterface(); + +private: + void loadPlugin(); + bool checkSwap(); + void refreshPluginItemsVisible(); + +private: + bool m_pluginLoaded; + QDBusInterface *m_interface = nullptr; + + NotificationsWidget *m_itemWidget; + TipsWidget *m_tipsLabel; +}; + +#endif // NOTIFITIONPLUGIN_H diff --git a/plugins/notifications/notificationswidget.cpp b/plugins/notifications/notificationswidget.cpp new file mode 100644 index 000000000..0e963bb5d --- /dev/null +++ b/plugins/notifications/notificationswidget.cpp @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. + * + * Author: sbw + * + * Maintainer: sbw + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "notificationswidget.h" + +#include +#include +#include +#include +#include + +#include +#include + +DWIDGET_USE_NAMESPACE; + +NotificationsWidget::NotificationsWidget(QWidget *parent) + : QWidget(parent) + , m_hover(false) + , m_pressed(false) +{ + setMouseTracking(true); + setMinimumSize(PLUGIN_BACKGROUND_MIN_SIZE, PLUGIN_BACKGROUND_MIN_SIZE); + + connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, this, [ = ] { + update(); + }); + m_icon = QIcon::fromTheme(":/icons/resources/icons/notification.svg"); +} + +QSize NotificationsWidget::sizeHint() const +{ + return QSize(PLUGIN_BACKGROUND_MAX_SIZE, PLUGIN_BACKGROUND_MAX_SIZE); +} + +void NotificationsWidget::paintEvent(QPaintEvent *e) +{ + Q_UNUSED(e); + + QPixmap pixmap; + QString iconName = "notification"; + int iconSize = PLUGIN_ICON_MAX_SIZE; + + QPainter painter(this); + + if (rect().height() > PLUGIN_BACKGROUND_MIN_SIZE) { + + QColor color; + if (DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::LightType) { + color = Qt::black; + painter.setOpacity(0.5); + + if (m_hover) { + painter.setOpacity(0.6); + } + + if (m_pressed) { + painter.setOpacity(0.3); + } + } else { + color = Qt::white; + painter.setOpacity(0.1); + + if (m_hover) { + painter.setOpacity(0.2); + } + + if (m_pressed) { + painter.setOpacity(0.05); + } + } + + painter.setRenderHint(QPainter::Antialiasing, true); + + DStyleHelper dstyle(style()); + const int radius = dstyle.pixelMetric(DStyle::PM_FrameRadius); + + QPainterPath path; + + int minSize = std::min(width(), height()); + QRect rc(0, 0, minSize, minSize); + rc.moveTo(rect().center() - rc.center()); + + path.addRoundedRect(rc, radius, radius); + painter.fillPath(path, color); + } else if (DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::LightType) { + // 最小尺寸时,不画背景,采用深色图标 + iconName.append(PLUGIN_MIN_ICON_NAME); + } + + painter.setOpacity(1); + + pixmap = loadSvg(iconName, QSize(iconSize, iconSize)); + + const QRectF &rf = QRectF(rect()); + const QRectF &rfp = QRectF(pixmap.rect()); + painter.drawPixmap(rf.center() - rfp.center() / pixmap.devicePixelRatioF(), pixmap); +} + +const QPixmap NotificationsWidget::loadSvg(const QString &fileName, const QSize &size) const +{ + const auto ratio = devicePixelRatioF(); + + QPixmap pixmap; + pixmap = QIcon::fromTheme(fileName, m_icon).pixmap(size * ratio); + pixmap.setDevicePixelRatio(ratio); + + return pixmap; +} + +void NotificationsWidget::mousePressEvent(QMouseEvent *event) +{ + m_pressed = true; + update(); + + QWidget::mousePressEvent(event); +} + +void NotificationsWidget::mouseReleaseEvent(QMouseEvent *event) +{ + m_pressed = false; + m_hover = false; + update(); + + QWidget::mouseReleaseEvent(event); +} + +void NotificationsWidget::mouseMoveEvent(QMouseEvent *event) +{ + m_hover = true; + QWidget::mouseMoveEvent(event); +} + +void NotificationsWidget::leaveEvent(QEvent *event) +{ + if (!rect().contains(mapFromGlobal(QCursor::pos()))) { + m_hover = false; + m_pressed = false; + update(); + } + + QWidget::leaveEvent(event); +} + +void NotificationsWidget::resizeEvent(QResizeEvent *event) +{ + const Dock::Position position = qApp->property(PROP_POSITION).value(); + // 保持横纵比 + if (position == Dock::Bottom || position == Dock::Top) { + setMaximumWidth(height()); + setMaximumHeight(QWIDGETSIZE_MAX); + } else { + setMaximumHeight(width()); + setMaximumWidth(QWIDGETSIZE_MAX); + } + + QWidget::resizeEvent(event); +} diff --git a/plugins/notifications/notificationswidget.h b/plugins/notifications/notificationswidget.h new file mode 100644 index 000000000..fc9dbe671 --- /dev/null +++ b/plugins/notifications/notificationswidget.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. + * + * Author: sbw + * + * Maintainer: sbw + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef NOTIFICATIONSWIDGET_H +#define NOTIFICATIONSWIDGET_H + +#include "constants.h" + +#include +#include + +class NotificationsWidget: public QWidget +{ + Q_OBJECT + +public: + explicit NotificationsWidget(QWidget *parent = 0); + +protected: + QSize sizeHint() const override; + void paintEvent(QPaintEvent *e) override; + void mousePressEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; + void mouseMoveEvent(QMouseEvent *event) override; + void leaveEvent(QEvent *event) override; + void resizeEvent(QResizeEvent *event) override; + +private: + const QPixmap loadSvg(const QString &fileName, const QSize &size) const; + +private: + Dock::DisplayMode m_displayMode; + bool m_hover; + bool m_pressed; + QIcon m_icon; +}; + +#endif // NOTIFICATIONSWIDGET_H diff --git a/plugins/notifications/resources.qrc b/plugins/notifications/resources.qrc new file mode 100644 index 000000000..4f9274604 --- /dev/null +++ b/plugins/notifications/resources.qrc @@ -0,0 +1,6 @@ + + + resources/icons/notification-dark.svg + resources/icons/notification.svg + + diff --git a/plugins/notifications/resources/icons/notification-dark.svg b/plugins/notifications/resources/icons/notification-dark.svg new file mode 100644 index 000000000..af1c5d3dc --- /dev/null +++ b/plugins/notifications/resources/icons/notification-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/plugins/notifications/resources/icons/notification.svg b/plugins/notifications/resources/icons/notification.svg new file mode 100644 index 000000000..d4d284697 --- /dev/null +++ b/plugins/notifications/resources/icons/notification.svg @@ -0,0 +1,3 @@ + + +