From be7efa5ec2bcf2c87947ee2ff5e2b9c70eb2084e Mon Sep 17 00:00:00 2001 From: Nate Graham Date: Wed, 13 Oct 2021 09:57:23 -0600 Subject: [PATCH] applets/notifications: Embellish header for critical notifications We get intermittent user complaints and bug reports about notifications not being visible enough, especially on large or cluttered screens. This commit attempts to remedy the situation by tinting the header for on the left side for critical notifications using the color scheme's "warning" color. Only critical notifications receive this treatment since they're the only ones that the user really does need to see. BUG: 420541 FIXED-IN: 5.24 --- .../package/contents/ui/NotificationItem.qml | 204 ++++++++++-------- .../package/contents/ui/NotificationPopup.qml | 1 + 2 files changed, 119 insertions(+), 86 deletions(-) diff --git a/applets/notifications/package/contents/ui/NotificationItem.qml b/applets/notifications/package/contents/ui/NotificationItem.qml index 59dccfc6a1..6483342242 100644 --- a/applets/notifications/package/contents/ui/NotificationItem.qml +++ b/applets/notifications/package/contents/ui/NotificationItem.qml @@ -48,6 +48,7 @@ ColumnLayout { property int jobState property int percentage property int jobError: 0 + property int urgency property bool suspendable property bool killable @@ -145,116 +146,147 @@ ColumnLayout { RowLayout { id: bodyRow Layout.fillWidth: true + + // When the urgent notification line is visible, remove margins to allow + // it to touch the edges of the popup + Layout.topMargin: urgentNotificationLine.visible? notificationItem.thumbnailTopPadding + PlasmaCore.Units.devicePixelRatio : -1 + Layout.leftMargin: urgentNotificationLine.visible? notificationItem.thumbnailLeftPadding : -1 + Layout.bottomMargin: urgentNotificationLine.visible? notificationItem.thumbnailBottomPadding : -1 + spacing: PlasmaCore.Units.smallSpacing - ColumnLayout { + // Visual flourish for urgent notifications to make them stand out more + Rectangle { + id: urgentNotificationLine + Layout.fillHeight: true + Layout.alignment: Qt.AlignVCenter + implicitWidth: Math.round(PlasmaCore.Units.gridUnit / 4) + + color: PlasmaCore.Theme.neutralTextColor + + visible: notificationItem.urgency == NotificationManager.Notifications.CriticalUrgency + } + + RowLayout { Layout.fillWidth: true - spacing: 0 + // Re-add margins to this item if they were removed in the parent item + // to let the urgent notification line touch the edges; we do want + // everything else to have normal margins + Layout.topMargin: urgentNotificationLine.visible? -notificationItem.thumbnailTopPadding : -1 + Layout.leftMargin: urgentNotificationLine.visible? -notificationItem.thumbnailLeftPadding : -1 + Layout.bottomMargin: urgentNotificationLine.visible? -notificationItem.thumbnailBottomPadding : -1 - RowLayout { - id: summaryRow + spacing: PlasmaCore.Units.smallSpacing + + ColumnLayout { Layout.fillWidth: true - visible: summaryLabel.text !== "" + spacing: 0 - PlasmaExtras.Heading { - id: summaryLabel + RowLayout { + id: summaryRow Layout.fillWidth: true - Layout.preferredHeight: implicitHeight - textFormat: Text.PlainText - maximumLineCount: 3 - wrapMode: Text.WordWrap - elide: Text.ElideRight - level: 4 - // Give it a bit more visual prominence than the app name in the header - type: PlasmaExtras.Heading.Type.Primary - text: { - if (notificationItem.notificationType === NotificationManager.Notifications.JobType) { - if (notificationItem.jobState === NotificationManager.Notifications.JobStateSuspended) { - if (notificationItem.summary) { - return i18ndc("plasma_applet_org.kde.plasma.notifications", "Job name, e.g. Copying is paused", "%1 (Paused)", notificationItem.summary); - } - } else if (notificationItem.jobState === NotificationManager.Notifications.JobStateStopped) { - if (notificationItem.jobError) { + visible: summaryLabel.text !== "" + + PlasmaExtras.Heading { + id: summaryLabel + Layout.fillWidth: true + Layout.preferredHeight: implicitHeight + textFormat: Text.PlainText + maximumLineCount: 3 + wrapMode: Text.WordWrap + elide: Text.ElideRight + level: 4 + // Give it a bit more visual prominence than the app name in the header + type: PlasmaExtras.Heading.Type.Primary + text: { + if (notificationItem.notificationType === NotificationManager.Notifications.JobType) { + if (notificationItem.jobState === NotificationManager.Notifications.JobStateSuspended) { if (notificationItem.summary) { - return i18ndc("plasma_applet_org.kde.plasma.notifications", "Job name, e.g. Copying has failed", "%1 (Failed)", notificationItem.summary); - } else { - return i18nd("plasma_applet_org.kde.plasma.notifications", "Job Failed"); + return i18ndc("plasma_applet_org.kde.plasma.notifications", "Job name, e.g. Copying is paused", "%1 (Paused)", notificationItem.summary); } - } else { - if (notificationItem.summary) { - return i18ndc("plasma_applet_org.kde.plasma.notifications", "Job name, e.g. Copying has finished", "%1 (Finished)", notificationItem.summary); + } else if (notificationItem.jobState === NotificationManager.Notifications.JobStateStopped) { + if (notificationItem.jobError) { + if (notificationItem.summary) { + return i18ndc("plasma_applet_org.kde.plasma.notifications", "Job name, e.g. Copying has failed", "%1 (Failed)", notificationItem.summary); + } else { + return i18nd("plasma_applet_org.kde.plasma.notifications", "Job Failed"); + } } else { - return i18nd("plasma_applet_org.kde.plasma.notifications", "Job Finished"); + if (notificationItem.summary) { + return i18ndc("plasma_applet_org.kde.plasma.notifications", "Job name, e.g. Copying has finished", "%1 (Finished)", notificationItem.summary); + } else { + return i18nd("plasma_applet_org.kde.plasma.notifications", "Job Finished"); + } } } } + // some apps use their app name as summary, avoid showing the same text twice + // try very hard to match the two + if (notificationItem.summary && notificationItem.summary.toLocaleLowerCase().trim() != notificationItem.applicationName.toLocaleLowerCase().trim()) { + return notificationItem.summary; + } + return ""; } - // some apps use their app name as summary, avoid showing the same text twice - // try very hard to match the two - if (notificationItem.summary && notificationItem.summary.toLocaleLowerCase().trim() != notificationItem.applicationName.toLocaleLowerCase().trim()) { - return notificationItem.summary; - } - return ""; + visible: text !== "" } - visible: text !== "" - } - // inGroup headerItem is reparented here - } + // inGroup headerItem is reparented here + } - RowLayout { - id: bodyTextRow + RowLayout { + id: bodyTextRow - Layout.fillWidth: true - spacing: PlasmaCore.Units.smallSpacing - - SelectableLabel { - id: bodyLabel - // FIXME how to assign this via State? target: bodyLabel.Layout doesn't work and just assigning the property doesn't either - Layout.alignment: notificationItem.inGroup ? Qt.AlignTop : Qt.AlignVCenter Layout.fillWidth: true + spacing: PlasmaCore.Units.smallSpacing + + SelectableLabel { + id: bodyLabel + // FIXME how to assign this via State? target: bodyLabel.Layout doesn't work and just assigning the property doesn't either + Layout.alignment: notificationItem.inGroup ? Qt.AlignTop : Qt.AlignVCenter + Layout.fillWidth: true + + Layout.maximumHeight: notificationItem.maximumLineCount > 0 + ? (theme.mSize(font).height * notificationItem.maximumLineCount) : -1 + + // HACK RichText does not allow to specify link color and since LineEdit + // does not support StyledText, we have to inject some CSS to force the color, + // cf. QTBUG-81463 and to some extent QTBUG-80354 + text: "" + notificationItem.body + + // Cannot do text !== "" because RichText adds some HTML tags even when empty + visible: notificationItem.body !== "" + onClicked: notificationItem.bodyClicked(mouse) + onLinkActivated: Qt.openUrlExternally(link) + } - Layout.maximumHeight: notificationItem.maximumLineCount > 0 - ? (theme.mSize(font).height * notificationItem.maximumLineCount) : -1 - - // HACK RichText does not allow to specify link color and since LineEdit - // does not support StyledText, we have to inject some CSS to force the color, - // cf. QTBUG-81463 and to some extent QTBUG-80354 - text: "" + notificationItem.body - - // Cannot do text !== "" because RichText adds some HTML tags even when empty - visible: notificationItem.body !== "" - onClicked: notificationItem.bodyClicked(mouse) - onLinkActivated: Qt.openUrlExternally(link) + // inGroup iconContainer is reparented here } - - // inGroup iconContainer is reparented here } - } - Item { - id: iconContainer - - Layout.preferredWidth: PlasmaCore.Units.iconSizes.large - Layout.preferredHeight: PlasmaCore.Units.iconSizes.large - Layout.topMargin: PlasmaCore.Units.smallSpacing - Layout.bottomMargin: PlasmaCore.Units.smallSpacing - - visible: iconItem.active - - PlasmaCore.IconItem { - id: iconItem - // don't show two identical icons - readonly property bool active: valid && source != notificationItem.applicationIconSource - anchors.fill: parent - usesPlasmaTheme: false - smooth: true - // don't show a generic "info" icon since this is a notification already - source: notificationItem.icon !== "dialog-information" ? notificationItem.icon : "" - visible: active - } + Item { + id: iconContainer + + Layout.preferredWidth: PlasmaCore.Units.iconSizes.large + Layout.preferredHeight: PlasmaCore.Units.iconSizes.large + Layout.topMargin: PlasmaCore.Units.smallSpacing + Layout.bottomMargin: PlasmaCore.Units.smallSpacing + + visible: iconItem.active + + PlasmaCore.IconItem { + id: iconItem + // don't show two identical icons + readonly property bool active: valid && source != notificationItem.applicationIconSource + anchors.fill: parent + usesPlasmaTheme: false + smooth: true + // don't show a generic "info" icon since this is a notification already + source: notificationItem.icon !== "dialog-information" ? notificationItem.icon : "" + visible: active + } - // JobItem reparents a file icon here for finished jobs with one total file + // JobItem reparents a file icon here for finished jobs with one total file + } } } diff --git a/applets/notifications/package/contents/ui/NotificationPopup.qml b/applets/notifications/package/contents/ui/NotificationPopup.qml index bb8de35f71..9892fe3a4c 100644 --- a/applets/notifications/package/contents/ui/NotificationPopup.qml +++ b/applets/notifications/package/contents/ui/NotificationPopup.qml @@ -183,6 +183,7 @@ PlasmaCore.Dialog { hovered: area.containsMouse maximumLineCount: 8 bodyCursorShape: notificationPopup.hasDefaultAction ? Qt.PointingHandCursor : 0 + urgency: notificationPopup.urgency thumbnailLeftPadding: -notificationPopup.margins.left thumbnailRightPadding: -notificationPopup.margins.right -- GitLab