From d3b1da2deff1e3e373ebcad7b4eda70cc74be80c Mon Sep 17 00:00:00 2001 From: Martchus Date: Tue, 12 Sep 2017 00:00:16 +0200 Subject: [PATCH] plasmoid: Customize buttons * Use less space * Fix iconSource when menu present --- plasmoid/lib/CMakeLists.txt | 3 + plasmoid/package/contents/ui/ButtonShadow.qml | 138 ++++++++ plasmoid/package/contents/ui/DetailItem.qml | 2 - plasmoid/package/contents/ui/DevicesPage.qml | 6 +- .../package/contents/ui/DirectoriesPage.qml | 12 +- .../package/contents/ui/DownloadsPage.qml | 4 +- .../contents/ui/FullRepresentation.qml | 24 +- plasmoid/package/contents/ui/TinyButton.qml | 9 + .../package/contents/ui/TinyButtonStyle.qml | 314 ++++++++++++++++++ 9 files changed, 488 insertions(+), 24 deletions(-) create mode 100644 plasmoid/package/contents/ui/ButtonShadow.qml create mode 100644 plasmoid/package/contents/ui/TinyButton.qml create mode 100644 plasmoid/package/contents/ui/TinyButtonStyle.qml diff --git a/plasmoid/lib/CMakeLists.txt b/plasmoid/lib/CMakeLists.txt index f69b788..34c178d 100644 --- a/plasmoid/lib/CMakeLists.txt +++ b/plasmoid/lib/CMakeLists.txt @@ -19,6 +19,9 @@ set(PLASMOID_FILES ../package/contents/ui/DetailView.qml ../package/contents/ui/DetailItem.qml ../package/contents/ui/ToolTipView.qml + ../package/contents/ui/TinyButton.qml + ../package/contents/ui/TinyButtonStyle.qml + ../package/contents/ui/ButtonShadow.qml ../package/contents/ui/main.qml ) list(APPEND QML_SRC_FILES ${PLASMOID_FILES}) diff --git a/plasmoid/package/contents/ui/ButtonShadow.qml b/plasmoid/package/contents/ui/ButtonShadow.qml new file mode 100644 index 0000000..2e93e91 --- /dev/null +++ b/plasmoid/package/contents/ui/ButtonShadow.qml @@ -0,0 +1,138 @@ + +// Imported from Plasma 5.38.0 for TinyButtonStyle.qml which is a customized +// version of Plasma's ToolButtonStyle.qml + +/* + * Copyright (C) 2011 by Daker Fernandes Pinheiro + * Copyright (C) 2011 by Marco Martin + * + * 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 2.010-1301, USA. + */ + +/**Documented API +Inherits: + Item + +Imports: + QtQuick 2.1 + org.kde.plasma.core + +Description: +TODO i need more info here + + +Properties: +**/ +import QtQuick 2.1 +import org.kde.plasma.core 2.0 as PlasmaCore + +Item { + id: main + state: parent.state + //used to tell apart this implementation with the touch components one + property bool hasOverState: true + property alias enabledBorders: shadow.enabledBorders + + PlasmaCore.FrameSvgItem { + id: hover + + anchors { + fill: parent + leftMargin: -margins.left + topMargin: -margins.top + rightMargin: -margins.right + bottomMargin: -margins.bottom + } + opacity: 0 + imagePath: "widgets/button" + prefix: "hover" + } + + PlasmaCore.FrameSvgItem { + id: shadow + + anchors { + fill: parent + leftMargin: -margins.left + topMargin: -margins.top + rightMargin: -margins.right + bottomMargin: -margins.bottom + } + imagePath: "widgets/button" + prefix: "shadow" + } + + states: [ + State { + name: "shadow" + PropertyChanges { + target: shadow + opacity: 1 + } + PropertyChanges { + target: hover + opacity: 0 + prefix: "hover" + } + }, + State { + name: "hover" + PropertyChanges { + target: shadow + opacity: 0 + } + PropertyChanges { + target: hover + opacity: 1 + prefix: "hover" + } + }, + State { + name: "focus" + PropertyChanges { + target: shadow + opacity: 0 + } + PropertyChanges { + target: hover + opacity: 1 + prefix: "focus" + } + }, + State { + name: "hidden" + PropertyChanges { + target: shadow + opacity: 0 + } + PropertyChanges { + target: hover + opacity: 0 + prefix: "hover" + } + } + ] + + transitions: [ + Transition { + PropertyAnimation { + properties: "opacity" + duration: units.longDuration + easing.type: Easing.OutQuad + } + } + ] +} diff --git a/plasmoid/package/contents/ui/DetailItem.qml b/plasmoid/package/contents/ui/DetailItem.qml index 7af78d9..c98add2 100644 --- a/plasmoid/package/contents/ui/DetailItem.qml +++ b/plasmoid/package/contents/ui/DetailItem.qml @@ -8,14 +8,12 @@ RowLayout { Layout.leftMargin: units.iconSizes.smallMedium text: name font.pointSize: theme.defaultFont.pointSize * 0.8 - height: contentHeight elide: Text.ElideRight } PlasmaComponents.Label { Layout.fillWidth: true text: detail font.pointSize: theme.defaultFont.pointSize * 0.8 - height: contentHeight elide: Text.ElideRight } } diff --git a/plasmoid/package/contents/ui/DevicesPage.qml b/plasmoid/package/contents/ui/DevicesPage.qml index 1da4d0d..69ed675 100644 --- a/plasmoid/package/contents/ui/DevicesPage.qml +++ b/plasmoid/package/contents/ui/DevicesPage.qml @@ -28,8 +28,8 @@ Item { RowLayout { PlasmaCore.IconItem { - Layout.preferredWidth: units.iconSizes.smallMedium * 1.1 - Layout.preferredHeight: units.iconSizes.smallMedium * 1.1 + Layout.preferredWidth: units.iconSizes.small + Layout.preferredHeight: units.iconSizes.small anchors.verticalCenter: parent.verticalCenter source: statusIcon } @@ -51,7 +51,7 @@ Item { Item { width: 3 } - PlasmaComponents.ToolButton { + TinyButton { id: barcodeToolButton iconSource: paused ? "media-playback-start" : "media-playback-pause" tooltip: paused ? qsTr("Resume") : qsTr("Pause") diff --git a/plasmoid/package/contents/ui/DirectoriesPage.qml b/plasmoid/package/contents/ui/DirectoriesPage.qml index d332bb0..252a095 100644 --- a/plasmoid/package/contents/ui/DirectoriesPage.qml +++ b/plasmoid/package/contents/ui/DirectoriesPage.qml @@ -30,8 +30,8 @@ Item { id: itemSummary PlasmaCore.IconItem { - Layout.preferredWidth: units.iconSizes.smallMedium * 1.1 - Layout.preferredHeight: units.iconSizes.smallMedium * 1.1 + Layout.preferredWidth: units.iconSizes.small + Layout.preferredHeight: units.iconSizes.small anchors.verticalCenter: parent.verticalCenter source: statusIcon } @@ -54,7 +54,7 @@ Item { Item { width: units.smallSpacing } - PlasmaComponents.ToolButton { + TinyButton { iconSource: "emblem-important" tooltip: qsTr("Show errors") // 5 stands for SyncthingDirStatus::OutOfSync, unfortunately there is currently @@ -66,13 +66,13 @@ Item { plasmoid.expanded = false } } - PlasmaComponents.ToolButton { + TinyButton { iconSource: "view-refresh" tooltip: qsTr("Rescan") onClicked: plasmoid.nativeInterface.connection.rescan( dirId) } - PlasmaComponents.ToolButton { + TinyButton { id: barcodeToolButton iconSource: paused ? "media-playback-start" : "media-playback-pause" tooltip: paused ? qsTr("Resume") : qsTr("Pause") @@ -82,7 +82,7 @@ Item { [dirId]) } } - PlasmaComponents.ToolButton { + TinyButton { iconSource: "folder" tooltip: qsTr("Open in file browser") onClicked: { diff --git a/plasmoid/package/contents/ui/DownloadsPage.qml b/plasmoid/package/contents/ui/DownloadsPage.qml index 39dc0db..53a1938 100644 --- a/plasmoid/package/contents/ui/DownloadsPage.qml +++ b/plasmoid/package/contents/ui/DownloadsPage.qml @@ -56,7 +56,7 @@ Item { Item { width: 3 } - PlasmaComponents.ToolButton { + TinyButton { iconSource: "folder" tooltip: qsTr("Open in file browser") onClicked: { @@ -111,7 +111,7 @@ Item { value: percentage } } - PlasmaComponents.ToolButton { + TinyButton { iconSource: "folder" tooltip: qsTr("Open in file browser") onClicked: { diff --git a/plasmoid/package/contents/ui/FullRepresentation.qml b/plasmoid/package/contents/ui/FullRepresentation.qml index 400ada2..8a10b28 100644 --- a/plasmoid/package/contents/ui/FullRepresentation.qml +++ b/plasmoid/package/contents/ui/FullRepresentation.qml @@ -3,9 +3,9 @@ import QtQuick.Controls 1.4 import QtQuick.Layouts 1.1 import QtQml 2.2 import org.kde.plasma.plasmoid 2.0 -import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.extras 2.0 as PlasmaExtras +import org.kde.plasma.components 2.0 as PlasmaComponents import martchus.syncthingplasmoid 0.6 as SyncthingPlasmoid ColumnLayout { @@ -56,8 +56,9 @@ ColumnLayout { id: toolBar Layout.fillWidth: true - PlasmaComponents.ToolButton { + TinyButton { id: connectButton + states: [ State { name: "disconnected" @@ -113,7 +114,7 @@ ColumnLayout { } } } - PlasmaComponents.ToolButton { + TinyButton { id: startStopButton states: [ @@ -161,13 +162,14 @@ ColumnLayout { } return service.running ? "running" : "stopped" } - onClicked: plasmoid.nativeInterface.service.toggleRunning() + style: TinyButtonStyle { + } } Item { Layout.fillWidth: true } - PlasmaComponents.ToolButton { + TinyButton { tooltip: qsTr("Show own device ID") iconSource: "view-barcode" onClicked: { @@ -175,7 +177,7 @@ ColumnLayout { plasmoid.expanded = false } } - PlasmaComponents.ToolButton { + TinyButton { tooltip: qsTr("Show Syncthing log") iconSource: "text-x-generic" onClicked: { @@ -183,12 +185,12 @@ ColumnLayout { plasmoid.expanded = false } } - PlasmaComponents.ToolButton { + TinyButton { tooltip: qsTr("Rescan all directories") iconSource: "view-refresh" onClicked: plasmoid.nativeInterface.connection.rescanAllDirs() } - PlasmaComponents.ToolButton { + TinyButton { tooltip: qsTr("Settings") iconSource: "preferences-other" onClicked: { @@ -196,7 +198,7 @@ ColumnLayout { plasmoid.expanded = false } } - PlasmaComponents.ToolButton { + TinyButton { tooltip: qsTr("Web UI") iconSource: "internet-web-browser" onClicked: { @@ -251,10 +253,10 @@ ColumnLayout { Layout.fillWidth: true Layout.fillHeight: true } - ToolButton { + TinyButton { text: plasmoid.nativeInterface.currentConnectionConfigName - // FIXME: iconSource doesn't work iconSource: "network-connect" + paddingEnabled: true // FIXME: figure out why menu doesn't work in plasmoidviewer using NVIDIA driver // (works with plasmawindowed or Intel graphics) menu: Menu { diff --git a/plasmoid/package/contents/ui/TinyButton.qml b/plasmoid/package/contents/ui/TinyButton.qml new file mode 100644 index 0000000..046eb04 --- /dev/null +++ b/plasmoid/package/contents/ui/TinyButton.qml @@ -0,0 +1,9 @@ +import org.kde.plasma.components 2.0 as PlasmaComponents + +PlasmaComponents.ToolButton { + property int iconSize: units.iconSizes.small + property bool paddingEnabled: false + + style: TinyButtonStyle { + } +} diff --git a/plasmoid/package/contents/ui/TinyButtonStyle.qml b/plasmoid/package/contents/ui/TinyButtonStyle.qml new file mode 100644 index 0000000..192807a --- /dev/null +++ b/plasmoid/package/contents/ui/TinyButtonStyle.qml @@ -0,0 +1,314 @@ + +// This is a simplified and adjusted version of Plasma's ToolButtonStyle. +// It will make the button only as big as required and allows to disable +// padding. This makes the button a little bit more compact. Additionally, +// the iconSource works also when a menu is present. The ButtonShadow.qml +// file is still used (version from Plasma 5.38.0). +import QtQuick 2.0 +import QtQuick.Controls.Styles 1.1 as QtQuickControlStyle +import QtQuick.Layouts 1.1 +import QtQuick.Controls.Private 1.0 as QtQuickControlsPrivate + +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.extras 2.0 as PlasmaExtras +import org.kde.plasma.components 2.0 as PlasmaComponents + +QtQuickControlStyle.ButtonStyle { + id: style + + property int minimumWidth + property int minimumHeight + property bool flat: control.flat !== undefined ? control.flat : !(control.checkable + && control.checked) + property bool controlHovered: control.hovered + && !(QtQuickControlsPrivate.Settings.hasTouchScreen + && QtQuickControlsPrivate.Settings.isMobile) + + label: RowLayout { + id: buttonContent + spacing: units.smallSpacing + + Layout.preferredWidth: Math.max(control.iconSize, label.implicitWidth) + Layout.preferredHeight: Math.max(control.iconSize, label.implicitHeight) + + PlasmaCore.IconItem { + id: icon + source: control.iconName || control.iconSource + Layout.preferredWidth: control.iconSize + Layout.preferredHeight: control.iconSize + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + active: style.controlHovered + colorGroup: controlHovered + || !flat ? PlasmaCore.Theme.ButtonColorGroup : PlasmaCore.ColorScope.colorGroup + } + + //NOTE: this is used only to check elements existence + PlasmaCore.FrameSvgItem { + id: buttonsurfaceChecker + visible: false + imagePath: "widgets/button" + prefix: style.flat ? ["toolbutton-hover", "normal"] : "normal" + } + + PlasmaComponents.Label { + id: label + anchors.verticalCenter: parent.verticalCenter + text: control.text + textFormat: Text.StyledText + font: control.font || theme.defaultFont + visible: control.text !== "" + Layout.fillWidth: true + color: (controlHovered || !flat) && buttonsurfaceChecker.usedPrefix + !== "toolbutton-hover" ? theme.buttonTextColor : PlasmaCore.ColorScope.textColor + horizontalAlignment: icon.valid ? Text.AlignLeft : Text.AlignHCenter + elide: Text.ElideRight + } + + PlasmaExtras.ConditionalLoader { + id: arrow + when: control.menu !== null + visible: when + Layout.preferredWidth: units.iconSizes.small + Layout.preferredHeight: units.iconSizes.small + + source: Component { + PlasmaCore.SvgItem { + visible: control.menu !== null + svg: PlasmaCore.Svg { + imagePath: "widgets/arrows" + colorGroup: (style.controlHovered || !style.flat) + && buttonsurfaceChecker.usedPrefix + !== "toolbutton-hover" ? PlasmaCore.Theme.ButtonColorGroup : PlasmaCore.ColorScope.colorGroup + } + elementId: "down-arrow" + } + } + } + } + + background: Item { + id: buttonSurface + + Connections { + target: control + onHoveredChanged: { + if (style.controlHovered) { + control.z += 2 + } else { + control.z -= 2 + } + } + } + + ButtonShadow { + id: shadow + visible: !style.flat || control.activeFocus + anchors.fill: parent + enabledBorders: surfaceNormal.enabledBorders + state: { + if (control.pressed) { + return "hidden" + } else if (style.controlHovered) { + return "hover" + } else if (control.activeFocus) { + return "focus" + } else { + return "shadow" + } + } + } + + PlasmaCore.FrameSvgItem { + id: surfaceNormal + anchors.fill: parent + imagePath: "widgets/button" + prefix: style.flat ? ["toolbutton-hover", "normal"] : "normal" + + enabledBorders: { + if (style.flat || !control.parent + || control.parent.width < control.parent.implicitWidth + || control.parent.spacing !== 0 + || !bordersSvg.hasElement( + "pressed-hint-compose-over-border")) { + if (shadows !== null) { + shadows.destroy() + } + return "AllBorders" + } + + var borders = new Array() + if (control.x == 0) { + borders.push("LeftBorder") + shadow.anchors.leftMargin = 0 + } else { + shadow.anchors.leftMargin = -1 + } + if (control.y == 0) { + borders.push("TopBorder") + shadow.anchors.topMargin = 0 + } else { + shadow.anchors.topMargin = -1 + } + if (control.x + control.width >= control.parent.width) { + borders.push("RightBorder") + shadow.anchors.rightMargin = 0 + } else { + shadow.anchors.rightMargin = -1 + } + if (control.y + control.height >= control.parent.height) { + borders.push("BottomBorder") + shadow.anchors.bottomMargin = 0 + } else { + shadow.anchors.bottomMargin = -1 + } + + if (shadows === null) { + shadows = shadowsComponent.createObject(buttonSurface) + } + + return borders.join("|") + } + + PlasmaCore.Svg { + id: bordersSvg + imagePath: "widgets/button" + } + } + + PlasmaCore.FrameSvgItem { + id: surfacePressed + anchors.fill: parent + imagePath: "widgets/button" + prefix: style.flat ? ["toolbutton-pressed", "pressed"] : "pressed" + enabledBorders: surfaceNormal.enabledBorders + opacity: 0 + } + + property Item shadows + Component { + id: shadowsComponent + Item { + anchors.fill: parent + + PlasmaCore.SvgItem { + svg: bordersSvg + width: naturalSize.width + elementId: (buttonSurface.state == "pressed" ? surfacePressed.prefix : surfaceNormal.prefix) + "-left" + visible: button.x > 0 + anchors { + left: parent.left + top: parent.top + bottom: parent.bottom + margins: 1 + leftMargin: -1 + } + } + PlasmaCore.SvgItem { + svg: bordersSvg + width: naturalSize.width + elementId: (buttonSurface.state == "pressed" ? surfacePressed.prefix : surfaceNormal.prefix) + "-right" + visible: button.x + button.width < button.parent.width + anchors { + right: parent.right + top: parent.top + bottom: parent.bottom + margins: 1 + rightMargin: -1 + } + } + PlasmaCore.SvgItem { + svg: bordersSvg + height: naturalSize.height + elementId: (buttonSurface.state == "pressed" ? surfacePressed.prefix : surfaceNormal.prefix) + "-top" + visible: button.y > 0 + anchors { + left: parent.left + top: parent.top + right: parent.right + margins: 1 + topMargin: -1 + } + } + PlasmaCore.SvgItem { + svg: bordersSvg + height: naturalSize.height + elementId: (buttonSurface.state == "pressed" ? surfacePressed.prefix : surfaceNormal.prefix) + "-bottom" + visible: button.y + button.height < button.parent.height + anchors { + left: parent.left + right: parent.right + bottom: parent.bottom + margins: 1 + bottomMargin: -1 + } + } + } + } + + state: (control.pressed + || control.checked ? "pressed" : (style.controlHovered ? "hover" : "normal")) + + states: [ + State { + name: "normal" + PropertyChanges { + target: surfaceNormal + opacity: style.flat ? 0 : 1 + } + PropertyChanges { + target: surfacePressed + opacity: 0 + } + }, + State { + name: "hover" + PropertyChanges { + target: surfaceNormal + opacity: 1 + } + PropertyChanges { + target: surfacePressed + opacity: 0 + } + }, + State { + name: "pressed" + PropertyChanges { + target: surfaceNormal + opacity: 0 + } + PropertyChanges { + target: surfacePressed + opacity: 1 + } + } + ] + + transitions: [ + Transition { + // Cross fade from pressed to normal + ParallelAnimation { + NumberAnimation { + target: surfaceNormal + property: "opacity" + duration: 100 + } + NumberAnimation { + target: surfacePressed + property: "opacity" + duration: 100 + } + } + } + ] + + Component.onCompleted: { + if (control.paddingEnabled) { + padding.top = surfaceNormal.margins.top + padding.left = surfaceNormal.margins.left + padding.right = surfaceNormal.margins.right + padding.bottom = surfaceNormal.margins.bottom + } + } + } +}