diff options
| -rw-r--r-- | config/Config.qml | 2 | ||||
| -rw-r--r-- | config/DContentConfig.qml | 11 | ||||
| -rw-r--r-- | modules/bar/popouts/Background.qml | 2 | ||||
| -rw-r--r-- | modules/bar/popouts/Bluetooth.qml | 38 | ||||
| -rw-r--r-- | modules/bar/popouts/Content.qml | 4 | ||||
| -rw-r--r-- | modules/bar/popouts/Wrapper.qml | 22 | ||||
| -rw-r--r-- | modules/detachedcontent/DetachedContent.qml | 98 | ||||
| -rw-r--r-- | modules/detachedcontent/NavRail.qml | 193 | ||||
| -rw-r--r-- | modules/detachedcontent/Session.qml | 5 |
9 files changed, 372 insertions, 3 deletions
diff --git a/config/Config.qml b/config/Config.qml index 1ab8cb4..8756a12 100644 --- a/config/Config.qml +++ b/config/Config.qml @@ -11,6 +11,7 @@ Singleton { property alias bar: adapter.bar property alias border: adapter.border property alias dashboard: adapter.dashboard + property alias dcontent: adapter.dcontent property alias launcher: adapter.launcher property alias notifs: adapter.notifs property alias osd: adapter.osd @@ -33,6 +34,7 @@ Singleton { property BarConfig bar: BarConfig {} property BorderConfig border: BorderConfig {} property DashboardConfig dashboard: DashboardConfig {} + property DContentConfig dcontent: DContentConfig {} property LauncherConfig launcher: LauncherConfig {} property NotifsConfig notifs: NotifsConfig {} property OsdConfig osd: OsdConfig {} diff --git a/config/DContentConfig.qml b/config/DContentConfig.qml new file mode 100644 index 0000000..13afbd2 --- /dev/null +++ b/config/DContentConfig.qml @@ -0,0 +1,11 @@ +import Quickshell.Io + +JsonObject { + property Sizes sizes: Sizes {} + + component Sizes: JsonObject { + property real heightMult: 0.7 + property real ratio: 16 / 9 + property real expandedNavWidth: 180 + } +} diff --git a/modules/bar/popouts/Background.qml b/modules/bar/popouts/Background.qml index f7d568f..14f5f20 100644 --- a/modules/bar/popouts/Background.qml +++ b/modules/bar/popouts/Background.qml @@ -8,7 +8,7 @@ ShapePath { required property Wrapper wrapper required property bool invertBottomRounding - readonly property real rounding: Config.border.rounding + readonly property real rounding: wrapper.isDetached ? Appearance.rounding.normal : Config.border.rounding readonly property bool flatten: wrapper.width < rounding * 2 readonly property real roundingX: flatten ? wrapper.width / 2 : rounding property real ibr: invertBottomRounding ? -1 : 1 diff --git a/modules/bar/popouts/Bluetooth.qml b/modules/bar/popouts/Bluetooth.qml index 5b1127f..56dd4a4 100644 --- a/modules/bar/popouts/Bluetooth.qml +++ b/modules/bar/popouts/Bluetooth.qml @@ -12,6 +12,8 @@ import QtQuick.Layouts ColumnLayout { id: root + required property Item wrapper + spacing: Appearance.spacing.small StyledText { @@ -170,6 +172,42 @@ ColumnLayout { } } + StyledRect { + Layout.topMargin: Appearance.spacing.small + implicitWidth: expandBtn.implicitWidth + Appearance.padding.normal * 2 + implicitHeight: expandBtn.implicitHeight + Appearance.padding.small + + radius: Appearance.rounding.normal + color: Colours.palette.m3primaryContainer + + StateLayer { + color: Colours.palette.m3onPrimaryContainer + + function onClicked(): void { + root.wrapper.detach("bluetooth"); + } + } + + RowLayout { + id: expandBtn + + anchors.centerIn: parent + spacing: Appearance.spacing.small + + StyledText { + Layout.leftMargin: Appearance.padding.smaller + text: qsTr("Open panel") + color: Colours.palette.m3onPrimaryContainer + } + + MaterialIcon { + text: "chevron_right" + color: Colours.palette.m3onPrimaryContainer + font.pointSize: Appearance.font.size.large + } + } + } + component Toggle: RowLayout { required property string label property alias checked: toggle.checked diff --git a/modules/bar/popouts/Content.qml b/modules/bar/popouts/Content.qml index 684f702..42e138d 100644 --- a/modules/bar/popouts/Content.qml +++ b/modules/bar/popouts/Content.qml @@ -35,7 +35,9 @@ Item { Popout { name: "bluetooth" - source: "Bluetooth.qml" + sourceComponent: Bluetooth { + wrapper: root.wrapper + } } Popout { diff --git a/modules/bar/popouts/Wrapper.qml b/modules/bar/popouts/Wrapper.qml index 293f9d5..9a7f7c1 100644 --- a/modules/bar/popouts/Wrapper.qml +++ b/modules/bar/popouts/Wrapper.qml @@ -3,6 +3,7 @@ pragma ComponentBehavior: Bound import qs.services import qs.config import qs.modules.windowinfo +import qs.modules.detachedcontent import Quickshell import Quickshell.Wayland import Quickshell.Hyprland @@ -21,6 +22,7 @@ Item { property bool hasCurrent property string detachedMode + property string queuedMode readonly property bool isDetached: detachedMode.length > 0 property int animLength: Appearance.anim.durations.normal @@ -28,7 +30,12 @@ Item { function detach(mode: string): void { animLength = Appearance.anim.durations.large; - detachedMode = mode; + if (mode === "winfo") { + detachedMode = mode; + } else { + detachedMode = "any"; + queuedMode = mode; + } focus = true; } @@ -86,6 +93,19 @@ Item { } } + Comp { + id: detachedContent + + shouldBeActive: root.detachedMode === "any" + asynchronous: true + anchors.centerIn: parent + + sourceComponent: DetachedContent { + screen: root.screen + active: root.queuedMode + } + } + Behavior on x { Anim { duration: root.animLength diff --git a/modules/detachedcontent/DetachedContent.qml b/modules/detachedcontent/DetachedContent.qml new file mode 100644 index 0000000..4226917 --- /dev/null +++ b/modules/detachedcontent/DetachedContent.qml @@ -0,0 +1,98 @@ +pragma ComponentBehavior: Bound + +import qs.widgets +import qs.services +import qs.config +import Quickshell +import QtQuick +import QtQuick.Layouts +import QtQuick.Effects + +Item { + id: root + + required property ShellScreen screen + property alias active: session.active + readonly property Session session: Session { + id: session + } + + implicitWidth: implicitHeight * Config.dcontent.sizes.ratio + implicitHeight: screen.height * Config.dcontent.sizes.heightMult + + GridLayout { + anchors.fill: parent + + rows: 2 + columns: 2 + rowSpacing: 0 + columnSpacing: 0 + + StyledRect { + Layout.fillHeight: true + Layout.rowSpan: 2 + + topLeftRadius: Appearance.rounding.normal + bottomLeftRadius: Appearance.rounding.normal + implicitWidth: navRail.implicitWidth + color: Colours.palette.m3surfaceContainer + + NavRail { + id: navRail + + session: root.session + } + } + + StyledRect { + Layout.fillWidth: true + implicitHeight: 50 + topRightRadius: Appearance.rounding.normal + color: Colours.palette.m3surfaceContainer + } + + Item { + Layout.fillWidth: true + Layout.fillHeight: true + + StyledText { + anchors.centerIn: parent + text: qsTr("Work in progress") + color: Colours.palette.m3outline + font.pointSize: Appearance.font.size.extraLarge + font.weight: 500 + } + + StyledRect { + anchors.fill: parent + color: Colours.palette.m3surfaceContainer + bottomRightRadius: Appearance.rounding.normal + + layer.enabled: true + layer.effect: MultiEffect { + maskSource: mask + maskEnabled: true + maskInverted: true + maskThresholdMin: 0.5 + maskSpreadAtMin: 1 + } + } + + Item { + id: mask + + anchors.fill: parent + layer.enabled: true + visible: false + + Rectangle { + anchors.fill: parent + anchors.margins: Appearance.padding.normal + anchors.topMargin: 0 + anchors.leftMargin: 0 + radius: Appearance.rounding.small + } + } + } + } +} diff --git a/modules/detachedcontent/NavRail.qml b/modules/detachedcontent/NavRail.qml new file mode 100644 index 0000000..fb30c06 --- /dev/null +++ b/modules/detachedcontent/NavRail.qml @@ -0,0 +1,193 @@ +pragma ComponentBehavior: Bound + +import qs.widgets +import qs.services +import qs.config +import QtQuick +import QtQuick.Layouts + +Item { + id: root + + required property Session session + property bool expanded + + implicitWidth: layout.implicitWidth + Appearance.padding.large * 4 + implicitHeight: layout.implicitHeight + Appearance.padding.large * 2 + + ColumnLayout { + id: layout + + anchors.centerIn: parent + spacing: Appearance.spacing.normal + + states: State { + name: "expanded" + when: root.expanded + + PropertyChanges { + layout.spacing: Appearance.spacing.small / 2 + menuIcon.opacity: 0 + menuIconExpanded.opacity: 1 + menuIcon.rotation: 180 + menuIconExpanded.rotation: 0 + } + AnchorChanges { + target: menuIcon + anchors.horizontalCenter: undefined + } + AnchorChanges { + target: menuIconExpanded + anchors.horizontalCenter: undefined + } + } + + transitions: Transition { + Anim { + properties: "spacing,opacity,rotation" + } + } + + Item { + Layout.fillWidth: true + Layout.bottomMargin: Appearance.spacing.small / 2 + implicitHeight: Math.max(menuIcon.implicitHeight, menuIconExpanded.implicitHeight) + Appearance.padding.normal * 2 + + StateLayer { + radius: Appearance.rounding.small + + function onClicked(): void { + root.expanded = !root.expanded; + } + } + + MaterialIcon { + id: menuIcon + + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + text: "menu" + font.pointSize: Appearance.font.size.large + } + + MaterialIcon { + id: menuIconExpanded + + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + text: "menu_open" + font.pointSize: Appearance.font.size.large + opacity: 0 + rotation: -180 + } + } + + NavItem { + icon: "settings_bluetooth" + label: "bluetooth" + } + } + + component NavItem: Item { + id: item + + required property string icon + required property string label + readonly property bool active: root.session.active === label + + implicitWidth: background.implicitWidth + implicitHeight: background.implicitHeight + smallLabel.implicitHeight + smallLabel.anchors.topMargin + + states: State { + name: "expanded" + when: root.expanded + + PropertyChanges { + expandedLabel.opacity: 1 + smallLabel.opacity: 0 + background.implicitWidth: Config.dcontent.sizes.expandedNavWidth + background.implicitHeight: icon.implicitHeight + Appearance.padding.normal * 2 + item.implicitHeight: background.implicitHeight + } + } + + transitions: Transition { + Anim { + property: "opacity" + duration: Appearance.anim.durations.small + } + + Anim { + properties: "implicitWidth,implicitHeight" + duration: Appearance.anim.durations.expressiveDefaultSpatial + easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial + } + } + + StyledRect { + id: background + + radius: Appearance.rounding.full + color: item.active ? Colours.palette.m3secondaryContainer : Colours.palette.m3surfaceContainer + + implicitWidth: icon.implicitWidth + icon.anchors.leftMargin * 2 + implicitHeight: icon.implicitHeight + Appearance.padding.small + + StateLayer { + color: item.active ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface + + function onClicked(): void { + root.session.active = item.label; + } + } + + MaterialIcon { + id: icon + + anchors.left: parent.left + anchors.verticalCenter: parent.verticalCenter + anchors.leftMargin: Appearance.padding.large + + text: item.icon + color: item.active ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface + font.pointSize: Appearance.font.size.large + fill: item.active ? 1 : 0 + + Behavior on fill { + Anim {} + } + } + + StyledText { + id: expandedLabel + + anchors.left: icon.right + anchors.verticalCenter: parent.verticalCenter + anchors.leftMargin: Appearance.spacing.small + + opacity: 0 + text: item.label + color: item.active ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface + font.capitalization: Font.Capitalize + } + + StyledText { + id: smallLabel + + anchors.horizontalCenter: icon.horizontalCenter + anchors.top: icon.bottom + anchors.topMargin: Appearance.spacing.small / 2 + + text: item.label + font.pointSize: Appearance.font.size.small + font.capitalization: Font.Capitalize + } + } + } + + component Anim: NumberAnimation { + duration: Appearance.anim.durations.normal + easing.type: Easing.BezierSpline + easing.bezierCurve: Appearance.anim.curves.standard + } +} diff --git a/modules/detachedcontent/Session.qml b/modules/detachedcontent/Session.qml new file mode 100644 index 0000000..a3f2de5 --- /dev/null +++ b/modules/detachedcontent/Session.qml @@ -0,0 +1,5 @@ +import QtQuick + +QtObject { + property string active +} |