diff --git a/applets/notifications/package/contents/ui/NotificationItem.qml b/applets/notifications/package/contents/ui/NotificationItem.qml index 59dccfc6a1c107121ece630cd9d2e261689aaf77..64833422425aadb22e7f9a64ba3da02124542777 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 bb8de35f718e18909aeb4f27b9b016480c241715..9892fe3a4c5a9e71a5077ca6047b5c9036b698bc 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