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
wilder-5.24
Nate Graham 4 years ago
parent 618a027369
commit be7efa5ec2
  1. 204
      applets/notifications/package/contents/ui/NotificationItem.qml
  2. 1
      applets/notifications/package/contents/ui/NotificationPopup.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: "<style>a { color: " + PlasmaCore.Theme.linkColor + "; }</style>" + 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: "<style>a { color: " + PlasmaCore.Theme.linkColor + "; }</style>" + 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
}
}
}

@ -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

Loading…
Cancel
Save