From 1669197b33f388b9a4d7f8fae66d725c62d026ee Mon Sep 17 00:00:00 2001 From: Nate Graham Date: Wed, 10 Jun 2020 13:35:31 +0000 Subject: [PATCH] [applets/systemtray] Use a grid for the hidden items view This improves the applet in a variety of ways: - Much more touch friendly than the current skinny list view - Many more items can be displayed without needing to scroll - Substantial code simplification - UI improvement from no longer sometimes showing an awkward vertical strip of icons that was invisibly scrollable but some of whose items ate scroll events, and which pushed the header over to the left in a somewhat random-looking way BUG: 402681 FIXED-IN: 5.20 --- .../contents/ui/CurrentItemHighLight.qml | 23 +-- .../contents/ui/ExpandedRepresentation.qml | 161 +++++++----------- .../package/contents/ui/HiddenItemsView.qml | 35 ++-- .../contents/ui/items/AbstractItem.qml | 37 ++-- .../systemtray/package/contents/ui/main.qml | 1 - 5 files changed, 114 insertions(+), 143 deletions(-) diff --git a/applets/systemtray/package/contents/ui/CurrentItemHighLight.qml b/applets/systemtray/package/contents/ui/CurrentItemHighLight.qml index fed9f910a..6adc0abb4 100644 --- a/applets/systemtray/package/contents/ui/CurrentItemHighLight.qml +++ b/applets/systemtray/package/contents/ui/CurrentItemHighLight.qml @@ -24,20 +24,11 @@ import org.kde.plasma.core 2.0 as PlasmaCore PlasmaCore.FrameSvgItem { id: expandedItem - property Item visualParent - property Item target property int location - //! when the target is the root item we use the maximum thickness of the panel - x: plasmoid.formFactor === PlasmaCore.Types.Vertical && target === root ? - 0 : Math.max(0, (target ? target.x : 0) + (visualParent ? visualParent.x : 0)) - y: plasmoid.formFactor === PlasmaCore.Types.Horizontal && target === root ? - 0 : Math.max(0, (target ? target.y : 0) + (visualParent ? visualParent.y : 0)) z: -1 // always draw behind icons - width: plasmoid.formFactor === PlasmaCore.Types.Vertical && target === root ? - parent.width : Math.min(parent.width, target ? target.width : 0) - height: plasmoid.formFactor === PlasmaCore.Types.Horizontal && target === root ? - parent.height : Math.min(parent.height, target ? target.height : 0) + width: parent.width + height: parent.height imagePath: "widgets/tabbar" prefix: { @@ -60,7 +51,7 @@ PlasmaCore.FrameSvgItem { } return prefix; } - opacity: target && dialog.visible ? 1 : 0 + opacity: parent && dialog.visible ? 1 : 0 Behavior on opacity { NumberAnimation { duration: units.longDuration @@ -68,28 +59,28 @@ PlasmaCore.FrameSvgItem { } } Behavior on x { - enabled: target && expandedItem.opacity == 1 + enabled: parent && expandedItem.opacity == 1 NumberAnimation { duration: units.longDuration easing.type: Easing.InOutQuad } } Behavior on y { - enabled: target && expandedItem.opacity == 1 + enabled: parent && expandedItem.opacity == 1 NumberAnimation { duration: units.longDuration easing.type: Easing.InOutQuad } } Behavior on width { - enabled: target && expandedItem.opacity == 1 + enabled: parent && expandedItem.opacity == 1 NumberAnimation { duration: units.longDuration easing.type: Easing.InOutQuad } } Behavior on height { - enabled: target && expandedItem.opacity == 1 + enabled: parent && expandedItem.opacity == 1 NumberAnimation { duration: units.longDuration easing.type: Easing.InOutQuad diff --git a/applets/systemtray/package/contents/ui/ExpandedRepresentation.qml b/applets/systemtray/package/contents/ui/ExpandedRepresentation.qml index c9513acb3..364bf1254 100644 --- a/applets/systemtray/package/contents/ui/ExpandedRepresentation.qml +++ b/applets/systemtray/package/contents/ui/ExpandedRepresentation.qml @@ -1,5 +1,6 @@ /* * Copyright 2016 Marco Martin + * Copyright 2020 Nate Graham * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as @@ -25,19 +26,25 @@ import org.kde.plasma.components 3.0 as PlasmaComponents import org.kde.plasma.extras 2.0 as PlasmaExtras Item { - //set width/height to avoid an useless Dialog resize - width: Layout.minimumWidth - height: Layout.minimumHeight - Layout.minimumWidth: units.gridUnit * 24 - Layout.minimumHeight: units.gridUnit * 21 - Layout.preferredWidth: Layout.minimumWidth - Layout.preferredHeight: Layout.minimumHeight - Layout.maximumWidth: Layout.minimumWidth - Layout.maximumHeight: Layout.minimumHeight + id: popup + //set width/height to avoid useless Dialog resize + readonly property int defaultWidth: units.gridUnit * 24 + readonly property int defaultHeight: units.gridUnit * 21 + + width: defaultWidth + Layout.minimumWidth: defaultWidth + Layout.preferredWidth: defaultWidth + Layout.maximumWidth: defaultWidth + + height: defaultHeight + Layout.minimumHeight: defaultHeight + Layout.preferredHeight: defaultHeight + Layout.maximumHeight: defaultHeight property alias activeApplet: container.activeApplet property alias hiddenLayout: hiddenItemsView.layout + // Header PlasmaExtras.PlasmoidHeading { id: plasmoidHeading anchors { @@ -48,78 +55,35 @@ Item { height: trayHeading.height + bottomPadding + container.headingHeight } - PlasmaExtras.PlasmoidHeading { - id: plasmoidFooter - location: PlasmaExtras.PlasmoidHeading.Location.Footer - anchors { - bottom: parent.bottom - left: parent.left - right: parent.right - } - visible: container.appletHasFooter - height: container.footerHeight - } - + // Main content layout ColumnLayout { id: expandedRepresentation anchors.fill: parent + // TODO: remove this so the scrollview fully touches the header; + // add top padding internally spacing: plasmoidHeading.bottomPadding + // Header content layout RowLayout { id: trayHeading - PlasmaExtras.Heading { - id: heading - Layout.fillWidth: true - level: 1 - Layout.leftMargin: { - //Menu mode - if (!activeApplet && hiddenItemsView.visible && !LayoutMirroring.enabled) { - return units.smallSpacing; - - //applet open, sidebar - } else if (activeApplet && hiddenItemsView.visible && !LayoutMirroring.enabled) { - return hiddenItemsView.width + units.smallSpacing + dialog.margins.left; - - //applet open, no sidebar - } else { - return units.smallSpacing; - } - } - Layout.rightMargin: { - //Menu mode - if (!activeApplet && hiddenItemsView.visible && LayoutMirroring.enabled) { - return units.smallSpacing; - - //applet open, sidebar - } else if (activeApplet && hiddenItemsView.visible && LayoutMirroring.enabled) { - return hiddenItemsView.width + units.largeSpacing; - - //applet open, no sidebar - } else { - return 0; - } - } - + PlasmaComponents.ToolButton { + id: backButton visible: activeApplet - text: activeApplet ? activeApplet.title : "" - MouseArea { - anchors.fill: parent - onClicked: { - if (activeApplet) { - activeApplet.expanded = false; - dialog.visible = true; - } + icon.name: "go-previous" + onClicked: { + if (activeApplet) { + activeApplet.expanded = false; + dialog.visible = true; } } } PlasmaExtras.Heading { - id: noAppletHeading - visible: !activeApplet Layout.fillWidth: true + level: 1 - text: i18n("Status and Notifications") + text: activeApplet ? activeApplet.title : i18n("Status and Notifications") } PlasmaComponents.ToolButton { @@ -134,40 +98,43 @@ Item { } } - RowLayout { - spacing: 0 // must be 0 so that the separator is as close to the indicator as possible - - HiddenItemsView { - id: hiddenItemsView - Layout.fillWidth: !activeApplet - Layout.fillHeight: true - Layout.topMargin: container.headingHeight - } + // Grid view of all available items + HiddenItemsView { + id: hiddenItemsView + Layout.fillWidth: true + Layout.fillHeight: true + Layout.topMargin: units.smallSpacing + visible: !activeApplet + } - PlasmaCore.SvgItem { - visible: hiddenItemsView.visible && activeApplet - Layout.fillHeight: true - Layout.preferredWidth: lineSvg.elementSize("vertical-line").width - Layout.topMargin: container.headingHeight - elementId: "vertical-line" - svg: PlasmaCore.Svg { - id: lineSvg; - imagePath: "widgets/line" - } - } + // Container for currently visible item + PlasmoidPopupsContainer { + id: container + Layout.fillWidth: true + Layout.fillHeight: true + visible: activeApplet + // We need to add our own margins on the top and left (when the + // hidden items view is visible, at least) so it matches the + // dialog's own margins and content is centered correctly + Layout.topMargin: mergeHeadings ? 0 : dialog.margins.top + Layout.leftMargin: hiddenItemsView.visible && activeApplet && !LayoutMirroring.enabled ? dialog.margins.left : 0 + Layout.rightMargin: hiddenItemsView.visible && activeApplet && LayoutMirroring.enabled ? dialog.margins.right : 0 + } + } - PlasmoidPopupsContainer { - id: container - Layout.fillWidth: true - Layout.fillHeight: true - visible: activeApplet - // We need to add our own margins on the top and left (when the - // hidden items view is visible, at least) so it matches the - // dialog's own margins and content is centered correctly - Layout.topMargin: mergeHeadings ? 0 : dialog.margins.top - Layout.leftMargin: hiddenItemsView.visible && activeApplet && !LayoutMirroring.enabled ? dialog.margins.left : 0 - Layout.rightMargin: hiddenItemsView.visible && activeApplet && LayoutMirroring.enabled ? dialog.margins.right : 0 - } + // Footer + PlasmaExtras.PlasmoidHeading { + id: plasmoidFooter + location: PlasmaExtras.PlasmoidHeading.Location.Footer + anchors { + bottom: parent.bottom + left: parent.left + right: parent.right } + visible: container.appletHasFooter + height: container.footerHeight + // So that it doesn't appear over the content view, which results in + // the footer controls being inaccessible + z: -9999 } } diff --git a/applets/systemtray/package/contents/ui/HiddenItemsView.qml b/applets/systemtray/package/contents/ui/HiddenItemsView.qml index bd8fe3abe..9e65ff937 100644 --- a/applets/systemtray/package/contents/ui/HiddenItemsView.qml +++ b/applets/systemtray/package/contents/ui/HiddenItemsView.qml @@ -1,6 +1,7 @@ /* * Copyright 2016 Marco Martin * Copyright 2020 Konrad Materka + * Copyright 2020 Nate Graham * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as @@ -31,12 +32,12 @@ MouseArea { visible: !root.activeApplet || (root.activeApplet.parent && root.activeApplet.parent.inHiddenLayout) implicitWidth: root.activeApplet ? iconColumnWidth : parent.width - property alias layout: hiddenTasksColumn + property alias layout: hiddenTasks //Useful to align stuff to the column of icons, both in expanded and shrink modes property int iconColumnWidth: root.hiddenItemSize + highlight.marginHints.left + highlight.marginHints.right hoverEnabled: true - onExited: hiddenTasksColumn.currentIndex = -1 + onExited: hiddenTasks.currentIndex = -1 PlasmaExtras.ScrollArea { width: parent.width @@ -46,15 +47,18 @@ MouseArea { horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff verticalScrollBarPolicy: root.activeApplet ? Qt.ScrollBarAlwaysOff : Qt.ScrollBarAsNeeded - ListView { - id: hiddenTasksColumn + GridView { + id: hiddenTasks - spacing: units.smallSpacing + readonly property int rows: 4 + readonly property int columns: 4 + + cellWidth: hiddenTasks.width / hiddenTasks.columns + cellHeight: hiddenTasks.height / hiddenTasks.rows currentIndex: -1 highlight: PlasmaComponents.Highlight {} highlightMoveDuration: 0 - highlightResizeDuration: 0 readonly property int iconItemHeight: root.hiddenItemSize + highlight.marginHints.top + highlight.marginHints.bottom property int itemCount: model.rowCount() @@ -71,24 +75,17 @@ MouseArea { } Connections { - target: hiddenTasksColumn.model - // hiddenTasksColumn.count is not updated when ListView is hidden and is not rendered + target: hiddenTasks.model + // hiddenTasks.count is not updated when ListView is hidden and is not rendered // manually update itemCount so that expander arrow hides/shows itself correctly - onModelReset: hiddenTasksColumn.itemCount = hiddenTasksColumn.model.rowCount() - onRowsInserted: hiddenTasksColumn.itemCount = hiddenTasksColumn.model.rowCount() - onRowsRemoved: hiddenTasksColumn.itemCount = hiddenTasksColumn.model.rowCount() - onLayoutChanged: hiddenTasksColumn.itemCount = hiddenTasksColumn.model.rowCount() + onModelReset: hiddenTasks.itemCount = hiddenTasks.model.rowCount() + onRowsInserted: hiddenTasks.itemCount = hiddenTasks.model.rowCount() + onRowsRemoved: hiddenTasks.itemCount = hiddenTasks.model.rowCount() + onLayoutChanged: hiddenTasks.itemCount = hiddenTasks.model.rowCount() } PlasmaComponents.Highlight { id: highlight visible: false } - - CurrentItemHighLight { - readonly property bool hiddenAppletActivated: root.activeApplet && root.activeApplet.parent && root.activeApplet.parent.inHiddenLayout - parent: hiddenAppletActivated ? root.activeApplet.parent : hiddenTasksColumn.contentItem - target: hiddenAppletActivated ? root.activeApplet.parent : null - location: LayoutMirroring.enabled ? PlasmaCore.Types.RightEdge : PlasmaCore.Types.LeftEdge - } } diff --git a/applets/systemtray/package/contents/ui/items/AbstractItem.qml b/applets/systemtray/package/contents/ui/items/AbstractItem.qml index 85908fa7b..f8059fb9b 100644 --- a/applets/systemtray/package/contents/ui/items/AbstractItem.qml +++ b/applets/systemtray/package/contents/ui/items/AbstractItem.qml @@ -1,6 +1,7 @@ /* * Copyright 2016 Marco Martin * Copyright 2020 Konrad Materka + * Copyright 2020 Nate Graham * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as @@ -19,14 +20,15 @@ */ import QtQuick 2.2 +import QtQuick.Layouts 1.1 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents PlasmaCore.ToolTipArea { id: abstractItem - height: inVisibleLayout ? visibleLayout.cellHeight : hiddenLayout.iconItemHeight - width: inVisibleLayout ? visibleLayout.cellWidth : hiddenLayout.width + height: inVisibleLayout ? visibleLayout.cellHeight : hiddenTasks.cellHeight + width: inVisibleLayout ? visibleLayout.cellWidth : hiddenTasks.cellWidth property var model: itemModel @@ -123,21 +125,36 @@ PlasmaCore.ToolTipArea { } } - Row { - spacing: units.smallSpacing - anchors.horizontalCenter: inVisibleLayout ? parent.horizontalCenter : undefined + ColumnLayout { + anchors.fill: abstractItem + spacing: 0 + Item { id: iconContainer - anchors.verticalCenter: parent.verticalCenter - width: inVisibleLayout ? root.itemSize : hiddenLayout.iconItemHeight - height: width - property alias inHiddenLayout: abstractItem.inHiddenLayout + property alias inVisibleLayout: abstractItem.inVisibleLayout + readonly property int size: abstractItem.inVisibleLayout ? root.itemSize : units.iconSizes.medium + + Layout.alignment: Qt.AlignHCenter + implicitWidth: size + implicitHeight: size + Layout.topMargin: abstractItem.inHiddenLayout ? units.smallSpacing : 0 } PlasmaComponents.Label { id: label - anchors.verticalCenter: parent.verticalCenter + + Layout.fillWidth: true + Layout.fillHeight: true + Layout.bottomMargin: abstractItem.inHiddenLayout ? units.smallSpacing : 0 + visible: abstractItem.inHiddenLayout && !root.activeApplet + + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + elide: Text.ElideRight + wrapMode: Text.Wrap + maximumLineCount: 3 + opacity: visible ? 1 : 0 Behavior on opacity { NumberAnimation { diff --git a/applets/systemtray/package/contents/ui/main.qml b/applets/systemtray/package/contents/ui/main.qml index edcc5da55..6cd033a06 100644 --- a/applets/systemtray/package/contents/ui/main.qml +++ b/applets/systemtray/package/contents/ui/main.qml @@ -96,7 +96,6 @@ MouseArea { CurrentItemHighLight { readonly property bool visibleAppletActivated: root.activeApplet && root.activeApplet.parent && root.activeApplet.parent.inVisibleLayout parent: visibleAppletActivated ? root.activeApplet.parent : root - target: visibleAppletActivated ? root.activeApplet.parent : root location: plasmoid.location }