Commit 04112536 authored by Konrad Materka's avatar Konrad Materka

[applets/systemtray] Rework of "expanded" state handling

Refactor and simply logic of "expanded" state when dialog with active applet or list of hidden applets is shown.

Fixes a problem with keyboard shortcut activation.
It also fixes a bug when dialog closes on "go-back" button click.

BUG: 427685
FIXED-IN: 5.21
CCBUG: 400278
parent fae151b2
......@@ -35,10 +35,9 @@ Item {
Plasmoid.status: internalSystray ? internalSystray.status : PlasmaCore.Types.UnknownStatus
//synchronize state between SystemTray and wrapping Applet
//the "expanded" property is not really used now, but let's keep it in sync for consistency
Plasmoid.onExpandedChanged: {
if (internalSystray && !plasmoid.expanded) {
internalSystray.expanded = false;
if (internalSystray) {
internalSystray.expanded = plasmoid.expanded
}
}
Connections {
......
......@@ -30,7 +30,7 @@ PlasmaCore.FrameSvgItem {
z: -1 // always draw behind icons
width: parent.width
height: parent.height
opacity: parent && dialog.visible ? 1 : 0
opacity: parent && systemTrayState.expanded ? 1 : 0
function changeHighlightedItem(nextItem) {
parent = nextItem;
......@@ -64,10 +64,28 @@ PlasmaCore.FrameSvgItem {
return prefix;
}
Connections {
target: systemTrayState
function onActiveAppletChanged() {
if (systemTrayState.activeApplet && systemTrayState.activeApplet.parent.inVisibleLayout) {
changeHighlightedItem(systemTrayState.activeApplet.parent.container)
} else if (systemTrayState.expanded) {
changeHighlightedItem(root)
}
}
function onExpandedChanged() {
if (systemTrayState.expanded && !systemTrayState.activeApplet) {
changeHighlightedItemNoAnimation(root)
}
}
}
Behavior on opacity {
NumberAnimation {
duration: units.longDuration
easing.type: parent && dialog.visible ? Easing.OutCubic : Easing.InCubic
easing.type: parent && systemTrayState.expanded ? Easing.OutCubic : Easing.InCubic
}
}
Behavior on x {
......
......@@ -44,7 +44,6 @@ Item {
Layout.preferredHeight: defaultHeight
Layout.maximumHeight: defaultHeight
property alias activeApplet: container.activeApplet
property alias hiddenLayout: hiddenItemsView.layout
// Header
......@@ -72,29 +71,24 @@ Item {
PlasmaComponents.ToolButton {
id: backButton
visible: activeApplet && activeApplet.expanded && (hiddenItemsView.itemCount > 0)
visible: systemTrayState.activeApplet && systemTrayState.activeApplet.expanded && (hiddenItemsView.itemCount > 0)
icon.name: "go-previous"
onClicked: {
if (activeApplet) {
activeApplet.expanded = false;
dialog.visible = true;
}
}
onClicked: systemTrayState.setActiveApplet(null)
}
PlasmaExtras.Heading {
Layout.fillWidth: true
leftPadding: activeApplet ? 0 : units.smallSpacing * 2
leftPadding: systemTrayState.activeApplet ? 0 : units.smallSpacing * 2
level: 1
text: activeApplet ? activeApplet.title : i18n("Status and Notifications")
text: systemTrayState.activeApplet ? systemTrayState.activeApplet.title : i18n("Status and Notifications")
}
PlasmaComponents.ToolButton {
id: actionsButton
visible: visibleActions > 0
checked: configMenu.status !== PC2.DialogStatus.Closed
property QtObject applet: activeApplet || plasmoid
property QtObject applet: systemTrayState.activeApplet || plasmoid
onAppletChanged: {
configMenu.clearMenuItems();
updateVisibleActions();
......@@ -197,7 +191,7 @@ Item {
Layout.fillWidth: true
Layout.fillHeight: true
Layout.topMargin: units.smallSpacing
visible: !activeApplet
visible: !systemTrayState.activeApplet
}
// Container for currently visible item
......@@ -205,14 +199,10 @@ Item {
id: container
Layout.fillWidth: true
Layout.fillHeight: true
visible: activeApplet
visible: systemTrayState.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
// We need to add margin on the top so it matches the dialog's own margin
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
}
}
......
......@@ -28,14 +28,13 @@ PlasmaCore.ToolTipArea {
property bool vertical: plasmoid.formFactor === PlasmaCore.Types.Vertical
implicitWidth: units.iconSizes.smallMedium
implicitHeight: implicitWidth
visible: root.hiddenLayout.itemCount > 0
subText: root.expanded ? i18n("Close popup") : i18n("Show hidden icons")
subText: systemTrayState.expanded ? i18n("Close popup") : i18n("Show hidden icons")
MouseArea {
id: arrowMouseArea
anchors.fill: parent
onClicked: root.expanded = !root.expanded
onClicked: systemTrayState.expanded = !systemTrayState.expanded
readonly property int arrowAnimationDuration: units.shortDuration
......@@ -51,13 +50,13 @@ PlasmaCore.ToolTipArea {
width: Math.min(parent.width, parent.height)
height: width
rotation: root.expanded ? 180 : 0
rotation: systemTrayState.expanded ? 180 : 0
Behavior on rotation {
RotationAnimation {
duration: arrowMouseArea.arrowAnimationDuration
}
}
opacity: root.expanded ? 0 : 1
opacity: systemTrayState.expanded ? 0 : 1
Behavior on opacity {
NumberAnimation {
duration: arrowMouseArea.arrowAnimationDuration
......@@ -83,13 +82,13 @@ PlasmaCore.ToolTipArea {
width: arrow.width
height: arrow.height
rotation: root.expanded ? 0 : -180
rotation: systemTrayState.expanded ? 0 : -180
Behavior on rotation {
RotationAnimation {
duration: arrowMouseArea.arrowAnimationDuration
}
}
opacity: root.expanded ? 1 : 0
opacity: systemTrayState.expanded ? 1 : 0
Behavior on opacity {
NumberAnimation {
duration: arrowMouseArea.arrowAnimationDuration
......
......@@ -42,7 +42,7 @@ MouseArea {
frameVisible: false
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
verticalScrollBarPolicy: root.activeApplet ? Qt.ScrollBarAlwaysOff : Qt.ScrollBarAsNeeded
verticalScrollBarPolicy: systemTrayState.activeApplet ? Qt.ScrollBarAlwaysOff : Qt.ScrollBarAsNeeded
GridView {
id: hiddenTasks
......
......@@ -33,7 +33,7 @@ StackView {
Layout.minimumWidth: units.gridUnit * 12
Layout.minimumHeight: units.gridUnit * 12
property Item activeApplet
readonly property Item activeApplet: systemTrayState.activeApplet
/* Heading */
property bool appletHasHeading: false
......@@ -67,7 +67,7 @@ StackView {
}
}
mainStack.replace({item: activeApplet.fullRepresentationItem, immediate: !dialog.visible, properties: {focus: true}});
mainStack.replace({item: activeApplet.fullRepresentationItem, immediate: !systemTrayState.expanded, properties: {focus: true}});
} else {
mainStack.replace(emptyPage);
}
......@@ -75,7 +75,7 @@ StackView {
Connections {
target: plasmoid
function onAppletRemoved(applet) {
if (applet == root.activeApplet) {
if (applet === systemTrayState.activeApplet) {
mainStack.clear()
}
}
......
/*
* Copyright 2020 Konrad Materka <materka@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import QtQuick 2.12
import org.kde.plasma.core 2.1 as PlasmaCore
import org.kde.plasma.plasmoid 2.0
//This object contains state of the SystemTray, mainly related to the 'expanded' state
QtObject {
//true if System Tray is 'expanded'. It may be when:
// - there is an active applet or
// - 'Status and Notification' with hidden items is shown
property bool expanded: false
//set when there is an applet selected
property Item activeApplet
//allow expanded change only when activated at least once
//this is to suppress expanded state change during Plasma startup
property bool acceptExpandedChange: false
function setActiveApplet(applet) {
const oldApplet = activeApplet
activeApplet = applet
if (oldApplet && oldApplet !== applet) {
oldApplet.expanded = false
}
expanded = true
}
onExpandedChanged: {
if (expanded) {
plasmoid.status = PlasmaCore.Types.RequiresAttentionStatus
} else {
plasmoid.status = PlasmaCore.Types.PassiveStatus;
if (activeApplet) {
// if not expanded we don't have an active applet anymore
activeApplet.expanded = false
activeApplet = null
}
}
acceptExpandedChange = false
plasmoid.expanded = expanded
}
//listen on SystemTray AppletInterface signals
property Connections plasmoidConnections: Connections {
target: plasmoid
//emitted when activation is requested, for example by using a global keyboard shortcut
function onActivated() {
acceptExpandedChange = true
}
//emitted when the configuration dialog is opened
function onUserConfiguringChanged() {
if (plasmoid.userConfiguring) {
systemTrayState.expanded = false
}
}
function onExpandedChanged() {
if (acceptExpandedChange) {
expanded = plasmoid.expanded
} else {
plasmoid.expanded = expanded
}
}
}
property Connections activeAppletConnections: Connections {
target: activeApplet
function onExpandedChanged() {
if (!activeApplet.expanded) {
expanded = false
}
}
}
}
......@@ -151,7 +151,7 @@ PlasmaCore.ToolTipArea {
Layout.rightMargin: abstractItem.inHiddenLayout ? units.smallSpacing : 0
Layout.bottomMargin: abstractItem.inHiddenLayout ? units.smallSpacing : 0
visible: abstractItem.inHiddenLayout && !root.activeApplet
visible: abstractItem.inHiddenLayout
verticalAlignment: Text.AlignTop
horizontalAlignment: Text.AlignHCenter
......
......@@ -31,7 +31,7 @@ AbstractItem {
subText: applet ? applet.toolTipSubText : ""
mainItem: applet && applet.toolTipItem ? applet.toolTipItem : null
textFormat: applet ? applet.toolTipTextFormat : ""
active: root.activeApplet !== applet
active: systemTrayState.activeApplet !== applet
onClicked: {
if (applet && mouse.button === Qt.LeftButton) {
......@@ -70,24 +70,16 @@ AbstractItem {
Connections {
target: applet
//activation using global keyboard shortcut
function onActivated() {
plasmoidContainer.activated()
}
function onExpandedChanged(expanded) {
if (expanded) {
var oldApplet = root.activeApplet;
root.activeApplet = applet;
if (oldApplet && oldApplet !== applet) {
oldApplet.expanded = false;
}
dialog.visible = true;
systemTrayState.setActiveApplet(applet)
plasmoidContainer.activated()
} else if (root.activeApplet === applet) {
// if not expanded we don't have an active applet anymore
root.activeApplet = null;
dialog.visible = false;
}
}
......
......@@ -38,60 +38,27 @@ MouseArea {
LayoutMirroring.enabled: !vertical && Qt.application.layoutDirection === Qt.RightToLeft
LayoutMirroring.childrenInherit: true
readonly property alias systemTrayState: systemTrayState
readonly property alias itemSize: tasksGrid.itemSize
property alias expanded: dialog.visible
property Item activeApplet
property alias visibleLayout: tasksGrid
property alias hiddenLayout: expandedRepresentation.hiddenLayout
Plasmoid.onExpandedChanged: {
if (!plasmoid.expanded) {
dialog.visible = plasmoid.expanded;
}
}
readonly property alias visibleLayout: tasksGrid
readonly property alias hiddenLayout: expandedRepresentation.hiddenLayout
onWheel: {
// Don't propagate unhandled wheel events
wheel.accepted = true;
}
SystemTrayState {
id: systemTrayState
}
//being there forces the items to fully load, and they will be reparented in the popup one by one, this item is *never* visible
Item {
id: preloadedStorage
visible: false
}
Connections {
target: plasmoid
function onUserConfiguringChanged() {
if (plasmoid.userConfiguring) {
dialog.visible = false
}
}
}
CurrentItemHighLight {
property alias activeApplet: root.activeApplet
property alias dialogVisible: dialog.visible
// Not only is an applet active, but also it's an applet from the visible part of the tray, not the hidden part.
readonly property bool visibleAppletActivated: activeApplet && activeApplet.parent && activeApplet.parent.inVisibleLayout
onActiveAppletChanged: {
if (activeApplet && activeApplet.parent.inVisibleLayout) {
changeHighlightedItem(activeApplet.parent.container);
} else if (dialog.visible) {
changeHighlightedItem(root);
}
}
onDialogVisibleChanged: {
if (dialogVisible && !activeApplet) {
changeHighlightedItemNoAnimation(root);
}
}
location: plasmoid.location
}
......@@ -239,6 +206,7 @@ MouseArea {
id: expander
Layout.fillWidth: vertical
Layout.fillHeight: !vertical
visible: root.hiddenLayout.itemCount > 0
}
}
......@@ -249,27 +217,18 @@ MouseArea {
flags: Qt.WindowStaysOnTopHint
location: plasmoid.location
hideOnWindowDeactivate: !plasmoid.configuration.pin
visible: systemTrayState.expanded
onVisibleChanged: {
if (!visible) {
plasmoid.status = PlasmaCore.Types.PassiveStatus;
if (root.activeApplet) {
root.activeApplet.expanded = false;
}
} else {
plasmoid.status = PlasmaCore.Types.RequiresAttentionStatus;
}
plasmoid.expanded = visible;
systemTrayState.expanded = visible
}
mainItem: ExpandedRepresentation {
id: expandedRepresentation
Keys.onEscapePressed: {
root.expanded = false;
systemTrayState.expanded = false
}
activeApplet: root.activeApplet
LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft
LayoutMirroring.childrenInherit: true
}
......
......@@ -64,6 +64,12 @@ void SystemTray::init()
m_plasmoidRegistry = new PlasmoidRegistry(m_settings, this);
connect(m_plasmoidRegistry, &PlasmoidRegistry::plasmoidEnabled, this, &SystemTray::startApplet);
connect(m_plasmoidRegistry, &PlasmoidRegistry::plasmoidStopped, this, &SystemTray::stopApplet);
//we don't want to automatically propagate the activated signal from the Applet to the Containment
//even if SystemTray is of type Containment, it is de facto Applet and should act like one
connect(this, &Containment::appletAdded, this, [this](Plasma::Applet *applet) {
disconnect(applet, &Applet::activated, this, &Applet::activated);
});
}
void SystemTray::restoreContents(KConfigGroup &group)
......@@ -73,6 +79,12 @@ void SystemTray::restoreContents(KConfigGroup &group)
return;
}
KConfigGroup shortcutConfig(&group, "Shortcuts");
QString shortcutText = shortcutConfig.readEntryUntranslated("global", QString());
if (!shortcutText.isEmpty()) {
setGlobalShortcut(QKeySequence(shortcutText));
}
//cache known config group ids for applets
KConfigGroup cg = group.group("Applets");
for (const QString &group : cg.groupList()) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment