diff --git a/panels/notification/CMakeLists.txt b/panels/notification/CMakeLists.txt index 9ca089af5..de30b0fd1 100644 --- a/panels/notification/CMakeLists.txt +++ b/panels/notification/CMakeLists.txt @@ -16,6 +16,8 @@ add_library(ds-notification-shared SHARED ${CMAKE_SOURCE_DIR}/panels/notification/common/notifyentity.cpp ${CMAKE_SOURCE_DIR}/panels/notification/common/dbaccessor.h ${CMAKE_SOURCE_DIR}/panels/notification/common/dbaccessor.cpp + ${CMAKE_SOURCE_DIR}/panels/notification/common/notifysetting.h + ${CMAKE_SOURCE_DIR}/panels/notification/common/notifysetting.cpp ) set_target_properties(ds-notification-shared PROPERTIES @@ -28,6 +30,7 @@ target_include_directories(ds-notification-shared PUBLIC target_link_libraries(ds-notification-shared PUBLIC Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Sql + Dtk${DTK_VERSION_MAJOR}::Core ) install(TARGETS ds-notification-shared DESTINATION "${LIB_INSTALL_DIR}") diff --git a/panels/notification/bubble/bubblemodel.cpp b/panels/notification/bubble/bubblemodel.cpp index d130c0cce..10d4454d8 100644 --- a/panels/notification/bubble/bubblemodel.cpp +++ b/panels/notification/bubble/bubblemodel.cpp @@ -3,6 +3,9 @@ // SPDX-License-Identifier: GPL-3.0-or-later #include "bubblemodel.h" + +#include + #include "bubbleitem.h" #include @@ -24,7 +27,11 @@ BubbleModel::BubbleModel(QObject *parent) { m_updateTimeTipTimer->setInterval(1000); m_updateTimeTipTimer->setSingleShot(false); + BubbleMaxCount = NotifySetting::instance()->bubbleCount(); + connect(m_updateTimeTipTimer, &QTimer::timeout, this, &BubbleModel::updateBubbleTimeTip); + connect(NotifySetting::instance(), &NotifySetting::contentRowCountChanged, this, &BubbleModel::updateContentRowCount); + connect(NotifySetting::instance(), &NotifySetting::bubbleCountChanged, this, &BubbleModel::updateBubbleCount); } BubbleModel::~BubbleModel() @@ -48,13 +55,6 @@ void BubbleModel::push(BubbleItem *bubble) m_bubbles.prepend(bubble); endInsertRows(); - connect(bubble, &BubbleItem::timeTipChanged, this, [this, bubble] { - const auto row = m_bubbles.indexOf(bubble); - if (row <= displayRowCount()) { - Q_EMIT dataChanged(index(row), index(row), {BubbleModel::TimeTip}); - } - }); - updateLevel(); } @@ -192,6 +192,8 @@ QVariant BubbleModel::data(const QModelIndex &index, int role) const return m_bubbles[row]->actions(); case BubbleModel::Urgency: return m_bubbles[row]->urgency(); + case BubbleModel::ContentRowCount: + return NotifySetting::instance()->contentRowCount(); default: break; } @@ -214,6 +216,7 @@ QHash BubbleModel::roleNames() const mapRoleNames[BubbleModel::OverlayCount] = "overlayCount"; mapRoleNames[BubbleModel::DefaultAction] = "defaultAction"; mapRoleNames[BubbleModel::Actions] = "actions"; + mapRoleNames[BubbleModel::ContentRowCount] = "contentRowCount"; return mapRoleNames; } @@ -227,7 +230,7 @@ int BubbleModel::overlayCount() const return qMin(m_bubbles.count() - displayRowCount(), OverlayMaxCount); } -void BubbleModel::setBubbleCount(int count) +void BubbleModel::updateBubbleCount(int count) { if (count == BubbleMaxCount) return; @@ -245,6 +248,7 @@ void BubbleModel::setBubbleCount(int count) BubbleMaxCount = count; + layoutChanged(); updateLevel(); } @@ -302,19 +306,31 @@ void BubbleModel::updateBubbleTimeTip() { if (m_bubbles.isEmpty()) { m_updateTimeTipTimer->stop(); + return; } - for (int i = 0; i < displayRowCount(); i++) { - auto item = m_bubbles.at(i); - + for (auto item : m_bubbles) { qint64 diff = QDateTime::currentMSecsSinceEpoch() - item->ctime(); diff /= 1000; // secs - QString timeTip; if (diff >= 60) { + QString timeTip; timeTip = tr("%1 minutes ago").arg(diff / 60); item->setTimeTip(timeTip); }; } + + Q_EMIT dataChanged(index(0), index(m_bubbles.size() - 1), {BubbleModel::TimeTip}); } +void BubbleModel::updateContentRowCount(int rowCount) +{ + if (m_contentRowCount == rowCount) + return; + + m_contentRowCount = rowCount; + + if (!m_bubbles.isEmpty()) { + Q_EMIT dataChanged(index(0), index(m_bubbles.size() - 1), {BubbleModel::ContentRowCount}); + } +} } diff --git a/panels/notification/bubble/bubblemodel.h b/panels/notification/bubble/bubblemodel.h index d4d383411..5427e8b19 100644 --- a/panels/notification/bubble/bubblemodel.h +++ b/panels/notification/bubble/bubblemodel.h @@ -32,6 +32,7 @@ class BubbleModel : public QAbstractListModel DefaultAction, Actions, Urgency, + ContentRowCount } BubbleRole; explicit BubbleModel(QObject *parent = nullptr); @@ -58,7 +59,6 @@ class BubbleModel : public QAbstractListModel int displayRowCount() const; int overlayCount() const; - void setBubbleCount(int count); qint64 delayRemovedBubble() const; void setDelayRemovedBubble(qint64 newDelayRemovedBubble); @@ -67,14 +67,17 @@ class BubbleModel : public QAbstractListModel void delayRemovedBubbleChanged(); private: + void updateBubbleCount(int count); int replaceBubbleIndex(const BubbleItem *bubble) const; void updateLevel(); void updateBubbleTimeTip(); + void updateContentRowCount(int rowCount); private: QTimer *m_updateTimeTipTimer = nullptr; QList m_bubbles; int BubbleMaxCount{3}; + int m_contentRowCount{6}; const int OverlayMaxCount{2}; QList m_delayBubbles; qint64 m_delayRemovedBubble{-1}; diff --git a/panels/notification/bubble/bubblepanel.cpp b/panels/notification/bubble/bubblepanel.cpp index eb7fc6ada..99cb7f91f 100644 --- a/panels/notification/bubble/bubblepanel.cpp +++ b/panels/notification/bubble/bubblepanel.cpp @@ -6,16 +6,13 @@ #include "bubblemodel.h" #include "pluginfactory.h" #include "bubbleitem.h" +#include "dbaccessor.h" #include #include -#include - #include -#include "dbaccessor.h" - namespace notification { Q_DECLARE_LOGGING_CATEGORY(notifyLog) } @@ -31,9 +28,7 @@ BubblePanel::BubblePanel(QObject *parent) BubblePanel::~BubblePanel() { - if (m_setting) { - m_setting->deleteLater(); - } + } bool BubblePanel::load() @@ -55,13 +50,6 @@ bool BubblePanel::init() connect(m_notificationServer, SIGNAL(notificationStateChanged(qint64, int)), this, SLOT(onNotificationStateChanged(qint64, int))); - m_setting = Dtk::Core::DConfig::create("org.deepin.dde.shell", "org.deepin.dde.shell.notification"); - QObject::connect(m_setting, &Dtk::Core::DConfig::valueChanged, this, [this](const QString &key) { - if (key == "bubbleCount") { - updateMaxBubbleCount(); - } - }); - updateMaxBubbleCount(); connect(m_bubbles, &BubbleModel::rowsInserted, this, &BubblePanel::onBubbleCountChanged); connect(m_bubbles, &BubbleModel::rowsRemoved, this, &BubblePanel::onBubbleCountChanged); @@ -182,16 +170,6 @@ BubbleItem *BubblePanel::bubbleItem(int index) return m_bubbles->items().at(index); } -void BubblePanel::updateMaxBubbleCount() -{ - const auto count = m_setting->value("bubbleCount", 3).toInt(); - if (count < 1) { - qWarning(notifyLog) << "Invalid settings of bubbleCount:" << count << ", it should be greater than 0"; - return; - } - m_bubbles->setBubbleCount(count); -} - D_APPLET_CLASS(BubblePanel) bool BubblePanel::enabled() const diff --git a/panels/notification/bubble/bubblepanel.h b/panels/notification/bubble/bubblepanel.h index 6d869523c..1d12c3399 100644 --- a/panels/notification/bubble/bubblepanel.h +++ b/panels/notification/bubble/bubblepanel.h @@ -10,14 +10,6 @@ #include -namespace Dtk -{ -namespace Core -{ -class DConfig; -} -} - namespace notification { class NotifyEntity; @@ -68,15 +60,12 @@ private Q_SLOTS: BubbleItem *bubbleItem(int index); - void updateMaxBubbleCount(); - private: bool m_visible = false; BubbleModel *m_bubbles = nullptr; DS_NAMESPACE::DAppletProxy *m_notificationServer = nullptr; DataAccessor *m_accessor = nullptr; bool m_enabled = true; - Dtk::Core::DConfig *m_setting = nullptr; }; } diff --git a/panels/notification/bubble/package/NormalBubble.qml b/panels/notification/bubble/package/NormalBubble.qml index 99a6da48e..02228b543 100644 --- a/panels/notification/bubble/package/NormalBubble.qml +++ b/panels/notification/bubble/package/NormalBubble.qml @@ -22,6 +22,7 @@ NotifyItemContent { content: bubble.body strongInteractive: bubble.urgency === 2 contentIcon: bubble.bodyImagePath + contentRowCount: bubble.contentRowCount onRemove: function () { console.log("remove notify", bubble.appName) Applet.close(bubble.index) diff --git a/panels/notification/center/NormalNotify.qml b/panels/notification/center/NormalNotify.qml index cc7a4e2b1..12ff1f74f 100644 --- a/panels/notification/center/NormalNotify.qml +++ b/panels/notification/center/NormalNotify.qml @@ -43,6 +43,7 @@ NotifyItem { closeVisible: root.hovered || root.activeFocus strongInteractive: root.strongInteractive contentIcon: root.contentIcon + contentRowCount: root.contentRowCount onRemove: function () { root.state = "removing" diff --git a/panels/notification/center/NotifyStaging.qml b/panels/notification/center/NotifyStaging.qml index 9761d62a7..a7fcc1321 100644 --- a/panels/notification/center/NotifyStaging.qml +++ b/panels/notification/center/NotifyStaging.qml @@ -44,6 +44,7 @@ FocusScope { content: model.content strongInteractive: model.strongInteractive contentIcon: model.contentIcon + contentRowCount: model.contentRowCount onRemove: function () { console.log("remove overlap", model.id) diff --git a/panels/notification/center/NotifyViewDelegate.qml b/panels/notification/center/NotifyViewDelegate.qml index 553a4afe3..3d3acaa14 100644 --- a/panels/notification/center/NotifyViewDelegate.qml +++ b/panels/notification/center/NotifyViewDelegate.qml @@ -72,6 +72,7 @@ DelegateChooser { content: model.content strongInteractive: model.strongInteractive contentIcon: model.contentIcon + contentRowCount: model.contentRowCount property string defaultAction: model.defaultAction function invokeAction(actionId) { @@ -139,6 +140,7 @@ DelegateChooser { content: model.content strongInteractive: model.strongInteractive contentIcon: model.contentIcon + contentRowCount: model.contentRowCount Loader { anchors.fill: parent diff --git a/panels/notification/center/OverlapNotify.qml b/panels/notification/center/OverlapNotify.qml index 25ec2bd0f..b2199b1d9 100644 --- a/panels/notification/center/OverlapNotify.qml +++ b/panels/notification/center/OverlapNotify.qml @@ -52,6 +52,7 @@ NotifyItem { closeVisible: root.hovered || root.activeFocus strongInteractive: root.strongInteractive contentIcon: root.contentIcon + contentRowCount: root.contentRowCount onRemove: function () { root.state = "removing" diff --git a/panels/notification/center/notifymodel.cpp b/panels/notification/center/notifymodel.cpp index 4c13fd5ca..64cca22c8 100644 --- a/panels/notification/center/notifymodel.cpp +++ b/panels/notification/center/notifymodel.cpp @@ -10,6 +10,7 @@ #include "notifyentity.h" #include "notifyitem.h" #include "notifyaccessor.h" +#include "notifysetting.h" namespace notification { Q_DECLARE_LOGGING_CATEGORY(notifyLog) @@ -22,6 +23,7 @@ NotifyModel::NotifyModel(QObject *parent) { connect(m_accessor, &NotifyAccessor::entityReceived, this, &NotifyModel::doEntityReceived); connect(this, &NotifyModel::countChanged, this, &NotifyModel::onCountChanged); + connect(NotifySetting::instance(), &NotifySetting::contentRowCountChanged, this, &NotifyModel::updateContentRowCount); updateCollapseStatus(); @@ -391,6 +393,17 @@ void NotifyModel::updateCollapseStatus() setCollapse(!existGroup); } +void NotifyModel::updateContentRowCount(int rowCount) +{ + if (m_contentRowCount == rowCount) + return; + m_contentRowCount = rowCount; + + if (!m_appNotifies.isEmpty()) { + dataChanged(index(0), index(m_appNotifies.size() - 1), {NotifyRole::NotifyContentRowCount}); + } +} + bool NotifyModel::greaterNotify(const AppNotifyItem *item1, const AppNotifyItem *item2) const { const auto entity1 = greaterNotifyEntity(item1); @@ -706,6 +719,8 @@ QVariant NotifyModel::data(const QModelIndex &index, int role) const if (auto item = dynamic_cast(notify)) { return item->count(); } + } else if (role == NotifyRole::NotifyContentRowCount) { + return NotifySetting::instance()->contentRowCount(); } return QVariant::fromValue(notify); } @@ -759,7 +774,8 @@ QHash NotifyModel::roleNames() const {NotifyPinned, "pinned"}, {NotifyStrongInteractive, "strongInteractive"}, {NotifyContentIcon, "contentIcon"}, - {NotifyOverlapCount, "overlapCount"}}; + {NotifyOverlapCount, "overlapCount"}, + {NotifyContentRowCount, "contentRowCount"}}; return roles; } diff --git a/panels/notification/center/notifymodel.h b/panels/notification/center/notifymodel.h index 963365d8a..0127a9484 100644 --- a/panels/notification/center/notifymodel.h +++ b/panels/notification/center/notifymodel.h @@ -36,7 +36,8 @@ class NotifyModel : public QAbstractListModel NotifyPinned, NotifyStrongInteractive, NotifyContentIcon, - NotifyOverlapCount + NotifyOverlapCount, + NotifyContentRowCount }; NotifyModel(QObject *parent = nullptr); @@ -93,11 +94,13 @@ private slots: void trayUpdateGroupLastEntity(const NotifyEntity &entity); void trayUpdateGroupLastEntity(const QString &appName); void updateCollapseStatus(); + void updateContentRowCount(int rowCount); private: QList m_appNotifies; QPointer m_accessor; int m_refreshTimer = -1; bool m_collapse = false; + int m_contentRowCount = 6; }; } diff --git a/panels/notification/center/notifystagingmodel.cpp b/panels/notification/center/notifystagingmodel.cpp index 2fc766075..69dbeb8ec 100644 --- a/panels/notification/center/notifystagingmodel.cpp +++ b/panels/notification/center/notifystagingmodel.cpp @@ -11,6 +11,7 @@ #include "notifyitem.h" #include "notifyaccessor.h" #include "dbaccessor.h" +#include "notifysetting.h" namespace notification { Q_DECLARE_LOGGING_CATEGORY(notifyLog) @@ -23,6 +24,7 @@ NotifyStagingModel::NotifyStagingModel(QObject *parent) { connect(NotifyAccessor::instance(), &NotifyAccessor::stagingEntityReceived, this, &NotifyStagingModel::doEntityReceived); connect(NotifyAccessor::instance(), &NotifyAccessor::stagingEntityClosed, this, &NotifyStagingModel::onEntityClosed); + connect(NotifySetting::instance(), &NotifySetting::contentRowCountChanged, this, &NotifyStagingModel::updateContentRowCount); } void NotifyStagingModel::close() @@ -211,6 +213,8 @@ QVariant NotifyStagingModel::data(const QModelIndex &index, int role) const } else { return std::min(OverlayMaxCount, overlapCount()); } + } else if (role == NotifyRole::NotifyContentRowCount) { + return NotifySetting::instance()->contentRowCount(); } return QVariant::fromValue(notify); } @@ -264,7 +268,8 @@ QHash NotifyStagingModel::roleNames() const {NotifyContent, "content"}, {NotifyStrongInteractive, "strongInteractive"}, {NotifyContentIcon, "contentIcon"}, - {NotifyOverlapCount, "overlapCount"}}; + {NotifyOverlapCount, "overlapCount"}, + {NotifyContentRowCount, "contentRowCount"}}; return roles; } @@ -317,4 +322,15 @@ void NotifyStagingModel::updateOverlapCount(int count) } } +void NotifyStagingModel::updateContentRowCount(int rowCount) +{ + if (m_contentRowCount == rowCount) + return; + + m_contentRowCount = rowCount; + + if (!m_appNotifies.isEmpty()) { + dataChanged(index(0), index(m_appNotifies.size() - 1), {NotifyRole::NotifyContentRowCount}); + } +} } diff --git a/panels/notification/center/notifystagingmodel.h b/panels/notification/center/notifystagingmodel.h index 9b181446f..78e0b3798 100644 --- a/panels/notification/center/notifystagingmodel.h +++ b/panels/notification/center/notifystagingmodel.h @@ -34,7 +34,8 @@ class NotifyStagingModel : public QAbstractListModel NotifyContent, NotifyStrongInteractive, NotifyContentIcon, - NotifyOverlapCount + NotifyOverlapCount, + NotifyContentRowCount }; NotifyStagingModel(QObject *parent = nullptr); @@ -51,6 +52,7 @@ class NotifyStagingModel : public QAbstractListModel int overlapCount() const; void updateOverlapCount(int count); + void updateContentRowCount(int rowCount); private slots: void push(const NotifyEntity &entity); @@ -70,5 +72,6 @@ private slots: int m_refreshTimer = -1; DataAccessor *m_accessor = nullptr; int m_overlapCount = 0; + int m_contentRowCount = 6; }; } diff --git a/panels/notification/common/notifysetting.cpp b/panels/notification/common/notifysetting.cpp new file mode 100644 index 000000000..8d75455cb --- /dev/null +++ b/panels/notification/common/notifysetting.cpp @@ -0,0 +1,76 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "notifysetting.h" + +#include + +namespace notification { + +NotifySetting * NotifySetting::instance() +{ + static NotifySetting instance; + return &instance; +} + +int NotifySetting::bubbleCount() const +{ + return m_bubbleCount; +} + +int NotifySetting::contentRowCount() const +{ + return m_contentRowCount; +} + +NotifySetting::NotifySetting(QObject *parent) + : QObject(parent) +{ + m_setting = Dtk::Core::DConfig::create("org.deepin.dde.shell", "org.deepin.dde.shell.notification"); + connect(m_setting, &Dtk::Core::DConfig::valueChanged, this, [this](const QString &key) { + if (key == "bubbleCount") { + updateMaxBubbleCount(); + } else if (key == "bubbleContentRowCount") { + updateBubbleContentRowCount(); + } + }); + + updateMaxBubbleCount(); + updateBubbleContentRowCount(); +} + +NotifySetting::~NotifySetting() +{ + if (m_setting) + m_setting->deleteLater(); +} + +void NotifySetting::updateMaxBubbleCount() +{ + auto count = m_setting->value("bubbleCount").toInt(); + if (count < 1) { + qWarning() << "Invalid settings of bubbleCount:" << count << ", it should be greater than 0"; + return; + } + + if (m_bubbleCount != count) { + m_bubbleCount = count; + Q_EMIT bubbleCountChanged(count); + } +} + +void NotifySetting::updateBubbleContentRowCount() +{ + auto count = m_setting->value("bubbleContentRowCount").toInt(); + if (count < 1) { + qWarning() << "Invalid settings of bubbleContentRowCount:" << count << ", it should be greater than 0"; + return; + } + + if (m_contentRowCount != count) { + m_contentRowCount = count; + Q_EMIT contentRowCountChanged(count); + } +} +} diff --git a/panels/notification/common/notifysetting.h b/panels/notification/common/notifysetting.h new file mode 100644 index 000000000..4a2f9679f --- /dev/null +++ b/panels/notification/common/notifysetting.h @@ -0,0 +1,42 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include + +namespace Dtk::Core { + class DConfig; +} + +namespace notification { + +class NotifySetting : public QObject +{ + Q_OBJECT +public: + static NotifySetting *instance(); + + int bubbleCount() const; + int contentRowCount() const; + +signals: + void bubbleCountChanged(int count); + void contentRowCountChanged(int rowCount); + +private: + explicit NotifySetting(QObject *parent = nullptr); + ~NotifySetting() override; + + void updateMaxBubbleCount(); + void updateBubbleContentRowCount(); + +private: + int m_bubbleCount = 3; + int m_contentRowCount = 6; + + Dtk::Core::DConfig *m_setting = nullptr; +}; + +} \ No newline at end of file diff --git a/panels/notification/plugin/NotifyItem.qml b/panels/notification/plugin/NotifyItem.qml index 61199cce9..910a4c6a2 100644 --- a/panels/notification/plugin/NotifyItem.qml +++ b/panels/notification/plugin/NotifyItem.qml @@ -23,6 +23,7 @@ Control { ] property bool strongInteractive: false property string contentIcon: "deepin-editor" + property int contentRowCount: 6 signal remove() signal setting(var pos) diff --git a/panels/notification/plugin/NotifyItemContent.qml b/panels/notification/plugin/NotifyItemContent.qml index 3a1dc3df0..40964c3aa 100644 --- a/panels/notification/plugin/NotifyItemContent.qml +++ b/panels/notification/plugin/NotifyItemContent.qml @@ -172,7 +172,7 @@ NotifyItem { Layout.fillWidth: true visible: text !== "" text: root.content - maximumLineCount: 6 + maximumLineCount: root.contentRowCount font: DTK.fontManager.t8 color: palette.windowText wrapMode: Text.WordWrap 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 a6c47f600..f48de52af 100644 --- a/panels/notification/server/configs/org.deepin.dde.shell.notification.json +++ b/panels/notification/server/configs/org.deepin.dde.shell.notification.json @@ -90,6 +90,17 @@ "permissions": "readwrite", "visibility": "public" }, + "bubbleContentRowCount": { + "value": 6, + "serial": 0, + "flags": [], + "name": "notification bubble content row count", + "name[zh_CN]": "通知内容行数", + "description": "notification bubble content row count, the value should be greater than 0", + "description[zh_CN]": "通知内容行数, 数值应该大于0", + "permissions": "readwrite", + "visibility": "public" + }, "appsInfo": { "value": {}, "serial": 0,