From dca1d63717368e7fa965f7e67ea28d0de2e523d3 Mon Sep 17 00:00:00 2001 From: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> Date: Sun, 7 Jun 2026 22:38:43 +1000 Subject: [PATCH] feat: completely remove control center --- README.md | 2 +- modules/controlcenter/ControlCenter.qml | 99 --- modules/controlcenter/NavRail.qml | 226 ----- modules/controlcenter/PaneRegistry.qml | 98 --- modules/controlcenter/Panes.qml | 182 ---- modules/controlcenter/Session.qml | 23 - modules/controlcenter/WindowFactory.qml | 59 -- modules/controlcenter/WindowTitle.qml | 49 -- .../appearance/AppearancePane.qml | 265 ------ .../appearance/sections/AnimationsSection.qml | 44 - .../appearance/sections/BackgroundSection.qml | 346 -------- .../appearance/sections/BorderSection.qml | 68 -- .../sections/ColorSchemeSection.qml | 147 ---- .../sections/ColorVariantSection.qml | 91 -- .../appearance/sections/FontsSection.qml | 289 ------ .../appearance/sections/ScalesSection.qml | 92 -- .../appearance/sections/ThemeModeSection.qml | 23 - .../sections/TransparencySection.qml | 79 -- modules/controlcenter/audio/AudioPane.qml | 623 ------------- modules/controlcenter/bluetooth/BtPane.qml | 74 -- modules/controlcenter/bluetooth/Details.qml | 663 -------------- .../controlcenter/bluetooth/DeviceList.qml | 265 ------ modules/controlcenter/bluetooth/Settings.qml | 521 ----------- .../components/ConnectedButtonGroup.qml | 114 --- .../components/DeviceDetails.qml | 74 -- .../controlcenter/components/DeviceList.qml | 84 -- .../components/PaneTransition.qml | 67 -- .../components/ReadonlySlider.qml | 67 -- .../components/SettingsHeader.qml | 35 - .../controlcenter/components/SliderInput.qml | 180 ---- .../components/SplitPaneLayout.qml | 109 --- .../components/SplitPaneWithDetails.qml | 95 -- .../components/WallpaperGrid.qml | 233 ----- .../controlcenter/dashboard/DashboardPane.qml | 138 --- .../dashboard/GeneralSection.qml | 128 --- .../dashboard/PerformanceSection.qml | 107 --- .../controlcenter/launcher/LauncherPane.qml | 665 -------------- modules/controlcenter/launcher/Settings.qml | 208 ----- .../controlcenter/network/EthernetDetails.qml | 118 --- .../controlcenter/network/EthernetList.qml | 177 ---- .../controlcenter/network/EthernetPane.qml | 50 -- .../network/EthernetSettings.qml | 75 -- .../controlcenter/network/NetworkSettings.qml | 170 ---- .../controlcenter/network/NetworkingPane.qml | 379 -------- modules/controlcenter/network/VpnDetails.qml | 542 ------------ modules/controlcenter/network/VpnList.qml | 827 ------------------ modules/controlcenter/network/VpnSettings.qml | 257 ------ .../controlcenter/network/WirelessDetails.qml | 213 ----- .../controlcenter/network/WirelessList.qml | 225 ----- .../controlcenter/network/WirelessPane.qml | 57 -- .../network/WirelessPasswordDialog.qml | 522 ----------- .../network/WirelessSettings.qml | 73 -- .../notifications/NotificationsPane.qml | 425 --------- .../controlcenter/state/BluetoothState.qml | 12 - modules/controlcenter/state/EthernetState.qml | 7 - modules/controlcenter/state/LauncherState.qml | 7 - modules/controlcenter/state/NetworkState.qml | 9 - modules/controlcenter/state/VpnState.qml | 5 - modules/controlcenter/taskbar/TaskbarPane.qml | 792 ----------------- plugin/src/Caelestia/Config/CMakeLists.txt | 1 - plugin/src/Caelestia/Config/config.cpp | 3 - plugin/src/Caelestia/Config/config.hpp | 3 - .../src/Caelestia/Config/configattached.cpp | 1 - .../src/Caelestia/Config/configattached.hpp | 3 - .../src/Caelestia/Config/launcherconfig.hpp | 2 +- plugin/src/Caelestia/Config/tokens.hpp | 14 - 66 files changed, 2 insertions(+), 11599 deletions(-) delete mode 100644 modules/controlcenter/ControlCenter.qml delete mode 100644 modules/controlcenter/NavRail.qml delete mode 100644 modules/controlcenter/PaneRegistry.qml delete mode 100644 modules/controlcenter/Panes.qml delete mode 100644 modules/controlcenter/Session.qml delete mode 100644 modules/controlcenter/WindowFactory.qml delete mode 100644 modules/controlcenter/WindowTitle.qml delete mode 100644 modules/controlcenter/appearance/AppearancePane.qml delete mode 100644 modules/controlcenter/appearance/sections/AnimationsSection.qml delete mode 100644 modules/controlcenter/appearance/sections/BackgroundSection.qml delete mode 100644 modules/controlcenter/appearance/sections/BorderSection.qml delete mode 100644 modules/controlcenter/appearance/sections/ColorSchemeSection.qml delete mode 100644 modules/controlcenter/appearance/sections/ColorVariantSection.qml delete mode 100644 modules/controlcenter/appearance/sections/FontsSection.qml delete mode 100644 modules/controlcenter/appearance/sections/ScalesSection.qml delete mode 100644 modules/controlcenter/appearance/sections/ThemeModeSection.qml delete mode 100644 modules/controlcenter/appearance/sections/TransparencySection.qml delete mode 100644 modules/controlcenter/audio/AudioPane.qml delete mode 100644 modules/controlcenter/bluetooth/BtPane.qml delete mode 100644 modules/controlcenter/bluetooth/Details.qml delete mode 100644 modules/controlcenter/bluetooth/DeviceList.qml delete mode 100644 modules/controlcenter/bluetooth/Settings.qml delete mode 100644 modules/controlcenter/components/ConnectedButtonGroup.qml delete mode 100644 modules/controlcenter/components/DeviceDetails.qml delete mode 100644 modules/controlcenter/components/DeviceList.qml delete mode 100644 modules/controlcenter/components/PaneTransition.qml delete mode 100644 modules/controlcenter/components/ReadonlySlider.qml delete mode 100644 modules/controlcenter/components/SettingsHeader.qml delete mode 100644 modules/controlcenter/components/SliderInput.qml delete mode 100644 modules/controlcenter/components/SplitPaneLayout.qml delete mode 100644 modules/controlcenter/components/SplitPaneWithDetails.qml delete mode 100644 modules/controlcenter/components/WallpaperGrid.qml delete mode 100644 modules/controlcenter/dashboard/DashboardPane.qml delete mode 100644 modules/controlcenter/dashboard/GeneralSection.qml delete mode 100644 modules/controlcenter/dashboard/PerformanceSection.qml delete mode 100644 modules/controlcenter/launcher/LauncherPane.qml delete mode 100644 modules/controlcenter/launcher/Settings.qml delete mode 100644 modules/controlcenter/network/EthernetDetails.qml delete mode 100644 modules/controlcenter/network/EthernetList.qml delete mode 100644 modules/controlcenter/network/EthernetPane.qml delete mode 100644 modules/controlcenter/network/EthernetSettings.qml delete mode 100644 modules/controlcenter/network/NetworkSettings.qml delete mode 100644 modules/controlcenter/network/NetworkingPane.qml delete mode 100644 modules/controlcenter/network/VpnDetails.qml delete mode 100644 modules/controlcenter/network/VpnList.qml delete mode 100644 modules/controlcenter/network/VpnSettings.qml delete mode 100644 modules/controlcenter/network/WirelessDetails.qml delete mode 100644 modules/controlcenter/network/WirelessList.qml delete mode 100644 modules/controlcenter/network/WirelessPane.qml delete mode 100644 modules/controlcenter/network/WirelessPasswordDialog.qml delete mode 100644 modules/controlcenter/network/WirelessSettings.qml delete mode 100644 modules/controlcenter/notifications/NotificationsPane.qml delete mode 100644 modules/controlcenter/state/BluetoothState.qml delete mode 100644 modules/controlcenter/state/EthernetState.qml delete mode 100644 modules/controlcenter/state/LauncherState.qml delete mode 100644 modules/controlcenter/state/NetworkState.qml delete mode 100644 modules/controlcenter/state/VpnState.qml delete mode 100644 modules/controlcenter/taskbar/TaskbarPane.qml diff --git a/README.md b/README.md index 1dfbd205..0c47e15d 100644 --- a/README.md +++ b/README.md @@ -609,7 +609,7 @@ For example, to disable the bar on DP-1: "name": "Settings", "icon": "settings", "description": "Configure the shell", - "command": ["caelestia", "shell", "controlCenter", "open"], + "command": ["caelestia", "shell", "nexus", "open"], "enabled": true, "dangerous": false } diff --git a/modules/controlcenter/ControlCenter.qml b/modules/controlcenter/ControlCenter.qml deleted file mode 100644 index 57bea637..00000000 --- a/modules/controlcenter/ControlCenter.qml +++ /dev/null @@ -1,99 +0,0 @@ -pragma ComponentBehavior: Bound - -import QtQuick -import QtQuick.Layouts -import Quickshell -import Caelestia.Config -import qs.components -import qs.components.controls -import qs.services - -Item { - id: root - - required property ShellScreen screen - readonly property int rounding: floating ? 0 : Tokens.rounding.extraLarge - - property alias floating: session.floating - property alias active: session.active - property alias navExpanded: session.navExpanded - - readonly property bool initialOpeningComplete: panes.initialOpeningComplete - readonly property Session session: Session { - id: session - - root: root - } - - signal close - - implicitWidth: implicitHeight * Tokens.sizes.controlCenter.ratio - implicitHeight: screen.height * Tokens.sizes.controlCenter.heightMult - - GridLayout { - anchors.fill: parent - - rowSpacing: 0 - columnSpacing: 0 - rows: root.floating ? 2 : 1 - columns: 2 - - Loader { - Layout.fillWidth: true - Layout.columnSpan: 2 - - asynchronous: true - active: root.floating - visible: active - - sourceComponent: WindowTitle { - screen: root.screen - session: root.session - } - } - - StyledRect { - Layout.fillHeight: true - - topLeftRadius: root.rounding - bottomLeftRadius: root.rounding - implicitWidth: navRail.implicitWidth - color: Colours.tPalette.m3surfaceContainer - - CustomMouseArea { - function onWheel(event: WheelEvent): void { - // Prevent tab switching during initial opening animation to avoid blank pages - if (!panes.initialOpeningComplete) { - return; - } - - if (event.angleDelta.y < 0) - root.session.activeIndex = Math.min(root.session.activeIndex + 1, root.session.panes.length - 1); - else if (event.angleDelta.y > 0) - root.session.activeIndex = Math.max(root.session.activeIndex - 1, 0); - } - - anchors.fill: parent - } - - NavRail { - id: navRail - - screen: root.screen - session: root.session - initialOpeningComplete: root.initialOpeningComplete - } - } - - Panes { - id: panes - - Layout.fillWidth: true - Layout.fillHeight: true - - topRightRadius: root.rounding - bottomRightRadius: root.rounding - session: root.session - } - } -} diff --git a/modules/controlcenter/NavRail.qml b/modules/controlcenter/NavRail.qml deleted file mode 100644 index 85a367e4..00000000 --- a/modules/controlcenter/NavRail.qml +++ /dev/null @@ -1,226 +0,0 @@ -pragma ComponentBehavior: Bound - -import QtQuick -import QtQuick.Layouts -import Quickshell -import Caelestia.Config -import qs.components -import qs.services -import qs.modules.controlcenter - -Item { - id: root - - required property ShellScreen screen - required property Session session - required property bool initialOpeningComplete - - implicitWidth: layout.implicitWidth + Tokens.padding.extraExtraLarge - implicitHeight: layout.implicitHeight + Tokens.padding.extraLargeIncreased - - ColumnLayout { - id: layout - - anchors.left: parent.left - anchors.verticalCenter: parent.verticalCenter - anchors.leftMargin: Tokens.padding.medium * 2 - spacing: Tokens.spacing.medium - - states: State { - name: "expanded" - when: root.session.navExpanded - - PropertyChanges { - layout.spacing: root.Tokens.spacing.small - } - } - - transitions: Transition { - Anim { - properties: "spacing" - } - } - - Loader { - Layout.topMargin: Tokens.spacing.largeIncreased - asynchronous: true - active: !root.session.floating - visible: active - - sourceComponent: StyledRect { - readonly property int nonAnimWidth: normalWinIcon.implicitWidth + (root.session.navExpanded ? normalWinLabel.anchors.leftMargin + normalWinLabel.implicitWidth : 0) + normalWinIcon.anchors.leftMargin * 2 - - implicitWidth: nonAnimWidth - implicitHeight: root.session.navExpanded ? normalWinIcon.implicitHeight + Tokens.padding.medium * 2 : nonAnimWidth - - color: Colours.palette.m3primaryContainer - radius: Tokens.rounding.medium - - StateLayer { - id: normalWinState - - onClicked: { - root.session.root.close(); - WindowFactory.create(null, { - active: root.session.active, - navExpanded: root.session.navExpanded - }); - } - - color: Colours.palette.m3onPrimaryContainer - } - - MaterialIcon { - id: normalWinIcon - - anchors.left: parent.left - anchors.verticalCenter: parent.verticalCenter - anchors.leftMargin: Tokens.padding.large - - text: "select_window" - color: Colours.palette.m3onPrimaryContainer - fontStyle: Tokens.font.icon.large - fill: 1 - } - - StyledText { - id: normalWinLabel - - anchors.left: normalWinIcon.right - anchors.verticalCenter: parent.verticalCenter - anchors.leftMargin: Tokens.spacing.medium - - text: qsTr("Float window") - color: Colours.palette.m3onPrimaryContainer - opacity: root.session.navExpanded ? 1 : 0 - - Behavior on opacity { - Anim { - type: Anim.StandardSmall - } - } - } - - Behavior on implicitWidth { - Anim {} - } - - Behavior on implicitHeight { - Anim {} - } - } - } - - Repeater { - model: PaneRegistry.count - - NavItem { - required property int index - - Layout.topMargin: index === 0 ? Tokens.spacing.largeIncreased * 2 : 0 - icon: PaneRegistry.getByIndex(index).icon - label: PaneRegistry.getByIndex(index).label - } - } - } - - 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.session.navExpanded - - PropertyChanges { - expandedLabel.opacity: 1 - smallLabel.opacity: 0 - background.implicitWidth: icon.implicitWidth + icon.anchors.leftMargin * 2 + expandedLabel.anchors.leftMargin + expandedLabel.implicitWidth - background.implicitHeight: icon.implicitHeight + root.Tokens.padding.medium * 2 - item.implicitHeight: background.implicitHeight - } - } - - transitions: Transition { - Anim { - property: "opacity" - type: Anim.StandardSmall - } - - Anim { - properties: "implicitWidth,implicitHeight" - } - } - - StyledRect { - id: background - - radius: Tokens.rounding.full - color: Qt.alpha(Colours.palette.m3secondaryContainer, item.active ? 1 : 0) - - implicitWidth: icon.implicitWidth + icon.anchors.leftMargin * 2 - implicitHeight: icon.implicitHeight + Tokens.padding.extraSmall - - StateLayer { - onClicked: { - // Prevent tab switching during initial opening animation to avoid blank pages - if (!root.initialOpeningComplete) { - return; - } - root.session.active = item.label; - } - - color: item.active ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface - } - - MaterialIcon { - id: icon - - anchors.left: parent.left - anchors.verticalCenter: parent.verticalCenter - anchors.leftMargin: Tokens.padding.large - - text: item.icon - color: item.active ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface - fontStyle: Tokens.font.icon.large - fill: item.active ? 1 : 0 - - Behavior on fill { - Anim { - type: Anim.DefaultEffects - } - } - } - - StyledText { - id: expandedLabel - - anchors.left: icon.right - anchors.verticalCenter: parent.verticalCenter - anchors.leftMargin: Tokens.spacing.medium - - opacity: 0 - text: item.label - color: item.active ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface - font: Tokens.font.label.builders.medium.capitalisation(Font.Capitalize).build() - } - - StyledText { - id: smallLabel - - anchors.horizontalCenter: icon.horizontalCenter - anchors.top: icon.bottom - anchors.topMargin: Tokens.spacing.extraSmall - - text: item.label - font: Tokens.font.label.builders.small.capitalisation(Font.Capitalize).build() - } - } - } -} diff --git a/modules/controlcenter/PaneRegistry.qml b/modules/controlcenter/PaneRegistry.qml deleted file mode 100644 index 4d85969b..00000000 --- a/modules/controlcenter/PaneRegistry.qml +++ /dev/null @@ -1,98 +0,0 @@ -pragma Singleton - -import QtQuick - -QtObject { - id: root - - readonly property list panes: [ - QtObject { - readonly property string id: "network" - readonly property string label: "network" - readonly property string icon: "router" - readonly property string component: "network/NetworkingPane.qml" - }, - QtObject { - readonly property string id: "bluetooth" - readonly property string label: "bluetooth" - readonly property string icon: "settings_bluetooth" - readonly property string component: "bluetooth/BtPane.qml" - }, - QtObject { - readonly property string id: "audio" - readonly property string label: "audio" - readonly property string icon: "volume_up" - readonly property string component: "audio/AudioPane.qml" - }, - QtObject { - readonly property string id: "appearance" - readonly property string label: "appearance" - readonly property string icon: "palette" - readonly property string component: "appearance/AppearancePane.qml" - }, - QtObject { - readonly property string id: "taskbar" - readonly property string label: "taskbar" - readonly property string icon: "task_alt" - readonly property string component: "taskbar/TaskbarPane.qml" - }, - QtObject { - readonly property string id: "notifications" - readonly property string label: "notifications" - readonly property string icon: "notifications" - readonly property string component: "notifications/NotificationsPane.qml" - }, - QtObject { - readonly property string id: "launcher" - readonly property string label: "launcher" - readonly property string icon: "apps" - readonly property string component: "launcher/LauncherPane.qml" - }, - QtObject { - readonly property string id: "dashboard" - readonly property string label: "dashboard" - readonly property string icon: "dashboard" - readonly property string component: "dashboard/DashboardPane.qml" - } - ] - - readonly property int count: panes.length - - readonly property var labels: { - const result = []; - for (let i = 0; i < panes.length; i++) { - result.push(panes[i].label); - } - return result; - } - - function getByIndex(index: int): var { - if (index >= 0 && index < panes.length) { - return panes[index]; - } - return null; - } - - function getIndexByLabel(label: string): int { - for (let i = 0; i < panes.length; i++) { - if (panes[i].label === label) { - return i; - } - } - return -1; - } - - function getByLabel(label: string): var { - const index = getIndexByLabel(label); - return getByIndex(index); - } - - function getById(id: string): var { - for (let i = 0; i < panes.length; i++) { - if (panes[i].id === id) { - return panes[i]; - } - } - return null; - } -} diff --git a/modules/controlcenter/Panes.qml b/modules/controlcenter/Panes.qml deleted file mode 100644 index c3a8e21b..00000000 --- a/modules/controlcenter/Panes.qml +++ /dev/null @@ -1,182 +0,0 @@ -pragma ComponentBehavior: Bound - -import "bluetooth" -import "network" -import "audio" -import "appearance" -import "taskbar" -import "notifications" -import "launcher" -import "dashboard" -import QtQuick -import QtQuick.Layouts -import Quickshell.Widgets -import Caelestia.Config -import qs.components -import qs.services -import qs.modules.controlcenter - -ClippingRectangle { - id: root - - required property Session session - - readonly property bool initialOpeningComplete: layout.initialOpeningComplete - - color: "transparent" - clip: true - focus: false - activeFocusOnTab: false - - MouseArea { - anchors.fill: parent - z: -1 - onPressed: function (mouse) { - root.focus = true; - mouse.accepted = false; - } - } - - Connections { - function onActiveIndexChanged(): void { - root.focus = true; - } - - target: root.session - } - - ColumnLayout { - id: layout - - property bool animationComplete: true - property bool initialOpeningComplete: false - - spacing: 0 - y: -root.session.activeIndex * root.height - clip: true - - Timer { - id: animationDelayTimer - - interval: Tokens.anim.durations.normal - onTriggered: { - layout.animationComplete = true; - } - } - - Timer { - id: initialOpeningTimer - - interval: Tokens.anim.durations.large - running: true - onTriggered: { - layout.initialOpeningComplete = true; - } - } - - Repeater { - model: PaneRegistry.count - - Pane { - required property int index - - paneIndex: index - componentPath: PaneRegistry.getByIndex(index).component - } - } - - Behavior on y { - Anim {} - } - - Connections { - function onActiveIndexChanged(): void { - layout.animationComplete = false; - animationDelayTimer.restart(); - } - - target: root.session - } - } - - component Pane: Item { - id: pane - - required property int paneIndex - required property string componentPath - property bool hasBeenLoaded: false - - function updateActive(): void { - const diff = Math.abs(root.session.activeIndex - pane.paneIndex); - const isActivePane = diff === 0; - let shouldBeActive = false; - - if (!layout.initialOpeningComplete) { - shouldBeActive = isActivePane; - } else { - if (diff <= 1) { - shouldBeActive = true; - } else if (pane.hasBeenLoaded) { - shouldBeActive = true; - } else { - shouldBeActive = layout.animationComplete; - } - } - - loader.active = shouldBeActive; - } - - implicitWidth: root.width - implicitHeight: root.height - - Loader { - id: loader - - anchors.fill: parent - asynchronous: true - clip: false - active: false - - Component.onCompleted: { - Qt.callLater(pane.updateActive); - } - - onActiveChanged: { - if (active && !pane.hasBeenLoaded) { - pane.hasBeenLoaded = true; - } - - if (active && !item) { - loader.setSource(pane.componentPath, { - "session": root.session - }); - } - } - - onItemChanged: { - if (item) { - pane.hasBeenLoaded = true; - } - } - } - - Connections { - function onActiveIndexChanged(): void { - pane.updateActive(); - } - - target: root.session - } - - Connections { - function onInitialOpeningCompleteChanged(): void { - pane.updateActive(); - } - function onAnimationCompleteChanged(): void { - pane.updateActive(); - } - - target: layout - } - } -} diff --git a/modules/controlcenter/Session.qml b/modules/controlcenter/Session.qml deleted file mode 100644 index e3839681..00000000 --- a/modules/controlcenter/Session.qml +++ /dev/null @@ -1,23 +0,0 @@ -import "./state" -import QtQuick -import qs.modules.controlcenter - -QtObject { - readonly property list panes: PaneRegistry.labels - - required property var root - property bool floating: false - property string active: "network" - property int activeIndex: 0 - property bool navExpanded: false - - readonly property BluetoothState bt: BluetoothState {} - readonly property NetworkState network: NetworkState {} - readonly property EthernetState ethernet: EthernetState {} - readonly property LauncherState launcher: LauncherState {} - readonly property VpnState vpn: VpnState {} - - onActiveChanged: activeIndex = Math.max(0, panes.indexOf(active)) - onActiveIndexChanged: if (panes[activeIndex]) - active = panes[activeIndex] -} diff --git a/modules/controlcenter/WindowFactory.qml b/modules/controlcenter/WindowFactory.qml deleted file mode 100644 index dc0dc4a0..00000000 --- a/modules/controlcenter/WindowFactory.qml +++ /dev/null @@ -1,59 +0,0 @@ -pragma Singleton - -import QtQuick -import Quickshell -import qs.components -import qs.services - -Singleton { - id: root - - function create(parent: Item, props: var): void { - controlCenter.createObject(parent ?? dummy, props); - } - - QtObject { - id: dummy - } - - Component { - id: controlCenter - - FloatingWindow { - id: win - - property alias active: cc.active - property alias navExpanded: cc.navExpanded - - color: Colours.tPalette.m3surface - - onVisibleChanged: { - if (!visible) - destroy(); - } - - implicitWidth: cc.implicitWidth - implicitHeight: cc.implicitHeight - - minimumSize.width: implicitWidth - minimumSize.height: implicitHeight - maximumSize.width: implicitWidth - maximumSize.height: implicitHeight - - title: qsTr("Caelestia Settings - %1").arg(cc.active.slice(0, 1).toUpperCase() + cc.active.slice(1)) - - ControlCenter { - id: cc - - anchors.fill: parent - screen: win.screen - onClose: win.destroy() - floating: true - } - - Behavior on color { - CAnim {} - } - } - } -} diff --git a/modules/controlcenter/WindowTitle.qml b/modules/controlcenter/WindowTitle.qml deleted file mode 100644 index 143168a2..00000000 --- a/modules/controlcenter/WindowTitle.qml +++ /dev/null @@ -1,49 +0,0 @@ -import QtQuick -import Quickshell -import Caelestia.Config -import qs.components -import qs.services - -StyledRect { - id: root - - required property ShellScreen screen - required property Session session - - implicitHeight: text.implicitHeight + Tokens.padding.medium - color: Colours.tPalette.m3surfaceContainer - - StyledText { - id: text - - anchors.horizontalCenter: parent.horizontalCenter - anchors.bottom: parent.bottom - - text: qsTr("Caelestia Settings - %1").arg(root.session.active) - font: Tokens.font.title.builders.medium.capitalisation(Font.Capitalize).weight(Font.Medium).build() - } - - Item { - anchors.right: parent.right - anchors.top: parent.top - anchors.margins: Tokens.padding.medium - - implicitWidth: implicitHeight - implicitHeight: closeIcon.implicitHeight + Tokens.padding.extraSmall - - StateLayer { - onClicked: { - QsWindow.window.destroy(); - } - - radius: Tokens.rounding.full - } - - MaterialIcon { - id: closeIcon - - anchors.centerIn: parent - text: "close" - } - } -} diff --git a/modules/controlcenter/appearance/AppearancePane.qml b/modules/controlcenter/appearance/AppearancePane.qml deleted file mode 100644 index 33676862..00000000 --- a/modules/controlcenter/appearance/AppearancePane.qml +++ /dev/null @@ -1,265 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "../components" -import "./sections" -import "../../launcher/services" -import QtQuick -import QtQuick.Layouts -import Quickshell -import Quickshell.Widgets -import Caelestia.Config -import Caelestia.Models -import qs.components -import qs.components.containers -import qs.components.controls -import qs.components.effects -import qs.components.images -import qs.services -import qs.utils - -Item { - id: root - - required property Session session - - property real animDurationsScale: GlobalConfig.appearance.anim.durations.scale ?? 1 - property string fontFamilyMaterial: Config.appearance.font.family.material ?? "Material Symbols Rounded" - property string fontFamilyMono: Config.appearance.font.family.mono ?? "CaskaydiaCove NF" - property string fontFamilySans: Config.appearance.font.family.sans ?? "Rubik" - property real fontSizeScale: Config.appearance.font.size.scale ?? 1 - property real paddingScale: Config.appearance.padding.scale ?? 1 - property real roundingScale: Config.appearance.rounding.scale ?? 1 - property real spacingScale: Config.appearance.spacing.scale ?? 1 - property bool transparencyEnabled: GlobalConfig.appearance.transparency.enabled ?? false - property real transparencyBase: GlobalConfig.appearance.transparency.base ?? 0.85 - property real transparencyLayers: GlobalConfig.appearance.transparency.layers ?? 0.4 - property real borderRounding: Config.border.rounding ?? 1 - property real borderThickness: Config.border.thickness ?? 1 - - property bool desktopClockEnabled: Config.background.desktopClock.enabled ?? false - property real desktopClockScale: Config.background.desktopClock.scale ?? 1 - property string desktopClockPosition: Config.background.desktopClock.position ?? "bottom-right" - property bool desktopClockShadowEnabled: Config.background.desktopClock.shadow.enabled ?? true - property real desktopClockShadowOpacity: Config.background.desktopClock.shadow.opacity ?? 0.7 - property real desktopClockShadowBlur: Config.background.desktopClock.shadow.blur ?? 0.4 - property bool desktopClockBackgroundEnabled: Config.background.desktopClock.background.enabled ?? false - property real desktopClockBackgroundOpacity: Config.background.desktopClock.background.opacity ?? 0.7 - property bool desktopClockBackgroundBlur: Config.background.desktopClock.background.blur ?? false - property bool desktopClockInvertColors: Config.background.desktopClock.invertColors ?? false - property bool backgroundEnabled: Config.background.enabled ?? true - property bool wallpaperEnabled: Config.background.wallpaperEnabled ?? true - property bool visualiserEnabled: Config.background.visualiser.enabled ?? false - property bool visualiserAutoHide: Config.background.visualiser.autoHide ?? true - property real visualiserRounding: Config.background.visualiser.rounding ?? 1 - property real visualiserSpacing: Config.background.visualiser.spacing ?? 1 - - function saveConfig() { - GlobalConfig.appearance.anim.durations.scale = root.animDurationsScale; - - GlobalConfig.appearance.font.family.material = root.fontFamilyMaterial; - GlobalConfig.appearance.font.family.mono = root.fontFamilyMono; - GlobalConfig.appearance.font.family.sans = root.fontFamilySans; - GlobalConfig.appearance.font.size.scale = root.fontSizeScale; - - GlobalConfig.appearance.padding.scale = root.paddingScale; - GlobalConfig.appearance.rounding.scale = root.roundingScale; - GlobalConfig.appearance.spacing.scale = root.spacingScale; - - GlobalConfig.appearance.transparency.enabled = root.transparencyEnabled; - GlobalConfig.appearance.transparency.base = root.transparencyBase; - GlobalConfig.appearance.transparency.layers = root.transparencyLayers; - - GlobalConfig.background.desktopClock.enabled = root.desktopClockEnabled; - GlobalConfig.background.enabled = root.backgroundEnabled; - GlobalConfig.background.desktopClock.scale = root.desktopClockScale; - GlobalConfig.background.desktopClock.position = root.desktopClockPosition; - GlobalConfig.background.desktopClock.shadow.enabled = root.desktopClockShadowEnabled; - GlobalConfig.background.desktopClock.shadow.opacity = root.desktopClockShadowOpacity; - GlobalConfig.background.desktopClock.shadow.blur = root.desktopClockShadowBlur; - GlobalConfig.background.desktopClock.background.enabled = root.desktopClockBackgroundEnabled; - GlobalConfig.background.desktopClock.background.opacity = root.desktopClockBackgroundOpacity; - GlobalConfig.background.desktopClock.background.blur = root.desktopClockBackgroundBlur; - GlobalConfig.background.desktopClock.invertColors = root.desktopClockInvertColors; - - GlobalConfig.background.wallpaperEnabled = root.wallpaperEnabled; - - GlobalConfig.background.visualiser.enabled = root.visualiserEnabled; - GlobalConfig.background.visualiser.autoHide = root.visualiserAutoHide; - GlobalConfig.background.visualiser.rounding = root.visualiserRounding; - GlobalConfig.background.visualiser.spacing = root.visualiserSpacing; - - GlobalConfig.border.rounding = root.borderRounding; - GlobalConfig.border.thickness = root.borderThickness; - } - - anchors.fill: parent - - Component { - id: appearanceRightContentComponent - - Item { - id: rightAppearanceFlickable - - ColumnLayout { - id: contentLayout - - anchors.fill: parent - spacing: 0 - - StyledText { - Layout.alignment: Qt.AlignHCenter - Layout.bottomMargin: Tokens.spacing.medium - text: qsTr("Wallpaper") - font: Tokens.font.body.builders.large.size(28).weight(Font.DemiBold).build() - } - - Loader { - id: wallpaperLoader - - Layout.fillWidth: true - Layout.fillHeight: true - Layout.bottomMargin: -Tokens.padding.extraLargeIncreased - - asynchronous: true - active: { - const isActive = root.session.activeIndex === 3; - const isAdjacent = Math.abs(root.session.activeIndex - 3) === 1; - const splitLayout = root.children[0]; - const loader = splitLayout && splitLayout.rightLoader ? splitLayout.rightLoader : null; - const shouldActivate = loader && loader.item !== null && (isActive || isAdjacent); - return shouldActivate; - } - - onStatusChanged: { - if (status === Loader.Error) { - console.error(lc, "Wallpaper loader error!"); - } - } - - sourceComponent: WallpaperGrid { - session: root.session - } - } - } - } - } - - SplitPaneLayout { - anchors.fill: parent - - leftContent: Component { - StyledFlickable { - id: sidebarFlickable - - readonly property var rootPane: root - - flickableDirection: Flickable.VerticalFlick - contentHeight: sidebarLayout.height - - StyledScrollBar.vertical: StyledScrollBar { - flickable: sidebarFlickable - } - - ColumnLayout { - id: sidebarLayout - - readonly property var rootPane: sidebarFlickable.rootPane - readonly property bool allSectionsExpanded: themeModeSection.expanded && colorVariantSection.expanded && colorSchemeSection.expanded && animationsSection.expanded && fontsSection.expanded && scalesSection.expanded && transparencySection.expanded && borderSection.expanded && backgroundSection.expanded - - anchors.left: parent.left - anchors.right: parent.right - spacing: Tokens.spacing.small - - RowLayout { - spacing: Tokens.spacing.medium - - StyledText { - text: qsTr("Appearance") - font: Tokens.font.body.builders.large.weight(Font.Medium).build() - } - - Item { - Layout.fillWidth: true - } - - IconButton { - icon: sidebarLayout.allSectionsExpanded ? "unfold_less" : "unfold_more" - type: IconButton.Text - label.animate: true - onClicked: { - const shouldExpand = !sidebarLayout.allSectionsExpanded; - themeModeSection.expanded = shouldExpand; - colorVariantSection.expanded = shouldExpand; - colorSchemeSection.expanded = shouldExpand; - animationsSection.expanded = shouldExpand; - fontsSection.expanded = shouldExpand; - scalesSection.expanded = shouldExpand; - transparencySection.expanded = shouldExpand; - borderSection.expanded = shouldExpand; - backgroundSection.expanded = shouldExpand; - } - } - } - - ThemeModeSection { - id: themeModeSection - } - - ColorVariantSection { - id: colorVariantSection - } - - ColorSchemeSection { - id: colorSchemeSection - } - - AnimationsSection { - id: animationsSection - - rootPane: sidebarFlickable.rootPane - } - - FontsSection { - id: fontsSection - - rootPane: sidebarFlickable.rootPane - } - - ScalesSection { - id: scalesSection - - rootPane: sidebarFlickable.rootPane - } - - TransparencySection { - id: transparencySection - - rootPane: sidebarFlickable.rootPane - } - - BorderSection { - id: borderSection - - rootPane: sidebarFlickable.rootPane - } - - BackgroundSection { - id: backgroundSection - - rootPane: sidebarFlickable.rootPane - } - } - } - } - - rightContent: appearanceRightContentComponent - } - - LoggingCategory { - id: lc - - name: "caelestia.qml.controlcenter.appearance" - defaultLogLevel: LoggingCategory.Info - } -} diff --git a/modules/controlcenter/appearance/sections/AnimationsSection.qml b/modules/controlcenter/appearance/sections/AnimationsSection.qml deleted file mode 100644 index 921d3abe..00000000 --- a/modules/controlcenter/appearance/sections/AnimationsSection.qml +++ /dev/null @@ -1,44 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "../../components" -import QtQuick -import QtQuick.Layouts -import Caelestia.Config -import qs.components -import qs.components.containers -import qs.components.controls -import qs.services - -CollapsibleSection { - id: root - - required property var rootPane - - title: qsTr("Animations") - showBackground: true - - SectionContainer { - contentSpacing: Tokens.spacing.medium - - SliderInput { - Layout.fillWidth: true - - label: qsTr("Animation duration scale") - value: rootPane.animDurationsScale - from: 0.1 - to: 5.0 - decimals: 1 - suffix: "×" - validator: DoubleValidator { - bottom: 0.1 - top: 5.0 - } - - onValueModified: newValue => { - rootPane.animDurationsScale = newValue; - rootPane.saveConfig(); - } - } - } -} diff --git a/modules/controlcenter/appearance/sections/BackgroundSection.qml b/modules/controlcenter/appearance/sections/BackgroundSection.qml deleted file mode 100644 index 75018df2..00000000 --- a/modules/controlcenter/appearance/sections/BackgroundSection.qml +++ /dev/null @@ -1,346 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "../../components" -import QtQuick -import QtQuick.Layouts -import Caelestia.Config -import qs.components -import qs.components.containers -import qs.components.controls -import qs.services - -CollapsibleSection { - id: root - - required property var rootPane - - title: qsTr("Background") - showBackground: true - - SwitchRow { - label: qsTr("Background enabled") - checked: rootPane.backgroundEnabled - onToggled: checked => { - rootPane.backgroundEnabled = checked; - rootPane.saveConfig(); - } - } - - SwitchRow { - label: qsTr("Wallpaper enabled") - checked: rootPane.wallpaperEnabled - onToggled: checked => { - rootPane.wallpaperEnabled = checked; - rootPane.saveConfig(); - } - } - - StyledText { - Layout.topMargin: Tokens.spacing.medium - text: qsTr("Desktop Clock") - font: Tokens.font.body.builders.large.weight(Font.Medium).build() - } - - SwitchRow { - label: qsTr("Desktop Clock enabled") - checked: rootPane.desktopClockEnabled - onToggled: checked => { - rootPane.desktopClockEnabled = checked; - rootPane.saveConfig(); - } - } - - SectionContainer { - id: posContainer - - readonly property var pos: (rootPane.desktopClockPosition || "top-left").split('-') - readonly property string currentV: pos[0] - readonly property string currentH: pos[1] - - function updateClockPos(v, h) { - rootPane.desktopClockPosition = v + "-" + h; - rootPane.saveConfig(); - } - - contentSpacing: Tokens.spacing.small - z: 1 - - StyledText { - text: qsTr("Positioning") - font: Tokens.font.body.builders.large.weight(Font.Medium).build() - } - - SplitButtonRow { - label: qsTr("Vertical Position") - enabled: rootPane.desktopClockEnabled - - menuItems: [ - MenuItem { - property string val: "top" - - text: qsTr("Top") - icon: "vertical_align_top" - }, - MenuItem { - property string val: "middle" - - text: qsTr("Middle") - icon: "vertical_align_center" - }, - MenuItem { - property string val: "bottom" - - text: qsTr("Bottom") - icon: "vertical_align_bottom" - } - ] - - Component.onCompleted: { - for (let i = 0; i < menuItems.length; i++) { - if (menuItems[i].val === posContainer.currentV) - active = menuItems[i]; - } - } - - // The signal from SplitButtonRow - onSelected: item => posContainer.updateClockPos(item.val, posContainer.currentH) - } - - SplitButtonRow { - label: qsTr("Horizontal Position") - enabled: rootPane.desktopClockEnabled - expandedZ: 99 - - menuItems: [ - MenuItem { - property string val: "left" - - text: qsTr("Left") - icon: "align_horizontal_left" - }, - MenuItem { - property string val: "center" - - text: qsTr("Center") - icon: "align_horizontal_center" - }, - MenuItem { - property string val: "right" - - text: qsTr("Right") - icon: "align_horizontal_right" - } - ] - - Component.onCompleted: { - for (let i = 0; i < menuItems.length; i++) { - if (menuItems[i].val === posContainer.currentH) - active = menuItems[i]; - } - } - - onSelected: item => posContainer.updateClockPos(posContainer.currentV, item.val) - } - } - - SwitchRow { - label: qsTr("Invert colors") - checked: rootPane.desktopClockInvertColors - onToggled: checked => { - rootPane.desktopClockInvertColors = checked; - rootPane.saveConfig(); - } - } - - SectionContainer { - contentSpacing: Tokens.spacing.small - - StyledText { - text: qsTr("Shadow") - font: Tokens.font.body.builders.large.weight(Font.Medium).build() - } - - SwitchRow { - label: qsTr("Enabled") - checked: rootPane.desktopClockShadowEnabled - onToggled: checked => { - rootPane.desktopClockShadowEnabled = checked; - rootPane.saveConfig(); - } - } - - SectionContainer { - contentSpacing: Tokens.spacing.medium - - SliderInput { - Layout.fillWidth: true - - label: qsTr("Opacity") - value: rootPane.desktopClockShadowOpacity * 100 - from: 0 - to: 100 - suffix: "%" - validator: IntValidator { - bottom: 0 - top: 100 - } - formatValueFunction: val => Math.round(val).toString() - parseValueFunction: text => parseInt(text) - - onValueModified: newValue => { - rootPane.desktopClockShadowOpacity = newValue / 100; - rootPane.saveConfig(); - } - } - } - - SectionContainer { - contentSpacing: Tokens.spacing.medium - - SliderInput { - Layout.fillWidth: true - - label: qsTr("Blur") - value: rootPane.desktopClockShadowBlur * 100 - from: 0 - to: 100 - suffix: "%" - validator: IntValidator { - bottom: 0 - top: 100 - } - formatValueFunction: val => Math.round(val).toString() - parseValueFunction: text => parseInt(text) - - onValueModified: newValue => { - rootPane.desktopClockShadowBlur = newValue / 100; - rootPane.saveConfig(); - } - } - } - } - - SectionContainer { - contentSpacing: Tokens.spacing.small - - StyledText { - text: qsTr("Background") - font: Tokens.font.body.builders.large.weight(Font.Medium).build() - } - - SwitchRow { - label: qsTr("Enabled") - checked: rootPane.desktopClockBackgroundEnabled - onToggled: checked => { - rootPane.desktopClockBackgroundEnabled = checked; - rootPane.saveConfig(); - } - } - - SwitchRow { - label: qsTr("Blur enabled") - checked: rootPane.desktopClockBackgroundBlur - onToggled: checked => { - rootPane.desktopClockBackgroundBlur = checked; - rootPane.saveConfig(); - } - } - - SectionContainer { - contentSpacing: Tokens.spacing.medium - - SliderInput { - Layout.fillWidth: true - - label: qsTr("Opacity") - value: rootPane.desktopClockBackgroundOpacity * 100 - from: 0 - to: 100 - suffix: "%" - validator: IntValidator { - bottom: 0 - top: 100 - } - formatValueFunction: val => Math.round(val).toString() - parseValueFunction: text => parseInt(text) - - onValueModified: newValue => { - rootPane.desktopClockBackgroundOpacity = newValue / 100; - rootPane.saveConfig(); - } - } - } - } - - StyledText { - Layout.topMargin: Tokens.spacing.medium - text: qsTr("Visualiser") - font: Tokens.font.body.builders.large.weight(Font.Medium).build() - } - - SwitchRow { - label: qsTr("Visualiser enabled") - checked: rootPane.visualiserEnabled - onToggled: checked => { - rootPane.visualiserEnabled = checked; - rootPane.saveConfig(); - } - } - - SwitchRow { - label: qsTr("Visualiser auto hide") - checked: rootPane.visualiserAutoHide - onToggled: checked => { - rootPane.visualiserAutoHide = checked; - rootPane.saveConfig(); - } - } - - SectionContainer { - contentSpacing: Tokens.spacing.medium - - SliderInput { - Layout.fillWidth: true - - label: qsTr("Visualiser rounding") - value: rootPane.visualiserRounding - from: 0 - to: 10 - stepSize: 1 - validator: IntValidator { - bottom: 0 - top: 10 - } - formatValueFunction: val => Math.round(val).toString() - parseValueFunction: text => parseInt(text) - - onValueModified: newValue => { - rootPane.visualiserRounding = Math.round(newValue); - rootPane.saveConfig(); - } - } - } - - SectionContainer { - contentSpacing: Tokens.spacing.medium - - SliderInput { - Layout.fillWidth: true - - label: qsTr("Visualiser spacing") - value: rootPane.visualiserSpacing - from: 0 - to: 2 - validator: DoubleValidator { - bottom: 0 - top: 2 - } - - onValueModified: newValue => { - rootPane.visualiserSpacing = newValue; - rootPane.saveConfig(); - } - } - } -} diff --git a/modules/controlcenter/appearance/sections/BorderSection.qml b/modules/controlcenter/appearance/sections/BorderSection.qml deleted file mode 100644 index 71bb6faf..00000000 --- a/modules/controlcenter/appearance/sections/BorderSection.qml +++ /dev/null @@ -1,68 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "../../components" -import QtQuick -import QtQuick.Layouts -import Caelestia.Config -import qs.components -import qs.components.containers -import qs.components.controls -import qs.services - -CollapsibleSection { - id: root - - required property var rootPane - - title: qsTr("Border") - showBackground: true - - SectionContainer { - contentSpacing: Tokens.spacing.medium - - SliderInput { - Layout.fillWidth: true - - label: qsTr("Border rounding") - value: rootPane.borderRounding - from: 0.1 - to: 100 - decimals: 1 - suffix: "px" - validator: DoubleValidator { - bottom: 0.1 - top: 100 - } - - onValueModified: newValue => { - rootPane.borderRounding = newValue; - rootPane.saveConfig(); - } - } - } - - SectionContainer { - contentSpacing: Tokens.spacing.medium - - SliderInput { - Layout.fillWidth: true - - label: qsTr("Border thickness") - value: rootPane.borderThickness - from: 0 - to: 100 - decimals: 1 - suffix: "px" - validator: DoubleValidator { - bottom: 0.1 - top: 100 - } - - onValueModified: newValue => { - rootPane.borderThickness = newValue; - rootPane.saveConfig(); - } - } - } -} diff --git a/modules/controlcenter/appearance/sections/ColorSchemeSection.qml b/modules/controlcenter/appearance/sections/ColorSchemeSection.qml deleted file mode 100644 index 5841d05c..00000000 --- a/modules/controlcenter/appearance/sections/ColorSchemeSection.qml +++ /dev/null @@ -1,147 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "../../../launcher/services" -import QtQuick -import QtQuick.Layouts -import Quickshell -import Caelestia.Config -import qs.components -import qs.components.containers -import qs.components.controls -import qs.services - -CollapsibleSection { - title: qsTr("Color scheme") - description: qsTr("Available color schemes") - showBackground: true - - ColumnLayout { - Layout.fillWidth: true - spacing: Tokens.spacing.extraSmall - - Repeater { - model: Schemes.list - - delegate: StyledRect { - required property var modelData - - Layout.fillWidth: true - - readonly property string schemeKey: `${modelData.name} ${modelData.flavour}` - readonly property bool isCurrent: schemeKey === Schemes.currentScheme - - color: Qt.alpha(Colours.tPalette.m3surfaceContainer, isCurrent ? Colours.tPalette.m3surfaceContainer.a : 0) - radius: Tokens.rounding.large - border.width: isCurrent ? 1 : 0 - border.color: Colours.palette.m3primary - implicitHeight: schemeRow.implicitHeight + Tokens.padding.medium * 2 - - StateLayer { - onClicked: { - const name = modelData.name; - const flavour = modelData.flavour; - const schemeKey = `${name} ${flavour}`; - - Schemes.currentScheme = schemeKey; - Quickshell.execDetached(["caelestia", "scheme", "set", "-n", name, "-f", flavour]); - - Qt.callLater(() => { - reloadTimer.restart(); - }); - } - } - - Timer { - id: reloadTimer - - interval: 300 - onTriggered: { - Schemes.reload(); - } - } - - RowLayout { - id: schemeRow - - anchors.fill: parent - anchors.margins: Tokens.padding.medium - - spacing: Tokens.spacing.medium - - StyledRect { - id: preview - - Layout.alignment: Qt.AlignVCenter - - border.width: 1 - border.color: Qt.alpha(`#${modelData.colours?.outline}`, 0.5) - - color: `#${modelData.colours?.surface}` - radius: Tokens.rounding.full - implicitWidth: iconPlaceholder.implicitWidth - implicitHeight: iconPlaceholder.implicitWidth - - MaterialIcon { - id: iconPlaceholder - - visible: false - text: "circle" - fontStyle: Tokens.font.icon.large - } - - Item { - anchors.top: parent.top - anchors.bottom: parent.bottom - anchors.right: parent.right - - implicitWidth: parent.implicitWidth / 2 - clip: true - - StyledRect { - anchors.top: parent.top - anchors.bottom: parent.bottom - anchors.right: parent.right - - implicitWidth: preview.implicitWidth - color: `#${modelData.colours?.primary}` - radius: Tokens.rounding.full - } - } - } - - Column { - Layout.fillWidth: true - spacing: 0 - - StyledText { - text: modelData.flavour ?? "" - font: Tokens.font.body.medium - } - - StyledText { - text: modelData.name ?? "" - font: Tokens.font.body.small - color: Colours.palette.m3outline - - elide: Text.ElideRight - anchors.left: parent.left - anchors.right: parent.right - } - } - - Loader { - asynchronous: true - active: isCurrent - - sourceComponent: MaterialIcon { - text: "check" - color: Colours.palette.m3onSurfaceVariant - fontStyle: Tokens.font.icon.large - } - } - } - } - } - } -} diff --git a/modules/controlcenter/appearance/sections/ColorVariantSection.qml b/modules/controlcenter/appearance/sections/ColorVariantSection.qml deleted file mode 100644 index 3d0198aa..00000000 --- a/modules/controlcenter/appearance/sections/ColorVariantSection.qml +++ /dev/null @@ -1,91 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "../../../launcher/services" -import QtQuick -import QtQuick.Layouts -import Quickshell -import Caelestia.Config -import qs.components -import qs.components.containers -import qs.components.controls -import qs.services - -CollapsibleSection { - title: qsTr("Color variant") - description: qsTr("Material theme variant") - showBackground: true - - ColumnLayout { - Layout.fillWidth: true - spacing: Tokens.spacing.extraSmall - - Repeater { - model: M3Variants.list - - delegate: StyledRect { - required property var modelData - - Layout.fillWidth: true - - color: Qt.alpha(Colours.tPalette.m3surfaceContainer, modelData.variant === Schemes.currentVariant ? Colours.tPalette.m3surfaceContainer.a : 0) - radius: Tokens.rounding.large - border.width: modelData.variant === Schemes.currentVariant ? 1 : 0 - border.color: Colours.palette.m3primary - implicitHeight: variantRow.implicitHeight + Tokens.padding.medium * 2 - - StateLayer { - onClicked: { - const variant = modelData.variant; - - Schemes.currentVariant = variant; - Quickshell.execDetached(["caelestia", "scheme", "set", "-v", variant]); - - Qt.callLater(() => { - reloadTimer.restart(); - }); - } - } - - Timer { - id: reloadTimer - - interval: 300 - onTriggered: { - Schemes.reload(); - } - } - - RowLayout { - id: variantRow - - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - anchors.margins: Tokens.padding.medium - - spacing: Tokens.spacing.medium - - MaterialIcon { - text: modelData.icon - fontStyle: Tokens.font.icon.large - fill: modelData.variant === Schemes.currentVariant ? 1 : 0 - } - - StyledText { - Layout.fillWidth: true - text: modelData.name - font: modelData.variant === Schemes.currentVariant ? Tokens.font.body.builders.small.weight(Font.Medium).build() : Tokens.font.body.builders.small.weight(Font.Normal).build() - } - - MaterialIcon { - visible: modelData.variant === Schemes.currentVariant - text: "check" - color: Colours.palette.m3primary - fontStyle: Tokens.font.icon.large - } - } - } - } - } -} diff --git a/modules/controlcenter/appearance/sections/FontsSection.qml b/modules/controlcenter/appearance/sections/FontsSection.qml deleted file mode 100644 index 03bec48f..00000000 --- a/modules/controlcenter/appearance/sections/FontsSection.qml +++ /dev/null @@ -1,289 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "../../components" -import QtQuick -import QtQuick.Layouts -import Caelestia.Config -import qs.components -import qs.components.containers -import qs.components.controls -import qs.services - -CollapsibleSection { - id: root - - required property var rootPane - - title: qsTr("Fonts") - showBackground: true - - CollapsibleSection { - id: sansFontSection - - title: qsTr("Sans-serif font family") - expanded: true - showBackground: true - nested: true - - Loader { - Layout.fillWidth: true - Layout.preferredHeight: item ? Math.min(item.contentHeight, 300) : 0 - asynchronous: true - active: sansFontSection.expanded - - sourceComponent: StyledListView { - id: sansFontList - - property alias contentHeight: sansFontList.contentHeight - - clip: true - spacing: Tokens.spacing.extraSmall - model: Qt.fontFamilies() - - StyledScrollBar.vertical: StyledScrollBar { - flickable: sansFontList - } - - delegate: StyledRect { - required property string modelData - required property int index - readonly property bool isCurrent: modelData === rootPane.fontFamilySans - - width: ListView.view.width - color: Qt.alpha(Colours.tPalette.m3surfaceContainer, isCurrent ? Colours.tPalette.m3surfaceContainer.a : 0) - radius: Tokens.rounding.large - border.width: isCurrent ? 1 : 0 - border.color: Colours.palette.m3primary - implicitHeight: fontFamilySansRow.implicitHeight + Tokens.padding.medium * 2 - - StateLayer { - onClicked: { - rootPane.fontFamilySans = modelData; - rootPane.saveConfig(); - } - } - - RowLayout { - id: fontFamilySansRow - - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - anchors.margins: Tokens.padding.medium - - spacing: Tokens.spacing.medium - - StyledText { - text: modelData - font: Tokens.font.body.medium - } - - Item { - Layout.fillWidth: true - } - - Loader { - asynchronous: true - active: isCurrent - - sourceComponent: MaterialIcon { - text: "check" - color: Colours.palette.m3onSurfaceVariant - fontStyle: Tokens.font.icon.large - } - } - } - } - } - } - } - - CollapsibleSection { - id: monoFontSection - - title: qsTr("Monospace font family") - expanded: false - showBackground: true - nested: true - - Loader { - Layout.fillWidth: true - Layout.preferredHeight: item ? Math.min(item.contentHeight, 300) : 0 - asynchronous: true - active: monoFontSection.expanded - - sourceComponent: StyledListView { - id: monoFontList - - property alias contentHeight: monoFontList.contentHeight - - clip: true - spacing: Tokens.spacing.extraSmall - model: Qt.fontFamilies() - - StyledScrollBar.vertical: StyledScrollBar { - flickable: monoFontList - } - - delegate: StyledRect { - required property string modelData - required property int index - readonly property bool isCurrent: modelData === rootPane.fontFamilyMono - - width: ListView.view.width - color: Qt.alpha(Colours.tPalette.m3surfaceContainer, isCurrent ? Colours.tPalette.m3surfaceContainer.a : 0) - radius: Tokens.rounding.large - border.width: isCurrent ? 1 : 0 - border.color: Colours.palette.m3primary - implicitHeight: fontFamilyMonoRow.implicitHeight + Tokens.padding.medium * 2 - - StateLayer { - onClicked: { - rootPane.fontFamilyMono = modelData; - rootPane.saveConfig(); - } - } - - RowLayout { - id: fontFamilyMonoRow - - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - anchors.margins: Tokens.padding.medium - - spacing: Tokens.spacing.medium - - StyledText { - text: modelData - font: Tokens.font.body.medium - } - - Item { - Layout.fillWidth: true - } - - Loader { - asynchronous: true - active: isCurrent - - sourceComponent: MaterialIcon { - text: "check" - color: Colours.palette.m3onSurfaceVariant - fontStyle: Tokens.font.icon.large - } - } - } - } - } - } - } - - CollapsibleSection { - id: materialFontSection - - title: qsTr("Material font family") - expanded: false - showBackground: true - nested: true - - Loader { - id: materialFontLoader - - Layout.fillWidth: true - Layout.preferredHeight: item ? Math.min(item.contentHeight, 300) : 0 - asynchronous: true - active: materialFontSection.expanded - - sourceComponent: StyledListView { - id: materialFontList - - property alias contentHeight: materialFontList.contentHeight - - clip: true - spacing: Tokens.spacing.extraSmall - model: Qt.fontFamilies().filter(f => f.startsWith("Material Symbols")) - - StyledScrollBar.vertical: StyledScrollBar { - flickable: materialFontList - } - - delegate: StyledRect { - required property string modelData - required property int index - readonly property bool isCurrent: modelData === rootPane.fontFamilyMaterial - - width: ListView.view.width - color: Qt.alpha(Colours.tPalette.m3surfaceContainer, isCurrent ? Colours.tPalette.m3surfaceContainer.a : 0) - radius: Tokens.rounding.large - border.width: isCurrent ? 1 : 0 - border.color: Colours.palette.m3primary - implicitHeight: fontFamilyMaterialRow.implicitHeight + Tokens.padding.medium * 2 - - StateLayer { - onClicked: { - rootPane.fontFamilyMaterial = modelData; - rootPane.saveConfig(); - } - } - - RowLayout { - id: fontFamilyMaterialRow - - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - anchors.margins: Tokens.padding.medium - - spacing: Tokens.spacing.medium - - StyledText { - text: modelData - font: Tokens.font.body.medium - } - - Item { - Layout.fillWidth: true - } - - Loader { - asynchronous: true - active: isCurrent - - sourceComponent: MaterialIcon { - text: "check" - color: Colours.palette.m3onSurfaceVariant - fontStyle: Tokens.font.icon.large - } - } - } - } - } - } - } - - SectionContainer { - contentSpacing: Tokens.spacing.medium - - SliderInput { - Layout.fillWidth: true - - label: qsTr("Font size scale") - value: rootPane.fontSizeScale - from: 0.7 - to: 1.5 - decimals: 2 - suffix: "×" - validator: DoubleValidator { - bottom: 0.7 - top: 1.5 - } - - onValueModified: newValue => { - rootPane.fontSizeScale = newValue; - rootPane.saveConfig(); - } - } - } -} diff --git a/modules/controlcenter/appearance/sections/ScalesSection.qml b/modules/controlcenter/appearance/sections/ScalesSection.qml deleted file mode 100644 index 60e7e493..00000000 --- a/modules/controlcenter/appearance/sections/ScalesSection.qml +++ /dev/null @@ -1,92 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "../../components" -import QtQuick -import QtQuick.Layouts -import Caelestia.Config -import qs.components -import qs.components.containers -import qs.components.controls -import qs.services - -CollapsibleSection { - id: root - - required property var rootPane - - title: qsTr("Scales") - showBackground: true - - SectionContainer { - contentSpacing: Tokens.spacing.medium - - SliderInput { - Layout.fillWidth: true - - label: qsTr("Padding scale") - value: rootPane.paddingScale - from: 0.5 - to: 2.0 - decimals: 1 - suffix: "×" - validator: DoubleValidator { - bottom: 0.5 - top: 2.0 - } - - onValueModified: newValue => { - rootPane.paddingScale = newValue; - rootPane.saveConfig(); - } - } - } - - SectionContainer { - contentSpacing: Tokens.spacing.medium - - SliderInput { - Layout.fillWidth: true - - label: qsTr("Rounding scale") - value: rootPane.roundingScale - from: 0.1 - to: 5.0 - decimals: 1 - suffix: "×" - validator: DoubleValidator { - bottom: 0.1 - top: 5.0 - } - - onValueModified: newValue => { - rootPane.roundingScale = newValue; - rootPane.saveConfig(); - } - } - } - - SectionContainer { - contentSpacing: Tokens.spacing.medium - - SliderInput { - Layout.fillWidth: true - - label: qsTr("Spacing scale") - value: rootPane.spacingScale - from: 0.1 - to: 2.0 - decimals: 1 - suffix: "×" - validator: DoubleValidator { - bottom: 0.1 - top: 2.0 - } - - onValueModified: newValue => { - rootPane.spacingScale = newValue; - rootPane.saveConfig(); - } - } - } -} diff --git a/modules/controlcenter/appearance/sections/ThemeModeSection.qml b/modules/controlcenter/appearance/sections/ThemeModeSection.qml deleted file mode 100644 index aab53b8b..00000000 --- a/modules/controlcenter/appearance/sections/ThemeModeSection.qml +++ /dev/null @@ -1,23 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import QtQuick -import Caelestia.Config -import qs.components -import qs.components.containers -import qs.components.controls -import qs.services - -CollapsibleSection { - title: qsTr("Theme mode") - description: qsTr("Light or dark theme") - showBackground: true - - SwitchRow { - label: qsTr("Dark mode") - checked: !Colours.currentLight - onToggled: checked => { - Colours.setMode(checked ? "dark" : "light"); - } - } -} diff --git a/modules/controlcenter/appearance/sections/TransparencySection.qml b/modules/controlcenter/appearance/sections/TransparencySection.qml deleted file mode 100644 index eaa8dfd6..00000000 --- a/modules/controlcenter/appearance/sections/TransparencySection.qml +++ /dev/null @@ -1,79 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "../../components" -import QtQuick -import QtQuick.Layouts -import Caelestia.Config -import qs.components -import qs.components.containers -import qs.components.controls -import qs.services - -CollapsibleSection { - id: root - - required property var rootPane - - title: qsTr("Transparency") - showBackground: true - - SwitchRow { - label: qsTr("Transparency enabled") - checked: rootPane.transparencyEnabled - onToggled: checked => { - rootPane.transparencyEnabled = checked; - rootPane.saveConfig(); - } - } - - SectionContainer { - contentSpacing: Tokens.spacing.medium - - SliderInput { - Layout.fillWidth: true - - label: qsTr("Transparency base") - value: rootPane.transparencyBase * 100 - from: 0 - to: 100 - suffix: "%" - validator: IntValidator { - bottom: 0 - top: 100 - } - formatValueFunction: val => Math.round(val).toString() - parseValueFunction: text => parseInt(text) - - onValueModified: newValue => { - rootPane.transparencyBase = newValue / 100; - rootPane.saveConfig(); - } - } - } - - SectionContainer { - contentSpacing: Tokens.spacing.medium - - SliderInput { - Layout.fillWidth: true - - label: qsTr("Transparency layers") - value: rootPane.transparencyLayers * 100 - from: 0 - to: 100 - suffix: "%" - validator: IntValidator { - bottom: 0 - top: 100 - } - formatValueFunction: val => Math.round(val).toString() - parseValueFunction: text => parseInt(text) - - onValueModified: newValue => { - rootPane.transparencyLayers = newValue / 100; - rootPane.saveConfig(); - } - } - } -} diff --git a/modules/controlcenter/audio/AudioPane.qml b/modules/controlcenter/audio/AudioPane.qml deleted file mode 100644 index 1f0da38d..00000000 --- a/modules/controlcenter/audio/AudioPane.qml +++ /dev/null @@ -1,623 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "../components" -import QtQuick -import QtQuick.Layouts -import Quickshell.Widgets -import Caelestia.Config -import qs.components -import qs.components.containers -import qs.components.controls -import qs.components.effects -import qs.services - -Item { - id: root - - required property Session session - - anchors.fill: parent - - SplitPaneLayout { - anchors.fill: parent - - leftContent: Component { - StyledFlickable { - id: leftAudioFlickable - - flickableDirection: Flickable.VerticalFlick - contentHeight: leftContent.height - - StyledScrollBar.vertical: StyledScrollBar { - flickable: leftAudioFlickable - } - - ColumnLayout { - id: leftContent - - anchors.left: parent.left - anchors.right: parent.right - spacing: Tokens.spacing.medium - - RowLayout { - Layout.fillWidth: true - spacing: Tokens.spacing.medium - - StyledText { - text: qsTr("Audio") - font: Tokens.font.body.builders.large.weight(Font.Medium).build() - } - - Item { - Layout.fillWidth: true - } - } - - CollapsibleSection { - id: outputDevicesSection - - Layout.fillWidth: true - title: qsTr("Output devices") - expanded: true - - ColumnLayout { - Layout.fillWidth: true - spacing: Tokens.spacing.small - - RowLayout { - Layout.fillWidth: true - spacing: Tokens.spacing.small - - StyledText { - text: qsTr("Devices (%1)").arg(Audio.sinks.length) - font: Tokens.font.body.builders.medium.weight(Font.Medium).build() - } - } - - StyledText { - Layout.fillWidth: true - text: qsTr("All available output devices") - color: Colours.palette.m3outline - } - - Repeater { - Layout.fillWidth: true - model: Audio.sinks - - delegate: StyledRect { - required property var modelData - - Layout.fillWidth: true - - color: Audio.sink?.id === modelData.id ? Colours.layer(Colours.palette.m3surfaceContainer, 2) : "transparent" - radius: Tokens.rounding.large - implicitHeight: outputRowLayout.implicitHeight + Tokens.padding.medium * 2 - - StateLayer { - onClicked: { - Audio.setAudioSink(modelData); - } - } - - RowLayout { - id: outputRowLayout - - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - anchors.margins: Tokens.padding.medium - - spacing: Tokens.spacing.medium - - MaterialIcon { - text: Audio.sink?.id === modelData.id ? "speaker" : "speaker_group" - fontStyle: Tokens.font.icon.large - fill: Audio.sink?.id === modelData.id ? 1 : 0 - } - - StyledText { - Layout.fillWidth: true - elide: Text.ElideRight - maximumLineCount: 1 - - text: modelData.description || qsTr("Unknown") - font: Audio.sink?.id === modelData.id ? Tokens.font.body.builders.small.weight(Font.Medium).build() : Tokens.font.body.builders.small.weight(Font.Normal).build() - } - } - } - } - } - } - - CollapsibleSection { - id: inputDevicesSection - - Layout.fillWidth: true - title: qsTr("Input devices") - expanded: true - - ColumnLayout { - Layout.fillWidth: true - spacing: Tokens.spacing.small - - RowLayout { - Layout.fillWidth: true - spacing: Tokens.spacing.small - - StyledText { - text: qsTr("Devices (%1)").arg(Audio.sources.length) - font: Tokens.font.body.builders.medium.weight(Font.Medium).build() - } - } - - StyledText { - Layout.fillWidth: true - text: qsTr("All available input devices") - color: Colours.palette.m3outline - } - - Repeater { - Layout.fillWidth: true - model: Audio.sources - - delegate: StyledRect { - required property var modelData - - Layout.fillWidth: true - - color: Audio.source?.id === modelData.id ? Colours.layer(Colours.palette.m3surfaceContainer, 2) : "transparent" - radius: Tokens.rounding.large - implicitHeight: inputRowLayout.implicitHeight + Tokens.padding.medium * 2 - - StateLayer { - onClicked: { - Audio.setAudioSource(modelData); - } - } - - RowLayout { - id: inputRowLayout - - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - anchors.margins: Tokens.padding.medium - - spacing: Tokens.spacing.medium - - MaterialIcon { - text: "mic" - fontStyle: Tokens.font.icon.large - fill: Audio.source?.id === modelData.id ? 1 : 0 - } - - StyledText { - Layout.fillWidth: true - elide: Text.ElideRight - maximumLineCount: 1 - - text: modelData.description || qsTr("Unknown") - font: Audio.source?.id === modelData.id ? Tokens.font.body.builders.small.weight(Font.Medium).build() : Tokens.font.body.builders.small.weight(Font.Normal).build() - } - } - } - } - } - } - } - } - } - - rightContent: Component { - StyledFlickable { - id: rightAudioFlickable - - flickableDirection: Flickable.VerticalFlick - contentHeight: contentLayout.height - - StyledScrollBar.vertical: StyledScrollBar { - flickable: rightAudioFlickable - } - - ColumnLayout { - id: contentLayout - - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - spacing: Tokens.spacing.medium - - SettingsHeader { - icon: "volume_up" - title: qsTr("Audio Settings") - } - - SectionHeader { - title: qsTr("Output volume") - description: qsTr("Control the volume of your output device") - } - - SectionContainer { - contentSpacing: Tokens.spacing.medium - - ColumnLayout { - Layout.fillWidth: true - spacing: Tokens.spacing.small - - RowLayout { - Layout.fillWidth: true - spacing: Tokens.spacing.medium - - StyledText { - text: qsTr("Volume") - font: Tokens.font.body.builders.medium.weight(Font.Medium).build() - } - - Item { - Layout.fillWidth: true - } - - StyledInputField { - id: outputVolumeInput - - Layout.preferredWidth: 70 - validator: IntValidator { - bottom: 0 - top: 100 - } - enabled: !Audio.muted - - Component.onCompleted: { - text = Math.round(Audio.volume * 100).toString(); - } - - onTextEdited: text => { - if (hasFocus) { - const val = parseInt(text); - if (!isNaN(val) && val >= 0 && val <= 100) { - Audio.setVolume(val / 100); - } - } - } - - onEditingFinished: { - const val = parseInt(text); - if (isNaN(val) || val < 0 || val > 100) { - text = Math.round(Audio.volume * 100).toString(); - } - } - - Connections { - function onVolumeChanged() { - if (!outputVolumeInput.hasFocus) { - outputVolumeInput.text = Math.round(Audio.volume * 100).toString(); - } - } - - target: Audio - } - } - - StyledText { - text: "%" - color: Colours.palette.m3outline - font: Tokens.font.body.medium - opacity: Audio.muted ? 0.5 : 1 - } - - StyledRect { - implicitWidth: implicitHeight - implicitHeight: muteIcon.implicitHeight + Tokens.padding.medium * 2 - - radius: Tokens.rounding.large - color: Audio.muted ? Colours.palette.m3secondary : Colours.palette.m3secondaryContainer - - StateLayer { - onClicked: { - if (Audio.sink?.audio) { - Audio.sink.audio.muted = !Audio.sink.audio.muted; - } - } - } - - MaterialIcon { - id: muteIcon - - anchors.centerIn: parent - text: Audio.muted ? "volume_off" : "volume_up" - color: Audio.muted ? Colours.palette.m3onSecondary : Colours.palette.m3onSecondaryContainer - } - } - } - - StyledSlider { - id: outputVolumeSlider - - Layout.fillWidth: true - implicitHeight: Tokens.padding.medium * 3 - - value: Audio.volume - enabled: !Audio.muted - opacity: enabled ? 1 : 0.5 - onMoved: { - Audio.setVolume(value); - if (!outputVolumeInput.hasFocus) { - outputVolumeInput.text = Math.round(value * 100).toString(); - } - } - } - } - } - - SectionHeader { - title: qsTr("Input volume") - description: qsTr("Control the volume of your input device") - } - - SectionContainer { - contentSpacing: Tokens.spacing.medium - - ColumnLayout { - Layout.fillWidth: true - spacing: Tokens.spacing.small - - RowLayout { - Layout.fillWidth: true - spacing: Tokens.spacing.medium - - StyledText { - text: qsTr("Volume") - font: Tokens.font.body.builders.medium.weight(Font.Medium).build() - } - - Item { - Layout.fillWidth: true - } - - StyledInputField { - id: inputVolumeInput - - Layout.preferredWidth: 70 - validator: IntValidator { - bottom: 0 - top: 100 - } - enabled: !Audio.sourceMuted - - Component.onCompleted: { - text = Math.round(Audio.sourceVolume * 100).toString(); - } - - onTextEdited: text => { - if (hasFocus) { - const val = parseInt(text); - if (!isNaN(val) && val >= 0 && val <= 100) { - Audio.setSourceVolume(val / 100); - } - } - } - - onEditingFinished: { - const val = parseInt(text); - if (isNaN(val) || val < 0 || val > 100) { - text = Math.round(Audio.sourceVolume * 100).toString(); - } - } - - Connections { - function onSourceVolumeChanged() { - if (!inputVolumeInput.hasFocus) { - inputVolumeInput.text = Math.round(Audio.sourceVolume * 100).toString(); - } - } - - target: Audio - } - } - - StyledText { - text: "%" - color: Colours.palette.m3outline - font: Tokens.font.body.medium - opacity: Audio.sourceMuted ? 0.5 : 1 - } - - StyledRect { - implicitWidth: implicitHeight - implicitHeight: muteInputIcon.implicitHeight + Tokens.padding.medium * 2 - - radius: Tokens.rounding.large - color: Audio.sourceMuted ? Colours.palette.m3secondary : Colours.palette.m3secondaryContainer - - StateLayer { - onClicked: { - if (Audio.source?.audio) { - Audio.source.audio.muted = !Audio.source.audio.muted; - } - } - } - - MaterialIcon { - id: muteInputIcon - - anchors.centerIn: parent - text: "mic_off" - color: Audio.sourceMuted ? Colours.palette.m3onSecondary : Colours.palette.m3onSecondaryContainer - } - } - } - - StyledSlider { - id: inputVolumeSlider - - Layout.fillWidth: true - implicitHeight: Tokens.padding.medium * 3 - - value: Audio.sourceVolume - enabled: !Audio.sourceMuted - opacity: enabled ? 1 : 0.5 - onMoved: { - Audio.setSourceVolume(value); - if (!inputVolumeInput.hasFocus) { - inputVolumeInput.text = Math.round(value * 100).toString(); - } - } - } - } - } - - SectionHeader { - title: qsTr("Applications") - description: qsTr("Control volume for individual applications") - } - - SectionContainer { - contentSpacing: Tokens.spacing.medium - - ColumnLayout { - Layout.fillWidth: true - spacing: Tokens.spacing.small - - Repeater { - model: Audio.streams - Layout.fillWidth: true - - delegate: ColumnLayout { - required property var modelData - required property int index - - Layout.fillWidth: true - spacing: Tokens.spacing.medium - - RowLayout { - Layout.fillWidth: true - spacing: Tokens.spacing.medium - - MaterialIcon { - text: "apps" - fontStyle: Tokens.font.icon.medium - fill: 0 - } - - StyledText { - Layout.fillWidth: true - elide: Text.ElideRight - maximumLineCount: 1 - text: Audio.getStreamName(modelData) - font: Tokens.font.body.builders.medium.weight(Font.Medium).build() - } - - StyledInputField { - id: streamVolumeInput - - Layout.preferredWidth: 70 - validator: IntValidator { - bottom: 0 - top: 100 - } - enabled: !Audio.getStreamMuted(modelData) - - Component.onCompleted: { - text = Math.round(Audio.getStreamVolume(modelData) * 100).toString(); - } - - onTextEdited: text => { - if (hasFocus) { - const val = parseInt(text); - if (!isNaN(val) && val >= 0 && val <= 100) { - Audio.setStreamVolume(modelData, val / 100); - } - } - } - - onEditingFinished: { - const val = parseInt(text); - if (isNaN(val) || val < 0 || val > 100) { - text = Math.round(Audio.getStreamVolume(modelData) * 100).toString(); - } - } - - Connections { - function onAudioChanged() { - if (!streamVolumeInput.hasFocus && modelData?.audio) { - streamVolumeInput.text = Math.round(modelData.audio.volume * 100).toString(); - } - } - - target: modelData - } - } - - StyledText { - text: "%" - color: Colours.palette.m3outline - font: Tokens.font.body.medium - opacity: Audio.getStreamMuted(modelData) ? 0.5 : 1 - } - - StyledRect { - implicitWidth: implicitHeight - implicitHeight: streamMuteIcon.implicitHeight + Tokens.padding.medium * 2 - - radius: Tokens.rounding.large - color: Audio.getStreamMuted(modelData) ? Colours.palette.m3secondary : Colours.palette.m3secondaryContainer - - StateLayer { - onClicked: { - Audio.setStreamMuted(modelData, !Audio.getStreamMuted(modelData)); - } - } - - MaterialIcon { - id: streamMuteIcon - - anchors.centerIn: parent - text: Audio.getStreamMuted(modelData) ? "volume_off" : "volume_up" - color: Audio.getStreamMuted(modelData) ? Colours.palette.m3onSecondary : Colours.palette.m3onSecondaryContainer - } - } - } - - StyledSlider { - Layout.fillWidth: true - implicitHeight: Tokens.padding.medium * 3 - - value: Audio.getStreamVolume(modelData) - enabled: !Audio.getStreamMuted(modelData) - opacity: enabled ? 1 : 0.5 - onMoved: { - Audio.setStreamVolume(modelData, value); - if (!streamVolumeInput.hasFocus) { - streamVolumeInput.text = Math.round(value * 100).toString(); - } - } - - Connections { - function onAudioChanged() { - if (modelData?.audio) { - value = modelData.audio.volume; - } - } - - target: modelData - } - } - } - } - - StyledText { - Layout.fillWidth: true - visible: Audio.streams.length === 0 - text: qsTr("No applications currently playing audio") - color: Colours.palette.m3outline - font: Tokens.font.body.small - horizontalAlignment: Text.AlignHCenter - } - } - } - } - } - } - } -} diff --git a/modules/controlcenter/bluetooth/BtPane.qml b/modules/controlcenter/bluetooth/BtPane.qml deleted file mode 100644 index b2b9c0f6..00000000 --- a/modules/controlcenter/bluetooth/BtPane.qml +++ /dev/null @@ -1,74 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "../components" -import "." -import QtQuick -import Quickshell.Bluetooth -import Quickshell.Widgets -import Caelestia.Config -import qs.components -import qs.components.containers -import qs.components.controls - -SplitPaneWithDetails { - id: root - - required property Session session - - anchors.fill: parent - - activeItem: session.bt.active - paneIdGenerator: function (item) { - return item ? (item.address || "") : ""; - } - - leftContent: Component { - StyledFlickable { - id: leftFlickable - - flickableDirection: Flickable.VerticalFlick - contentHeight: deviceList.height - - StyledScrollBar.vertical: StyledScrollBar { - flickable: leftFlickable - } - - DeviceList { - id: deviceList - - anchors.left: parent.left - anchors.right: parent.right - session: root.session - } - } - } - - rightDetailsComponent: Component { - Details { - session: root.session - } - } - - rightSettingsComponent: Component { - StyledFlickable { - id: settingsFlickable - - flickableDirection: Flickable.VerticalFlick - contentHeight: settingsInner.height - - StyledScrollBar.vertical: StyledScrollBar { - flickable: settingsFlickable - } - - Settings { - id: settingsInner - - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - session: root.session - } - } - } -} diff --git a/modules/controlcenter/bluetooth/Details.qml b/modules/controlcenter/bluetooth/Details.qml deleted file mode 100644 index acce9776..00000000 --- a/modules/controlcenter/bluetooth/Details.qml +++ /dev/null @@ -1,663 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "../components" -import QtQuick -import QtQuick.Layouts -import Quickshell.Bluetooth -import Caelestia.Config -import qs.components -import qs.components.containers -import qs.components.controls -import qs.components.effects -import qs.services -import qs.utils - -StyledFlickable { - id: root - - required property Session session - readonly property BluetoothDevice device: session.bt.active - - flickableDirection: Flickable.VerticalFlick - contentHeight: detailsWrapper.height - - StyledScrollBar.vertical: StyledScrollBar { - flickable: root - } - - Item { - id: detailsWrapper - - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - implicitHeight: details.implicitHeight - - DeviceDetails { - id: details - - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - - session: root.session - device: root.device - - headerComponent: Component { - SettingsHeader { - icon: Icons.getBluetoothIcon(root.device?.icon ?? "") - title: root.device?.name ?? "" - } - } - - sections: [ - Component { - ColumnLayout { - spacing: Tokens.spacing.medium - - StyledText { - Layout.topMargin: Tokens.spacing.largeIncreased - text: qsTr("Connection status") - font: Tokens.font.body.builders.large.weight(Font.Medium).build() - } - - StyledText { - text: qsTr("Connection settings for this device") - color: Colours.palette.m3outline - } - - StyledRect { - Layout.fillWidth: true - implicitHeight: deviceStatus.implicitHeight + Tokens.padding.extraLargeIncreased - - radius: Tokens.rounding.large - color: Colours.tPalette.m3surfaceContainer - - ColumnLayout { - id: deviceStatus - - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - anchors.margins: Tokens.padding.large - - spacing: Tokens.spacing.large - - Toggle { - label: qsTr("Connected") - checked: root.device?.connected ?? false - toggle.onToggled: root.device.connected = checked - } - - Toggle { - label: qsTr("Paired") - checked: root.device?.paired ?? false - toggle.onToggled: { - if (root.device.paired) - root.device.forget(); - else - root.device.pair(); - } - } - - Toggle { - label: qsTr("Blocked") - checked: root.device?.blocked ?? false - toggle.onToggled: root.device.blocked = checked - } - } - } - } - }, - Component { - ColumnLayout { - spacing: Tokens.spacing.medium - - StyledText { - Layout.topMargin: Tokens.spacing.largeIncreased - text: qsTr("Device properties") - font: Tokens.font.body.builders.large.weight(Font.Medium).build() - } - - StyledText { - text: qsTr("Additional settings") - color: Colours.palette.m3outline - } - - StyledRect { - Layout.fillWidth: true - implicitHeight: deviceProps.implicitHeight + Tokens.padding.extraLargeIncreased - - radius: Tokens.rounding.large - color: Colours.tPalette.m3surfaceContainer - - ColumnLayout { - id: deviceProps - - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - anchors.margins: Tokens.padding.large - - spacing: Tokens.spacing.large - - RowLayout { - Layout.fillWidth: true - spacing: Tokens.spacing.small - - Item { - id: renameDevice - - Layout.fillWidth: true - Layout.rightMargin: Tokens.spacing.small - - implicitHeight: renameLabel.implicitHeight + deviceNameEdit.implicitHeight - - states: State { - name: "editingDeviceName" - when: root.session.bt.editingDeviceName - - AnchorChanges { - target: deviceNameEdit - anchors.top: renameDevice.top - } - PropertyChanges { - renameDevice.implicitHeight: deviceNameEdit.implicitHeight - renameLabel.opacity: 0 - deviceNameEdit.padding: root.Tokens.padding.medium - } - } - - transitions: Transition { - AnchorAnim { - type: AnchorAnim.Standard - } - Anim { - properties: "implicitHeight,opacity,padding" - } - } - - StyledText { - id: renameLabel - - anchors.left: parent.left - - text: qsTr("Device name") - color: Colours.palette.m3outline - font: Tokens.font.label.small - } - - StyledTextField { - id: deviceNameEdit - - anchors.left: parent.left - anchors.right: parent.right - anchors.top: renameLabel.bottom - anchors.leftMargin: root.session.bt.editingDeviceName ? 0 : -Tokens.padding.medium - - text: root.device?.name ?? "" - readOnly: !root.session.bt.editingDeviceName - onAccepted: { - root.session.bt.editingDeviceName = false; - root.device.name = text; - } - - leftPadding: Tokens.padding.medium - rightPadding: Tokens.padding.medium - - background: StyledRect { - radius: Tokens.rounding.medium - border.width: 2 - border.color: Colours.palette.m3primary - opacity: root.session.bt.editingDeviceName ? 1 : 0 - - Behavior on border.color { - CAnim {} - } - - Behavior on opacity { - Anim {} - } - } - - Behavior on anchors.leftMargin { - Anim {} - } - } - } - - StyledRect { - implicitWidth: implicitHeight - implicitHeight: cancelEditIcon.implicitHeight + Tokens.padding.large - - radius: Tokens.rounding.medium - color: Colours.palette.m3secondaryContainer - opacity: root.session.bt.editingDeviceName ? 1 : 0 - scale: root.session.bt.editingDeviceName ? 1 : 0.5 - - StateLayer { - onClicked: { - root.session.bt.editingDeviceName = false; - deviceNameEdit.text = Qt.binding(() => root.device?.name ?? ""); - } - - color: Colours.palette.m3onSecondaryContainer - disabled: !root.session.bt.editingDeviceName - } - - MaterialIcon { - id: cancelEditIcon - - anchors.centerIn: parent - animate: true - text: "cancel" - color: Colours.palette.m3onSecondaryContainer - } - - Behavior on opacity { - Anim {} - } - - Behavior on scale { - Anim { - type: Anim.FastSpatial - } - } - } - - StyledRect { - implicitWidth: implicitHeight - implicitHeight: editIcon.implicitHeight + Tokens.padding.large - - radius: root.session.bt.editingDeviceName ? Tokens.rounding.medium : implicitHeight / 2 * Math.min(1, Tokens.rounding.scale) - color: Qt.alpha(Colours.palette.m3primary, root.session.bt.editingDeviceName ? 1 : 0) - - StateLayer { - onClicked: { - root.session.bt.editingDeviceName = !root.session.bt.editingDeviceName; - if (root.session.bt.editingDeviceName) - deviceNameEdit.forceActiveFocus(); - else - deviceNameEdit.accepted(); - } - - color: root.session.bt.editingDeviceName ? Colours.palette.m3onPrimary : Colours.palette.m3onSurface - } - - MaterialIcon { - id: editIcon - - anchors.centerIn: parent - animate: true - text: root.session.bt.editingDeviceName ? "check_circle" : "edit" - color: root.session.bt.editingDeviceName ? Colours.palette.m3onPrimary : Colours.palette.m3onSurface - } - - Behavior on radius { - Anim {} - } - } - } - - Toggle { - label: qsTr("Trusted") - checked: root.device?.trusted ?? false - toggle.onToggled: root.device.trusted = checked - } - - Toggle { - label: qsTr("Wake allowed") - checked: root.device?.wakeAllowed ?? false - toggle.onToggled: root.device.wakeAllowed = checked - } - } - } - } - }, - Component { - ColumnLayout { - spacing: Tokens.spacing.medium - - StyledText { - Layout.topMargin: Tokens.spacing.largeIncreased - text: qsTr("Device information") - font: Tokens.font.body.builders.large.weight(Font.Medium).build() - } - - StyledText { - text: qsTr("Information about this device") - color: Colours.palette.m3outline - } - - StyledRect { - Layout.fillWidth: true - implicitHeight: deviceInfo.implicitHeight + Tokens.padding.extraLargeIncreased - - radius: Tokens.rounding.large - color: Colours.tPalette.m3surfaceContainer - - ColumnLayout { - id: deviceInfo - - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - anchors.margins: Tokens.padding.large - - spacing: Tokens.spacing.extraSmall - - StyledText { - text: root.device?.batteryAvailable ? qsTr("Device battery (%1%)").arg(root.device.battery * 100) : qsTr("Battery unavailable") - } - - RowLayout { - id: batteryPercent - - Layout.topMargin: Tokens.spacing.extraSmall - Layout.fillWidth: true - Layout.preferredHeight: Tokens.padding.small - spacing: Tokens.spacing.extraSmall - - StyledRect { - Layout.fillWidth: true - Layout.fillHeight: true - radius: Tokens.rounding.full - color: Colours.palette.m3secondaryContainer - - StyledRect { - anchors.left: parent.left - anchors.top: parent.top - anchors.bottom: parent.bottom - anchors.margins: parent.height * 0.25 - - implicitWidth: root.device?.batteryAvailable ? batteryPercent.width * root.device.battery : 0 - radius: Tokens.rounding.full - color: Colours.palette.m3primary - } - } - } - - StyledText { - Layout.topMargin: Tokens.spacing.medium - text: qsTr("Dbus path") - } - - StyledText { - text: root.device?.dbusPath ?? "" - color: Colours.palette.m3outline - font: Tokens.font.body.small - } - - StyledText { - Layout.topMargin: Tokens.spacing.medium - text: qsTr("MAC address") - } - - StyledText { - text: root.device?.address ?? "" - color: Colours.palette.m3outline - font: Tokens.font.body.small - } - - StyledText { - Layout.topMargin: Tokens.spacing.medium - text: qsTr("Bonded") - } - - StyledText { - text: root.device?.bonded ? qsTr("Yes") : qsTr("No") - color: Colours.palette.m3outline - font: Tokens.font.body.small - } - - StyledText { - Layout.topMargin: Tokens.spacing.medium - text: qsTr("System name") - } - - StyledText { - text: root.device?.deviceName ?? "" - color: Colours.palette.m3outline - font: Tokens.font.body.small - } - } - } - } - } - ] - } - } - - ColumnLayout { - anchors.right: fabRoot.right - anchors.bottom: fabRoot.top - anchors.bottomMargin: Tokens.padding.medium - - Repeater { - id: fabMenu - - model: ListModel { - ListElement { - name: "trust" - icon: "handshake" - } - ListElement { - name: "block" - icon: "block" - } - ListElement { - name: "pair" - icon: "missing_controller" - } - ListElement { - name: "connect" - icon: "bluetooth_connected" - } - } - - StyledClippingRect { - id: fabMenuItem - - required property var modelData - required property int index - - Layout.alignment: Qt.AlignRight - - implicitHeight: fabMenuItemInner.implicitHeight + Tokens.padding.medium * 2 - - radius: Tokens.rounding.full - color: Colours.palette.m3primaryContainer - - opacity: 0 - - states: State { - name: "visible" - when: root.session.bt.fabMenuOpen - - PropertyChanges { - fabMenuItem.implicitWidth: fabMenuItemInner.implicitWidth + root.Tokens.padding.extraLargeIncreased - fabMenuItem.opacity: 1 - fabMenuItemInner.opacity: 1 - } - } - - transitions: [ - Transition { - to: "visible" - - SequentialAnimation { - PauseAnimation { - duration: (fabMenu.count - 1 - fabMenuItem.index) * Tokens.anim.durations.small / 8 - } - ParallelAnimation { - Anim { - property: "implicitWidth" - type: Anim.FastSpatial - } - Anim { - property: "opacity" - type: Anim.StandardSmall - } - } - } - }, - Transition { - from: "visible" - - SequentialAnimation { - PauseAnimation { - duration: fabMenuItem.index * Tokens.anim.durations.small / 8 - } - ParallelAnimation { - Anim { - property: "implicitWidth" - type: Anim.FastSpatial - } - Anim { - property: "opacity" - type: Anim.StandardSmall - } - } - } - } - ] - - StateLayer { - onClicked: { - root.session.bt.fabMenuOpen = false; - - const name = fabMenuItem.modelData.name; - if (fabMenuItem.modelData.name !== "pair") - root.device[`${name}ed`] = !root.device[`${name}ed`]; - else if (root.device.paired) - root.device.forget(); - else - root.device.pair(); - } - } - - RowLayout { - id: fabMenuItemInner - - anchors.centerIn: parent - spacing: Tokens.spacing.medium - opacity: 0 - - MaterialIcon { - text: fabMenuItem.modelData.icon - color: Colours.palette.m3onPrimaryContainer - fill: 1 - } - - StyledText { - animate: true - text: (root.device && root.device[`${fabMenuItem.modelData.name}ed`] ? fabMenuItem.modelData.name === "connect" ? "dis" : "un" : "") + fabMenuItem.modelData.name - color: Colours.palette.m3onPrimaryContainer - font: Tokens.font.body.builders.small.capitalisation(Font.Capitalize).build() - Layout.preferredWidth: implicitWidth - - Behavior on Layout.preferredWidth { - Anim { - type: Anim.StandardSmall - } - } - } - } - } - } - } - - Item { - id: fabRoot - - x: root.contentX + root.width - width - y: root.contentY + root.height - height - width: 64 - height: 64 - z: 10000 - - StyledRect { - id: fabBg - - anchors.right: parent.right - anchors.top: parent.top - - implicitWidth: 64 - implicitHeight: 64 - - radius: Tokens.rounding.large - color: root.session.bt.fabMenuOpen ? Colours.palette.m3primary : Colours.palette.m3primaryContainer - - states: State { - name: "expanded" - when: root.session.bt.fabMenuOpen - - PropertyChanges { - fabBg.implicitWidth: 48 - fabBg.implicitHeight: 48 - fabBg.radius: 48 / 2 - fab.fontStyle: Tokens.font.icon.large - } - } - - transitions: Transition { - Anim { - properties: "implicitWidth,implicitHeight" - type: Anim.FastSpatial - } - Anim { - properties: "radius,font.pointSize" - } - } - - Elevation { - anchors.fill: parent - radius: parent.radius - z: -1 - level: fabState.containsMouse && !fabState.pressed ? 4 : 3 - } - - StateLayer { - id: fabState - - onClicked: { - root.session.bt.fabMenuOpen = !root.session.bt.fabMenuOpen; - } - - color: root.session.bt.fabMenuOpen ? Colours.palette.m3onPrimary : Colours.palette.m3onPrimaryContainer - } - - MaterialIcon { - id: fab - - anchors.centerIn: parent - animate: true - text: root.session.bt.fabMenuOpen ? "close" : "settings" - color: root.session.bt.fabMenuOpen ? Colours.palette.m3onPrimary : Colours.palette.m3onPrimaryContainer - fontStyle: Tokens.font.icon.large - fill: 1 - } - } - } - - component Toggle: RowLayout { - required property string label - property alias checked: toggle.checked - property alias toggle: toggle - - Layout.fillWidth: true - spacing: Tokens.spacing.medium - - StyledText { - Layout.fillWidth: true - text: parent.label - } - - StyledSwitch { - id: toggle - - cLayer: 2 - } - } -} diff --git a/modules/controlcenter/bluetooth/DeviceList.qml b/modules/controlcenter/bluetooth/DeviceList.qml deleted file mode 100644 index f5877522..00000000 --- a/modules/controlcenter/bluetooth/DeviceList.qml +++ /dev/null @@ -1,265 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "../components" -import QtQuick -import QtQuick.Layouts -import Quickshell -import Quickshell.Bluetooth -import Caelestia.Config -import qs.components -import qs.components.containers -import qs.components.controls -import qs.services -import qs.utils - -DeviceList { - id: root - - required property Session session - readonly property bool smallDiscoverable: width <= 540 - readonly property bool smallPairable: width <= 480 - - title: qsTr("Devices (%1)").arg(Bluetooth.devices.values.length) - description: qsTr("All available bluetooth devices") - activeItem: session.bt.active - - model: ScriptModel { - id: deviceModel - - values: [...Bluetooth.devices.values].sort((a, b) => (b.connected - a.connected) || (b.paired - a.paired) || a.name.localeCompare(b.name)) - } - - headerComponent: Component { - RowLayout { - spacing: Tokens.spacing.medium - - StyledText { - text: qsTr("Bluetooth") - font: Tokens.font.body.builders.large.weight(Font.Medium).build() - } - - Item { - Layout.fillWidth: true - } - - ToggleButton { - toggled: Bluetooth.defaultAdapter?.enabled ?? false - icon: "power" - accent: "Tertiary" - iconSize: Tokens.font.body.medium.pointSize - horizontalPadding: Tokens.padding.medium - verticalPadding: Tokens.padding.small - tooltip: qsTr("Toggle Bluetooth") - - onClicked: { - const adapter = Bluetooth.defaultAdapter; - if (adapter) - adapter.enabled = !adapter.enabled; - } - } - - ToggleButton { - toggled: Bluetooth.defaultAdapter?.discoverable ?? false - icon: root.smallDiscoverable ? "group_search" : "" - label: root.smallDiscoverable ? "" : qsTr("Discoverable") - iconSize: Tokens.font.body.medium.pointSize - horizontalPadding: Tokens.padding.medium - verticalPadding: Tokens.padding.small - tooltip: qsTr("Make discoverable") - - onClicked: { - const adapter = Bluetooth.defaultAdapter; - if (adapter) - adapter.discoverable = !adapter.discoverable; - } - } - - ToggleButton { - toggled: Bluetooth.defaultAdapter?.pairable ?? false - icon: "missing_controller" - label: root.smallPairable ? "" : qsTr("Pairable") - iconSize: Tokens.font.body.medium.pointSize - horizontalPadding: Tokens.padding.medium - verticalPadding: Tokens.padding.small - tooltip: qsTr("Make pairable") - - onClicked: { - const adapter = Bluetooth.defaultAdapter; - if (adapter) - adapter.pairable = !adapter.pairable; - } - } - - ToggleButton { - toggled: Bluetooth.defaultAdapter?.discovering ?? false - icon: "bluetooth_searching" - accent: "Secondary" - iconSize: Tokens.font.body.medium.pointSize - horizontalPadding: Tokens.padding.medium - verticalPadding: Tokens.padding.small - tooltip: qsTr("Scan for devices") - - onClicked: { - const adapter = Bluetooth.defaultAdapter; - if (adapter) - adapter.discovering = !adapter.discovering; - } - } - - ToggleButton { - toggled: !root.session.bt.active - icon: "settings" - accent: "Primary" - iconSize: Tokens.font.body.medium.pointSize - horizontalPadding: Tokens.padding.medium - verticalPadding: Tokens.padding.small - tooltip: qsTr("Bluetooth settings") - - onClicked: { - if (root.session.bt.active) - root.session.bt.active = null; - else { - root.session.bt.active = root.model.values[0] ?? null; - } - } - } - } - } - - delegate: Component { - StyledRect { - id: device - - required property BluetoothDevice modelData - readonly property bool loading: modelData && (modelData.state === BluetoothDeviceState.Connecting || modelData.state === BluetoothDeviceState.Disconnecting) - readonly property bool connected: modelData && modelData.state === BluetoothDeviceState.Connected - - width: ListView.view ? ListView.view.width : undefined - implicitHeight: deviceInner.implicitHeight + Tokens.padding.medium * 2 - - color: Qt.alpha(Colours.tPalette.m3surfaceContainer, root.activeItem === modelData ? Colours.tPalette.m3surfaceContainer.a : 0) - radius: Tokens.rounding.large - - StateLayer { - id: stateLayer - - onClicked: { - if (device.modelData) - root.session.bt.active = device.modelData; - } - } - - RowLayout { - id: deviceInner - - anchors.fill: parent - anchors.margins: Tokens.padding.medium - - spacing: Tokens.spacing.medium - - StyledRect { - implicitWidth: implicitHeight - implicitHeight: icon.implicitHeight + Tokens.padding.medium * 2 - - radius: Tokens.rounding.large - color: device.connected ? Colours.palette.m3primaryContainer : (device.modelData && device.modelData.bonded) ? Colours.palette.m3secondaryContainer : Colours.tPalette.m3surfaceContainerHigh - - StyledRect { - anchors.fill: parent - radius: parent.radius - color: Qt.alpha(device.connected ? Colours.palette.m3onPrimaryContainer : (device.modelData && device.modelData.bonded) ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface, stateLayer.pressed ? 0.1 : stateLayer.containsMouse ? 0.08 : 0) - } - - MaterialIcon { - id: icon - - anchors.centerIn: parent - text: Icons.getBluetoothIcon(device.modelData ? device.modelData.icon : "") - color: device.connected ? Colours.palette.m3onPrimaryContainer : (device.modelData && device.modelData.bonded) ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface - fontStyle: Tokens.font.icon.large - fill: device.connected ? 1 : 0 - - Behavior on fill { - Anim { - type: Anim.DefaultEffects - } - } - } - } - - ColumnLayout { - Layout.fillWidth: true - - spacing: 0 - - StyledText { - Layout.fillWidth: true - text: device.modelData ? device.modelData.name : qsTr("Unknown") - elide: Text.ElideRight - } - - StyledText { - Layout.fillWidth: true - text: (device.modelData ? device.modelData.address : "") + (device.connected ? qsTr(" (Connected)") : (device.modelData && device.modelData.bonded) ? qsTr(" (Paired)") : "") - color: Colours.palette.m3outline - font: Tokens.font.body.small - elide: Text.ElideRight - } - } - - StyledRect { - id: connectBtn - - implicitWidth: implicitHeight - implicitHeight: connectIcon.implicitHeight + Tokens.padding.large - - radius: Tokens.rounding.full - color: Qt.alpha(Colours.palette.m3primaryContainer, device.connected ? 1 : 0) - - CircularIndicator { - anchors.fill: parent - running: device.loading - } - - StateLayer { - onClicked: { - if (device.loading) - return; - - if (device.connected) { - device.modelData.connected = false; - } else { - if (device.modelData.bonded) { - device.modelData.connected = true; - } else { - device.modelData.pair(); - } - } - } - - color: device.connected ? Colours.palette.m3onPrimaryContainer : Colours.palette.m3onSurface - disabled: device.loading - } - - MaterialIcon { - id: connectIcon - - anchors.centerIn: parent - animate: true - text: device.connected ? "link_off" : "link" - color: device.connected ? Colours.palette.m3onPrimaryContainer : Colours.palette.m3onSurface - - opacity: device.loading ? 0 : 1 - - Behavior on opacity { - Anim {} - } - } - } - } - } - } - - onItemSelected: item => session.bt.active = item -} diff --git a/modules/controlcenter/bluetooth/Settings.qml b/modules/controlcenter/bluetooth/Settings.qml deleted file mode 100644 index 14d2a53f..00000000 --- a/modules/controlcenter/bluetooth/Settings.qml +++ /dev/null @@ -1,521 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "../components" -import QtQuick -import QtQuick.Layouts -import Quickshell.Bluetooth -import Caelestia.Config -import qs.components -import qs.components.controls -import qs.components.effects -import qs.services - -ColumnLayout { - id: root - - required property Session session - - spacing: Tokens.spacing.medium - - SettingsHeader { - icon: "bluetooth" - title: qsTr("Bluetooth Settings") - } - - StyledText { - Layout.topMargin: Tokens.spacing.largeIncreased - text: qsTr("Adapter status") - font: Tokens.font.body.builders.large.weight(Font.Medium).build() - } - - StyledText { - text: qsTr("General adapter settings") - color: Colours.palette.m3outline - } - - StyledRect { - Layout.fillWidth: true - implicitHeight: adapterStatus.implicitHeight + Tokens.padding.extraLargeIncreased - - radius: Tokens.rounding.large - color: Colours.tPalette.m3surfaceContainer - - ColumnLayout { - id: adapterStatus - - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - anchors.margins: Tokens.padding.large - - spacing: Tokens.spacing.large - - Toggle { - label: qsTr("Powered") - checked: Bluetooth.defaultAdapter?.enabled ?? false - toggle.onToggled: { - const adapter = Bluetooth.defaultAdapter; - if (adapter) - adapter.enabled = checked; - } - } - - Toggle { - label: qsTr("Discoverable") - checked: Bluetooth.defaultAdapter?.discoverable ?? false - toggle.onToggled: { - const adapter = Bluetooth.defaultAdapter; - if (adapter) - adapter.discoverable = checked; - } - } - - Toggle { - label: qsTr("Pairable") - checked: Bluetooth.defaultAdapter?.pairable ?? false - toggle.onToggled: { - const adapter = Bluetooth.defaultAdapter; - if (adapter) - adapter.pairable = checked; - } - } - } - } - - StyledText { - Layout.topMargin: Tokens.spacing.largeIncreased - text: qsTr("Adapter properties") - font: Tokens.font.body.builders.large.weight(Font.Medium).build() - } - - StyledText { - text: qsTr("Per-adapter settings") - color: Colours.palette.m3outline - } - - StyledRect { - Layout.fillWidth: true - implicitHeight: adapterSettings.implicitHeight + Tokens.padding.extraLargeIncreased - - radius: Tokens.rounding.large - color: Colours.tPalette.m3surfaceContainer - - ColumnLayout { - id: adapterSettings - - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - anchors.margins: Tokens.padding.large - - spacing: Tokens.spacing.large - - RowLayout { - Layout.fillWidth: true - spacing: Tokens.spacing.medium - - StyledText { - Layout.fillWidth: true - text: qsTr("Current adapter") - } - - Item { - id: adapterPickerButton - - property bool expanded - - implicitWidth: adapterPicker.implicitWidth + Tokens.padding.medium * 2 - implicitHeight: adapterPicker.implicitHeight + Tokens.padding.large - - StateLayer { - onClicked: { - adapterPickerButton.expanded = !adapterPickerButton.expanded; - } - - radius: Tokens.rounding.medium - } - - RowLayout { - id: adapterPicker - - anchors.fill: parent - anchors.margins: Tokens.padding.medium - anchors.topMargin: Tokens.padding.small - anchors.bottomMargin: Tokens.padding.small - spacing: Tokens.spacing.medium - - StyledText { - Layout.leftMargin: Tokens.padding.extraSmall - text: Bluetooth.defaultAdapter?.name ?? qsTr("None") - } - - MaterialIcon { - text: "expand_more" - } - } - - Elevation { - anchors.fill: adapterListBg - radius: adapterListBg.radius - opacity: adapterPickerButton.expanded ? 1 : 0 - scale: adapterPickerButton.expanded ? 1 : 0.7 - level: 2 - - Behavior on opacity { - Anim {} - } - - Behavior on scale { - Anim { - type: Anim.FastSpatial - } - } - } - - StyledClippingRect { - id: adapterListBg - - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: parent.bottom - implicitHeight: adapterPickerButton.expanded ? adapterList.implicitHeight : adapterPickerButton.implicitHeight - - color: Colours.palette.m3secondaryContainer - radius: Tokens.rounding.medium - opacity: adapterPickerButton.expanded ? 1 : 0 - scale: adapterPickerButton.expanded ? 1 : 0.7 - - ColumnLayout { - id: adapterList - - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - - spacing: 0 - - Repeater { - model: Bluetooth.adapters - - Item { - id: adapter - - required property BluetoothAdapter modelData - - Layout.fillWidth: true - implicitHeight: adapterInner.implicitHeight + Tokens.padding.medium * 2 - - StateLayer { - onClicked: { - adapterPickerButton.expanded = false; - root.session.bt.currentAdapter = adapter.modelData; - } - - disabled: !adapterPickerButton.expanded - } - - RowLayout { - id: adapterInner - - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - anchors.margins: Tokens.padding.medium - spacing: Tokens.spacing.medium - - StyledText { - Layout.fillWidth: true - Layout.leftMargin: Tokens.padding.extraSmall - text: adapter.modelData.name - color: Colours.palette.m3onSecondaryContainer - } - - MaterialIcon { - text: "check" - color: Colours.palette.m3onSecondaryContainer - visible: adapter.modelData === root.session.bt.currentAdapter - } - } - } - } - } - - Behavior on opacity { - Anim {} - } - - Behavior on scale { - Anim { - type: Anim.FastSpatial - } - } - - Behavior on implicitHeight { - Anim {} - } - } - } - } - - RowLayout { - Layout.fillWidth: true - spacing: Tokens.spacing.medium - - StyledText { - Layout.fillWidth: true - text: qsTr("Discoverable timeout") - } - - CustomSpinBox { - min: 0 - value: root.session.bt.currentAdapter?.discoverableTimeout ?? 0 - onValueModified: value => { - if (root.session.bt.currentAdapter) { - root.session.bt.currentAdapter.discoverableTimeout = value; - } - } - } - } - - RowLayout { - Layout.fillWidth: true - spacing: Tokens.spacing.small - - Item { - id: renameAdapter - - Layout.fillWidth: true - Layout.rightMargin: Tokens.spacing.small - - implicitHeight: renameLabel.implicitHeight + adapterNameEdit.implicitHeight - - states: State { - name: "editingAdapterName" - when: root.session.bt.editingAdapterName - - AnchorChanges { - target: adapterNameEdit - anchors.top: renameAdapter.top - } - PropertyChanges { - renameAdapter.implicitHeight: adapterNameEdit.implicitHeight - renameLabel.opacity: 0 - adapterNameEdit.padding: Tokens.padding.medium - } - } - - transitions: Transition { - AnchorAnim { - type: AnchorAnim.Standard - } - Anim { - properties: "implicitHeight,opacity,padding" - } - } - - StyledText { - id: renameLabel - - anchors.left: parent.left - - text: qsTr("Rename adapter (currently does not work)") - color: Colours.palette.m3outline - font: Tokens.font.label.small - } - - StyledTextField { - id: adapterNameEdit - - anchors.left: parent.left - anchors.right: parent.right - anchors.top: renameLabel.bottom - anchors.leftMargin: root.session.bt.editingAdapterName ? 0 : -Tokens.padding.medium - - text: root.session.bt.currentAdapter?.name ?? "" - readOnly: !root.session.bt.editingAdapterName - onAccepted: { - root.session.bt.editingAdapterName = false; - } - - leftPadding: Tokens.padding.medium - rightPadding: Tokens.padding.medium - - background: StyledRect { - radius: Tokens.rounding.medium - border.width: 2 - border.color: Colours.palette.m3primary - opacity: root.session.bt.editingAdapterName ? 1 : 0 - - Behavior on border.color { - CAnim {} - } - - Behavior on opacity { - Anim {} - } - } - - Behavior on anchors.leftMargin { - Anim {} - } - } - } - - StyledRect { - implicitWidth: implicitHeight - implicitHeight: cancelEditIcon.implicitHeight + Tokens.padding.large - - radius: Tokens.rounding.medium - color: Colours.palette.m3secondaryContainer - opacity: root.session.bt.editingAdapterName ? 1 : 0 - scale: root.session.bt.editingAdapterName ? 1 : 0.5 - - StateLayer { - onClicked: { - root.session.bt.editingAdapterName = false; - adapterNameEdit.text = Qt.binding(() => root.session.bt.currentAdapter?.name ?? ""); - } - - color: Colours.palette.m3onSecondaryContainer - disabled: !root.session.bt.editingAdapterName - } - - MaterialIcon { - id: cancelEditIcon - - anchors.centerIn: parent - animate: true - text: "cancel" - color: Colours.palette.m3onSecondaryContainer - } - - Behavior on opacity { - Anim {} - } - - Behavior on scale { - Anim { - type: Anim.FastSpatial - } - } - } - - StyledRect { - implicitWidth: implicitHeight - implicitHeight: editIcon.implicitHeight + Tokens.padding.large - - radius: root.session.bt.editingAdapterName ? Tokens.rounding.medium : implicitHeight / 2 * Math.min(1, Tokens.rounding.scale) - color: Qt.alpha(Colours.palette.m3primary, root.session.bt.editingAdapterName ? 1 : 0) - - StateLayer { - onClicked: { - root.session.bt.editingAdapterName = !root.session.bt.editingAdapterName; - if (root.session.bt.editingAdapterName) - adapterNameEdit.forceActiveFocus(); - else - adapterNameEdit.accepted(); - } - - color: root.session.bt.editingAdapterName ? Colours.palette.m3onPrimary : Colours.palette.m3onSurface - } - - MaterialIcon { - id: editIcon - - anchors.centerIn: parent - animate: true - text: root.session.bt.editingAdapterName ? "check_circle" : "edit" - color: root.session.bt.editingAdapterName ? Colours.palette.m3onPrimary : Colours.palette.m3onSurface - } - - Behavior on radius { - Anim {} - } - } - } - } - } - - StyledText { - Layout.topMargin: Tokens.spacing.largeIncreased - text: qsTr("Adapter information") - font: Tokens.font.body.builders.large.weight(Font.Medium).build() - } - - StyledText { - text: qsTr("Information about the default adapter") - color: Colours.palette.m3outline - } - - StyledRect { - Layout.fillWidth: true - implicitHeight: adapterInfo.implicitHeight + Tokens.padding.extraLargeIncreased - - radius: Tokens.rounding.large - color: Colours.tPalette.m3surfaceContainer - - ColumnLayout { - id: adapterInfo - - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - anchors.margins: Tokens.padding.large - - spacing: Tokens.spacing.extraSmall - - StyledText { - text: qsTr("Adapter state") - } - - StyledText { - text: Bluetooth.defaultAdapter ? BluetoothAdapterState.toString(Bluetooth.defaultAdapter.state) : qsTr("Unknown") - color: Colours.palette.m3outline - font: Tokens.font.body.small - } - - StyledText { - Layout.topMargin: Tokens.spacing.medium - text: qsTr("Dbus path") - } - - StyledText { - text: Bluetooth.defaultAdapter?.dbusPath ?? "" - color: Colours.palette.m3outline - font: Tokens.font.body.small - } - - StyledText { - Layout.topMargin: Tokens.spacing.medium - text: qsTr("Adapter id") - } - - StyledText { - text: Bluetooth.defaultAdapter?.adapterId ?? "" - color: Colours.palette.m3outline - font: Tokens.font.body.small - } - } - } - - component Toggle: RowLayout { - required property string label - property alias checked: toggle.checked - property alias toggle: toggle - - Layout.fillWidth: true - spacing: Tokens.spacing.medium - - StyledText { - Layout.fillWidth: true - text: parent.label - } - - StyledSwitch { - id: toggle - - cLayer: 2 - } - } -} diff --git a/modules/controlcenter/components/ConnectedButtonGroup.qml b/modules/controlcenter/components/ConnectedButtonGroup.qml deleted file mode 100644 index 1aedbbd9..00000000 --- a/modules/controlcenter/components/ConnectedButtonGroup.qml +++ /dev/null @@ -1,114 +0,0 @@ -import ".." -import QtQuick -import QtQuick.Layouts -import Caelestia.Config -import qs.components -import qs.components.controls -import qs.components.effects -import qs.services - -StyledRect { - id: root - - property var options: [] // Array of {label: string, propertyName: string, onToggled: function, state: bool?} - property var rootItem: null // The root item that contains the properties we want to bind to - property string title: "" // Optional title text - property int rows: 1 // Number of rows - - Layout.fillWidth: true - implicitHeight: layout.implicitHeight + Tokens.padding.extraLargeIncreased - radius: Tokens.rounding.large - color: Colours.layer(Colours.palette.m3surfaceContainer, 2) - clip: true - - Behavior on implicitHeight { - Anim {} - } - - ColumnLayout { - id: layout - - anchors.fill: parent - anchors.margins: Tokens.padding.large - spacing: Tokens.spacing.medium - - StyledText { - visible: root.title !== "" - text: root.title - font: Tokens.font.title.small - } - - GridLayout { - id: buttonGrid - - Layout.alignment: Qt.AlignHCenter - rowSpacing: Tokens.spacing.small - columnSpacing: Tokens.spacing.small - rows: root.rows - columns: Math.ceil(root.options.length / root.rows) - - Repeater { - id: repeater - - model: root.options - - delegate: TextButton { - id: button - - required property int index - required property var modelData - - property bool _checked: false - - Layout.fillWidth: true - text: modelData.label - checked: _checked - isToggle: false - type: TextButton.Tonal - - // Create binding in Component.onCompleted - Component.onCompleted: { - if (modelData.state !== undefined && modelData.state) { - _checked = modelData.state; - } else if (root.rootItem && modelData.propertyName) { - const propName = modelData.propertyName; - const rootItem = root.rootItem; - _checked = Qt.binding(function () { - return rootItem[propName] ?? false; - }); - } - } - - // Match utilities Toggles radius styling - // Each button has full rounding (not connected) since they have spacing - radius: stateLayer.pressed ? Tokens.rounding.medium / 2 : internalChecked ? Tokens.rounding.medium : Tokens.rounding.large - - // Match utilities Toggles inactive color - inactiveColour: Colours.layer(Colours.palette.m3surfaceContainerHighest, 2) - - // Adjust width similar to utilities toggles - Layout.preferredWidth: implicitWidth + (stateLayer.pressed ? Tokens.padding.large : internalChecked ? Tokens.padding.small : 0) - - onClicked: { - if (modelData.onToggled && root.rootItem && modelData.propertyName) { - const currentValue = root.rootItem[modelData.propertyName] ?? false; - modelData.onToggled(!currentValue); - } - } - - Behavior on Layout.preferredWidth { - Anim { - type: Anim.FastSpatial - } - } - - Behavior on radius { - Anim { - type: Anim.FastSpatial - } - } - } - } - } - } -} diff --git a/modules/controlcenter/components/DeviceDetails.qml b/modules/controlcenter/components/DeviceDetails.qml deleted file mode 100644 index 1dfa327f..00000000 --- a/modules/controlcenter/components/DeviceDetails.qml +++ /dev/null @@ -1,74 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import QtQuick -import QtQuick.Layouts -import Caelestia.Config -import qs.components -import qs.components.containers -import qs.components.controls -import qs.components.effects - -Item { - id: root - - property Session session - property var device: null - - property Component headerComponent: null - property list sections: [] - - property Component topContent: null - property Component bottomContent: null - - implicitWidth: layout.implicitWidth - implicitHeight: layout.implicitHeight - - ColumnLayout { - id: layout - - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - spacing: Tokens.spacing.medium - - Loader { - id: headerLoader - - Layout.fillWidth: true - asynchronous: true - sourceComponent: root.headerComponent - visible: root.headerComponent !== null - } - - Loader { - id: topContentLoader - - Layout.fillWidth: true - asynchronous: true - sourceComponent: root.topContent - visible: root.topContent !== null - } - - Repeater { - model: root.sections - - Loader { - required property Component modelData - - Layout.fillWidth: true - asynchronous: true - sourceComponent: modelData - } - } - - Loader { - id: bottomContentLoader - - Layout.fillWidth: true - asynchronous: true - sourceComponent: root.bottomContent - visible: root.bottomContent !== null - } - } -} diff --git a/modules/controlcenter/components/DeviceList.qml b/modules/controlcenter/components/DeviceList.qml deleted file mode 100644 index a56a3bd0..00000000 --- a/modules/controlcenter/components/DeviceList.qml +++ /dev/null @@ -1,84 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import QtQuick -import QtQuick.Layouts -import Quickshell -import Caelestia.Config -import qs.components -import qs.components.containers -import qs.components.controls -import qs.services - -ColumnLayout { - id: root - - property Session session: null - property var model: null - property Component delegate: null - - property string title: "" - property string description: "" - property var activeItem: null - property Component headerComponent: null - property Component titleSuffix: null - property bool showHeader: true - property alias view: view - - signal itemSelected(var item) - - spacing: Tokens.spacing.small - - Loader { - id: headerLoader - - Layout.fillWidth: true - asynchronous: true - sourceComponent: root.headerComponent - visible: root.headerComponent !== null && root.showHeader - } - - RowLayout { - Layout.fillWidth: true - Layout.topMargin: root.headerComponent ? 0 : 0 - spacing: Tokens.spacing.small - visible: root.title !== "" || root.description !== "" - - StyledText { - visible: root.title !== "" - text: root.title - font: Tokens.font.title.builders.medium.weight(Font.Medium).build() - } - - Loader { - asynchronous: true - sourceComponent: root.titleSuffix - visible: root.titleSuffix !== null - } - - Item { - Layout.fillWidth: true - } - } - - StyledText { - visible: root.description !== "" - Layout.fillWidth: true - text: root.description - color: Colours.palette.m3outline - } - - StyledListView { - id: view - - Layout.fillWidth: true - implicitHeight: contentHeight - - model: root.model - delegate: root.delegate - - spacing: Tokens.spacing.extraSmall - interactive: false - clip: false - } -} diff --git a/modules/controlcenter/components/PaneTransition.qml b/modules/controlcenter/components/PaneTransition.qml deleted file mode 100644 index 489d3c78..00000000 --- a/modules/controlcenter/components/PaneTransition.qml +++ /dev/null @@ -1,67 +0,0 @@ -pragma ComponentBehavior: Bound - -import QtQuick -import Caelestia.Config - -SequentialAnimation { - id: root - - required property Item target - property list propertyActions - - property real scaleFrom: 1.0 - property real scaleTo: 0.8 - property real opacityFrom: 1.0 - property real opacityTo: 0.0 - - ParallelAnimation { - NumberAnimation { - target: root.target - property: "opacity" - from: root.opacityFrom - to: root.opacityTo - duration: Tokens.anim.durations.normal / 2 - easing: Tokens.anim.standardAccel - } - - NumberAnimation { - target: root.target - property: "scale" - from: root.scaleFrom - to: root.scaleTo - duration: Tokens.anim.durations.normal / 2 - easing: Tokens.anim.standardAccel - } - } - - ScriptAction { - script: { - for (let i = 0; i < root.propertyActions.length; i++) { - const action = root.propertyActions[i]; - if (action.target && action.property !== undefined) { - action.target[action.property] = action.value; - } - } - } - } - - ParallelAnimation { - NumberAnimation { - target: root.target - property: "opacity" - from: root.opacityTo - to: root.opacityFrom - duration: Tokens.anim.durations.normal / 2 - easing: Tokens.anim.standardDecel - } - - NumberAnimation { - target: root.target - property: "scale" - from: root.scaleTo - to: root.scaleFrom - duration: Tokens.anim.durations.normal / 2 - easing: Tokens.anim.standardDecel - } - } -} diff --git a/modules/controlcenter/components/ReadonlySlider.qml b/modules/controlcenter/components/ReadonlySlider.qml deleted file mode 100644 index a96114d3..00000000 --- a/modules/controlcenter/components/ReadonlySlider.qml +++ /dev/null @@ -1,67 +0,0 @@ -import ".." -import "../components" -import QtQuick -import QtQuick.Layouts -import Caelestia.Config -import qs.components -import qs.components.controls -import qs.services - -ColumnLayout { - id: root - - property string label: "" - property real value: 0 - property real from: 0 - property real to: 100 - property string suffix: "" - property bool readonly: false - - spacing: Tokens.spacing.small - - RowLayout { - Layout.fillWidth: true - spacing: Tokens.spacing.medium - - StyledText { - visible: root.label !== "" - text: root.label - font: Tokens.font.label.medium - color: root.readonly ? Colours.palette.m3outline : Colours.palette.m3onSurface - } - - Item { - Layout.fillWidth: true - } - - MaterialIcon { - visible: root.readonly - text: "lock" - color: Colours.palette.m3outline - fontStyle: Tokens.font.icon.small - } - - StyledText { - text: Math.round(root.value) + (root.suffix !== "" ? " " + root.suffix : "") - font: Tokens.font.body.medium - color: root.readonly ? Colours.palette.m3outline : Colours.palette.m3onSurface - } - } - - StyledRect { - Layout.fillWidth: true - implicitHeight: Tokens.padding.medium - radius: Tokens.rounding.full - color: Colours.layer(Colours.palette.m3surfaceContainerHighest, 1) - opacity: root.readonly ? 0.5 : 1.0 - - StyledRect { - anchors.left: parent.left - anchors.top: parent.top - anchors.bottom: parent.bottom - width: parent.width * ((root.value - root.from) / (root.to - root.from)) - radius: parent.radius - color: root.readonly ? Colours.palette.m3outline : Colours.palette.m3primary - } - } -} diff --git a/modules/controlcenter/components/SettingsHeader.qml b/modules/controlcenter/components/SettingsHeader.qml deleted file mode 100644 index bb65976b..00000000 --- a/modules/controlcenter/components/SettingsHeader.qml +++ /dev/null @@ -1,35 +0,0 @@ -pragma ComponentBehavior: Bound - -import QtQuick -import QtQuick.Layouts -import Caelestia.Config -import qs.components - -Item { - id: root - - required property string icon - required property string title - - Layout.fillWidth: true - implicitHeight: column.implicitHeight - - ColumnLayout { - id: column - - anchors.centerIn: parent - spacing: Tokens.spacing.medium - - MaterialIcon { - Layout.alignment: Qt.AlignHCenter - text: root.icon - fontStyle: Tokens.font.icon.size(84).weight(Font.Bold).build() - } - - StyledText { - Layout.alignment: Qt.AlignHCenter - text: root.title - font: Tokens.font.title.builders.medium.weight(Font.Bold).build() - } - } -} diff --git a/modules/controlcenter/components/SliderInput.qml b/modules/controlcenter/components/SliderInput.qml deleted file mode 100644 index 24241859..00000000 --- a/modules/controlcenter/components/SliderInput.qml +++ /dev/null @@ -1,180 +0,0 @@ -pragma ComponentBehavior: Bound - -import QtQuick -import QtQuick.Layouts -import Caelestia.Config -import qs.components -import qs.components.controls -import qs.components.effects -import qs.services - -ColumnLayout { - id: root - - property string label: "" - property real value: 0 - property real from: 0 - property real to: 100 - property real stepSize: 0 - property var validator: null - property string suffix: "" // Optional suffix text (e.g., "×", "px") - property int decimals: 1 // Number of decimal places to show (default: 1) - property var formatValueFunction: null // Optional custom format function - property var parseValueFunction: null // Optional custom parse function - property bool _initialized: false - - signal valueModified(real newValue) - - function formatValue(val: real): string { - if (formatValueFunction) { - return formatValueFunction(val); - } - // Default format function - // Check if it's an IntValidator (IntValidator doesn't have a 'decimals' property) - if (validator && validator.bottom !== undefined && validator.decimals === undefined) { - return Math.round(val).toString(); - } - // For DoubleValidator or no validator, use the decimals property - return val.toFixed(root.decimals); - } - - function parseValue(text: string): real { - if (parseValueFunction) { - return parseValueFunction(text); - } - // Default parse function - if (validator && validator.bottom !== undefined) { - // Check if it's an integer validator - if (validator.top !== undefined && validator.top === Math.floor(validator.top)) { - return parseInt(text); - } - } - return parseFloat(text); - } - - spacing: Tokens.spacing.small - - Component.onCompleted: { - // Set initialized flag after a brief delay to allow component to fully load - Qt.callLater(() => { - _initialized = true; - }); - } - - // Update input field when value changes externally (slider is already bound) - onValueChanged: { - // Only update if component is initialized to avoid issues during creation - if (root._initialized && !inputField.hasFocus) { - inputField.text = root.formatValue(root.value); - } - } - - RowLayout { - Layout.fillWidth: true - spacing: Tokens.spacing.medium - - StyledText { - visible: root.label !== "" - text: root.label - font: Tokens.font.label.medium - } - - Item { - Layout.fillWidth: true - } - - StyledInputField { - id: inputField - - Layout.preferredWidth: 70 - validator: root.validator - - Component.onCompleted: { - // Initialize text without triggering valueModified signal - text = root.formatValue(root.value); - } - - onTextEdited: text => { - if (hasFocus) { - const val = root.parseValue(text); - if (!isNaN(val)) { - // Validate against validator bounds if available - let isValid = true; - if (root.validator) { - if (root.validator.bottom !== undefined && val < root.validator.bottom) { - isValid = false; - } - if (root.validator.top !== undefined && val > root.validator.top) { - isValid = false; - } - } - - if (isValid) { - root.valueModified(val); - } - } - } - } - - onEditingFinished: { - const val = root.parseValue(text); - let isValid = true; - if (root.validator) { - if (root.validator.bottom !== undefined && val < root.validator.bottom) { - isValid = false; - } - if (root.validator.top !== undefined && val > root.validator.top) { - isValid = false; - } - } - - if (isNaN(val) || !isValid) { - text = root.formatValue(root.value); - } - } - } - - StyledText { - visible: root.suffix !== "" - text: root.suffix - color: Colours.palette.m3outline - font: Tokens.font.body.medium - } - } - - StyledSlider { - id: slider - - Layout.fillWidth: true - implicitHeight: Tokens.padding.medium * 3 - - from: root.from - to: root.to - stepSize: root.stepSize - - onValueChanged: { - // Update input field text in real-time as slider moves during dragging - // Always update when slider value changes (during dragging or external updates) - if (!inputField.hasFocus) { - const newValue = root.stepSize > 0 ? Math.round(value / root.stepSize) * root.stepSize : value; - inputField.text = root.formatValue(newValue); - } - } - - onMoved: { - const newValue = root.stepSize > 0 ? Math.round(value / root.stepSize) * root.stepSize : value; - root.valueModified(newValue); - if (!inputField.hasFocus) { - inputField.text = root.formatValue(newValue); - } - } - - // Use Binding to allow slider to move freely during dragging - Binding { - target: slider - property: "value" - value: root.value - when: !slider.pressed - } - } -} diff --git a/modules/controlcenter/components/SplitPaneLayout.qml b/modules/controlcenter/components/SplitPaneLayout.qml deleted file mode 100644 index 8cf23d5c..00000000 --- a/modules/controlcenter/components/SplitPaneLayout.qml +++ /dev/null @@ -1,109 +0,0 @@ -pragma ComponentBehavior: Bound - -import QtQuick -import QtQuick.Layouts -import Quickshell.Widgets -import Caelestia.Config -import qs.components -import qs.components.effects - -RowLayout { - id: root - - property Component leftContent: null - property Component rightContent: null - property real leftWidthRatio: 0.4 - property int leftMinimumWidth: 420 - property var leftLoaderProperties: ({}) - property var rightLoaderProperties: ({}) - property alias leftLoader: leftLoader - property alias rightLoader: rightLoader - - spacing: 0 - - Item { - id: leftPane - - Layout.preferredWidth: Math.floor(parent.width * root.leftWidthRatio) - Layout.minimumWidth: root.leftMinimumWidth - Layout.fillHeight: true - - ClippingRectangle { - id: leftClippingRect - - anchors.fill: parent - anchors.margins: Tokens.padding.medium - anchors.leftMargin: 0 - anchors.rightMargin: Tokens.padding.medium / 2 - - radius: leftBorder.innerRadius - color: "transparent" - - Loader { - id: leftLoader - - anchors.fill: parent - anchors.margins: Tokens.padding.large + Tokens.padding.medium - anchors.leftMargin: Tokens.padding.large - anchors.rightMargin: Tokens.padding.large + Tokens.padding.medium / 2 - - asynchronous: true - sourceComponent: root.leftContent - - Component.onCompleted: { - for (const key in root.leftLoaderProperties) { - leftLoader[key] = root.leftLoaderProperties[key]; - } - } - } - } - - InnerBorder { - id: leftBorder - - leftThickness: 0 - rightThickness: Tokens.padding.medium / 2 - } - } - - Item { - id: rightPane - - Layout.fillWidth: true - Layout.fillHeight: true - - ClippingRectangle { - id: rightClippingRect - - anchors.fill: parent - anchors.margins: Tokens.padding.medium - anchors.leftMargin: 0 - anchors.rightMargin: Tokens.padding.medium / 2 - - radius: rightBorder.innerRadius - color: "transparent" - - Loader { - id: rightLoader - - anchors.fill: parent - anchors.margins: Tokens.padding.extraLargeIncreased - - asynchronous: true - sourceComponent: root.rightContent - - Component.onCompleted: { - for (const key in root.rightLoaderProperties) { - rightLoader[key] = root.rightLoaderProperties[key]; - } - } - } - } - - InnerBorder { - id: rightBorder - - leftThickness: Tokens.padding.medium / 2 - } - } -} diff --git a/modules/controlcenter/components/SplitPaneWithDetails.qml b/modules/controlcenter/components/SplitPaneWithDetails.qml deleted file mode 100644 index ad1c444d..00000000 --- a/modules/controlcenter/components/SplitPaneWithDetails.qml +++ /dev/null @@ -1,95 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import QtQuick -import QtQuick.Layouts -import Quickshell.Widgets -import Caelestia.Config -import qs.components -import qs.components.containers -import qs.components.effects - -Item { - id: root - - required property Component leftContent - required property Component rightDetailsComponent - required property Component rightSettingsComponent - - property var activeItem: null - property var paneIdGenerator: function (item) { - return item ? String(item) : ""; - } - - property Component overlayComponent: null - - SplitPaneLayout { - id: splitLayout - - anchors.fill: parent - - leftContent: root.leftContent - - rightContent: Component { - Item { - id: rightPaneItem - - property var pane: root.activeItem - property string paneId: root.paneIdGenerator(pane) - property Component targetComponent: root.rightSettingsComponent - property Component nextComponent: root.rightSettingsComponent - - function getComponentForPane() { - return pane ? root.rightDetailsComponent : root.rightSettingsComponent; - } - - Component.onCompleted: { - targetComponent = getComponentForPane(); - nextComponent = targetComponent; - } - - onPaneChanged: { - nextComponent = getComponentForPane(); - paneId = root.paneIdGenerator(pane); - } - - Loader { - id: rightLoader - - anchors.fill: parent - - asynchronous: true - opacity: 1 - scale: 1 - transformOrigin: Item.Center - - clip: false - sourceComponent: rightPaneItem.targetComponent - } - - Behavior on paneId { - PaneTransition { - target: rightLoader - propertyActions: [ - PropertyAction { - target: rightPaneItem - property: "targetComponent" - value: rightPaneItem.nextComponent - } - ] - } - } - } - } - } - - Loader { - id: overlayLoader - - anchors.fill: parent - asynchronous: true - z: 1000 - sourceComponent: root.overlayComponent - active: root.overlayComponent !== null - } -} diff --git a/modules/controlcenter/components/WallpaperGrid.qml b/modules/controlcenter/components/WallpaperGrid.qml deleted file mode 100644 index a2378734..00000000 --- a/modules/controlcenter/components/WallpaperGrid.qml +++ /dev/null @@ -1,233 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import QtQuick -import Caelestia.Config -import Caelestia.Models -import qs.components -import qs.components.controls -import qs.components.effects -import qs.components.images -import qs.services - -GridView { - id: root - - required property Session session - - readonly property int minCellWidth: 200 + Tokens.spacing.medium - readonly property int columnsCount: Math.max(1, Math.floor(width / minCellWidth)) - - cellWidth: width / columnsCount - cellHeight: 140 + Tokens.spacing.medium - - model: Wallpapers.list - - clip: true - - StyledScrollBar.vertical: StyledScrollBar { - flickable: root - } - - delegate: Item { - required property var modelData - required property int index - readonly property bool isCurrent: modelData && modelData.path === Wallpapers.actualCurrent - readonly property real itemMargin: Tokens.spacing.medium / 2 - readonly property real itemRadius: Tokens.rounding.large - - width: root.cellWidth - height: root.cellHeight - - StateLayer { - onClicked: { - Wallpapers.setWallpaper(modelData.path); - } - - anchors.fill: parent - anchors.leftMargin: itemMargin - anchors.rightMargin: itemMargin - anchors.topMargin: itemMargin - anchors.bottomMargin: itemMargin - radius: itemRadius - } - - StyledClippingRect { - id: image - - anchors.fill: parent - anchors.leftMargin: itemMargin - anchors.rightMargin: itemMargin - anchors.topMargin: itemMargin - anchors.bottomMargin: itemMargin - color: Colours.tPalette.m3surfaceContainer - radius: itemRadius - antialiasing: true - layer.enabled: true - layer.smooth: true - - CachingImage { - id: cachingImage - - path: modelData.path - anchors.fill: parent - fillMode: Image.PreserveAspectCrop - cache: true - visible: opacity > 0 - antialiasing: true - smooth: true - sourceSize: Qt.size(width, height) - - opacity: status === Image.Ready ? 1 : 0 - - Behavior on opacity { - NumberAnimation { - duration: 1000 - easing.type: Easing.OutQuad - } - } - } - - // Fallback if CachingImage fails to load - Image { - id: fallbackImage - - anchors.fill: parent - source: fallbackTimer.triggered && cachingImage.status !== Image.Ready ? modelData.path : "" - asynchronous: true - fillMode: Image.PreserveAspectCrop - cache: true - visible: opacity > 0 - antialiasing: true - smooth: true - sourceSize: Qt.size(width, height) - - opacity: status === Image.Ready && cachingImage.status !== Image.Ready ? 1 : 0 - - Behavior on opacity { - NumberAnimation { - duration: 1000 - easing.type: Easing.OutQuad - } - } - } - - Timer { - id: fallbackTimer - - property bool triggered: false - - interval: 800 - running: cachingImage.status === Image.Loading || cachingImage.status === Image.Null - onTriggered: triggered = true - } - - // Gradient overlay for filename - Rectangle { - id: filenameOverlay - - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: parent.bottom - - implicitHeight: filenameText.implicitHeight + Tokens.padding.medium * 1.5 - radius: 0 - - gradient: Gradient { - GradientStop { - position: 0.0 - color: Qt.rgba(Colours.palette.m3surface.r, Colours.palette.m3surface.g, Colours.palette.m3surface.b, 0) - } - GradientStop { - position: 0.3 - color: Qt.rgba(Colours.palette.m3surface.r, Colours.palette.m3surface.g, Colours.palette.m3surface.b, 0.7) - } - GradientStop { - position: 0.6 - color: Qt.rgba(Colours.palette.m3surface.r, Colours.palette.m3surface.g, Colours.palette.m3surface.b, 0.9) - } - GradientStop { - position: 1.0 - color: Qt.rgba(Colours.palette.m3surface.r, Colours.palette.m3surface.g, Colours.palette.m3surface.b, 0.95) - } - } - - opacity: 0 - - Component.onCompleted: { - opacity = 1; - } - - Behavior on opacity { - NumberAnimation { - duration: 1000 - easing.type: Easing.OutCubic - } - } - } - } - - Rectangle { - anchors.fill: parent - anchors.leftMargin: itemMargin - anchors.rightMargin: itemMargin - anchors.topMargin: itemMargin - anchors.bottomMargin: itemMargin - color: "transparent" - radius: itemRadius + border.width - border.width: isCurrent ? 2 : 0 - border.color: Colours.palette.m3primary - antialiasing: true - smooth: true - - Behavior on border.width { - NumberAnimation { - duration: 150 - easing.type: Easing.OutQuad - } - } - - MaterialIcon { - anchors.right: parent.right - anchors.top: parent.top - anchors.margins: Tokens.padding.extraSmall - - visible: isCurrent - text: "check_circle" - color: Colours.palette.m3primary - fontStyle: Tokens.font.icon.large - } - } - - StyledText { - id: filenameText - - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: parent.bottom - anchors.leftMargin: Tokens.padding.medium + Tokens.spacing.medium / 2 - anchors.rightMargin: Tokens.padding.medium + Tokens.spacing.medium / 2 - anchors.bottomMargin: Tokens.padding.medium - - text: modelData.name - font: Tokens.font.body.builders.small.weight(Font.Medium).build() - color: isCurrent ? Colours.palette.m3primary : Colours.palette.m3onSurface - elide: Text.ElideMiddle - maximumLineCount: 1 - horizontalAlignment: Text.AlignHCenter - - opacity: 0 - - Component.onCompleted: { - opacity = 1; - } - - Behavior on opacity { - NumberAnimation { - duration: 1000 - easing.type: Easing.OutCubic - } - } - } - } -} diff --git a/modules/controlcenter/dashboard/DashboardPane.qml b/modules/controlcenter/dashboard/DashboardPane.qml deleted file mode 100644 index d69d0745..00000000 --- a/modules/controlcenter/dashboard/DashboardPane.qml +++ /dev/null @@ -1,138 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "../components" -import QtQuick -import QtQuick.Layouts -import Quickshell -import Quickshell.Widgets -import Caelestia.Config -import qs.components -import qs.components.containers -import qs.components.controls -import qs.components.effects -import qs.services -import qs.utils - -Item { - id: root - - required property Session session - - // General Settings - property bool enabled: Config.dashboard.enabled ?? true - property bool showOnHover: Config.dashboard.showOnHover ?? true - property int mediaUpdateInterval: GlobalConfig.dashboard.mediaUpdateInterval ?? 1000 - property int resourceUpdateInterval: GlobalConfig.dashboard.resourceUpdateInterval ?? 1000 - property int dragThreshold: Config.dashboard.dragThreshold ?? 50 - - // Dashboard Tabs - property bool showDashboard: Config.dashboard.showDashboard ?? true - property bool showMedia: Config.dashboard.showMedia ?? true - property bool showPerformance: Config.dashboard.showPerformance ?? true - property bool showWeather: Config.dashboard.showWeather ?? true - - // Performance Resources - property bool showBattery: Config.dashboard.performance.showBattery ?? false - property bool showGpu: Config.dashboard.performance.showGpu ?? true - property bool showCpu: Config.dashboard.performance.showCpu ?? true - property bool showMemory: Config.dashboard.performance.showMemory ?? true - property bool showStorage: Config.dashboard.performance.showStorage ?? true - property bool showNetwork: Config.dashboard.performance.showNetwork ?? true - - function saveConfig() { - GlobalConfig.dashboard.enabled = root.enabled; - GlobalConfig.dashboard.showOnHover = root.showOnHover; - GlobalConfig.dashboard.mediaUpdateInterval = root.mediaUpdateInterval; - GlobalConfig.dashboard.resourceUpdateInterval = root.resourceUpdateInterval; - GlobalConfig.dashboard.dragThreshold = root.dragThreshold; - GlobalConfig.dashboard.showDashboard = root.showDashboard; - GlobalConfig.dashboard.showMedia = root.showMedia; - GlobalConfig.dashboard.showPerformance = root.showPerformance; - GlobalConfig.dashboard.showWeather = root.showWeather; - GlobalConfig.dashboard.performance.showBattery = root.showBattery; - GlobalConfig.dashboard.performance.showGpu = root.showGpu; - GlobalConfig.dashboard.performance.showCpu = root.showCpu; - GlobalConfig.dashboard.performance.showMemory = root.showMemory; - GlobalConfig.dashboard.performance.showStorage = root.showStorage; - GlobalConfig.dashboard.performance.showNetwork = root.showNetwork; - // Note: sizes properties are readonly and cannot be modified - } - - anchors.fill: parent - - ClippingRectangle { - id: dashboardClippingRect - - anchors.fill: parent - anchors.margins: Tokens.padding.medium - anchors.leftMargin: 0 - anchors.rightMargin: Tokens.padding.medium - - radius: dashboardBorder.innerRadius - color: "transparent" - - Loader { - id: dashboardLoader - - anchors.fill: parent - anchors.margins: Tokens.padding.large + Tokens.padding.medium - anchors.leftMargin: Tokens.padding.large - anchors.rightMargin: Tokens.padding.large - - asynchronous: true - sourceComponent: dashboardContentComponent - } - } - - InnerBorder { - id: dashboardBorder - - leftThickness: 0 - rightThickness: Tokens.padding.medium - } - - Component { - id: dashboardContentComponent - - StyledFlickable { - id: dashboardFlickable - - flickableDirection: Flickable.VerticalFlick - contentHeight: dashboardLayout.height - - StyledScrollBar.vertical: StyledScrollBar { - flickable: dashboardFlickable - } - - ColumnLayout { - id: dashboardLayout - - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - - spacing: Tokens.spacing.medium - - RowLayout { - spacing: Tokens.spacing.medium - - StyledText { - text: qsTr("Dashboard") - font: Tokens.font.title.builders.medium.weight(Font.Medium).build() - } - } - - // General Settings Section - GeneralSection { - rootItem: root - } - - // Performance Resources Section - PerformanceSection { - rootItem: root - } - } - } - } -} diff --git a/modules/controlcenter/dashboard/GeneralSection.qml b/modules/controlcenter/dashboard/GeneralSection.qml deleted file mode 100644 index 42b67c79..00000000 --- a/modules/controlcenter/dashboard/GeneralSection.qml +++ /dev/null @@ -1,128 +0,0 @@ -import ".." -import "../components" -import QtQuick -import QtQuick.Layouts -import Caelestia.Config -import qs.components -import qs.components.controls -import qs.services - -SectionContainer { - id: root - - required property var rootItem - - Layout.fillWidth: true - alignTop: true - - StyledText { - text: qsTr("General Settings") - font: Tokens.font.title.small - } - - SwitchRow { - label: qsTr("Enabled") - checked: root.rootItem.enabled - onToggled: checked => { - root.rootItem.enabled = checked; - root.rootItem.saveConfig(); - } - } - - SwitchRow { - label: qsTr("Show on hover") - checked: root.rootItem.showOnHover - onToggled: checked => { - root.rootItem.showOnHover = checked; - root.rootItem.saveConfig(); - } - } - - RowLayout { - Layout.fillWidth: true - spacing: Tokens.spacing.medium - - SwitchRow { - Layout.fillWidth: true - label: qsTr("Show Dashboard tab") - checked: root.rootItem.showDashboard - onToggled: checked => { - root.rootItem.showDashboard = checked; - root.rootItem.saveConfig(); - } - } - - SwitchRow { - Layout.fillWidth: true - label: qsTr("Show Media tab") - checked: root.rootItem.showMedia - onToggled: checked => { - root.rootItem.showMedia = checked; - root.rootItem.saveConfig(); - } - } - - SwitchRow { - Layout.fillWidth: true - label: qsTr("Show Performance tab") - checked: root.rootItem.showPerformance - onToggled: checked => { - root.rootItem.showPerformance = checked; - root.rootItem.saveConfig(); - } - } - - SwitchRow { - Layout.fillWidth: true - label: qsTr("Show Weather tab") - checked: root.rootItem.showWeather - onToggled: checked => { - root.rootItem.showWeather = checked; - root.rootItem.saveConfig(); - } - } - } - - SliderInput { - Layout.fillWidth: true - - label: qsTr("Media update interval") - value: root.rootItem.mediaUpdateInterval - from: 100 - to: 10000 - stepSize: 100 - suffix: "ms" - validator: IntValidator { - bottom: 100 - top: 10000 - } - formatValueFunction: val => Math.round(val).toString() - parseValueFunction: text => parseInt(text) - - onValueModified: newValue => { - root.rootItem.mediaUpdateInterval = Math.round(newValue); - root.rootItem.saveConfig(); - } - } - - SliderInput { - Layout.fillWidth: true - - label: qsTr("Drag threshold") - value: root.rootItem.dragThreshold - from: 0 - to: 100 - suffix: "px" - validator: IntValidator { - bottom: 0 - top: 100 - } - formatValueFunction: val => Math.round(val).toString() - parseValueFunction: text => parseInt(text) - - onValueModified: newValue => { - root.rootItem.dragThreshold = Math.round(newValue); - root.rootItem.saveConfig(); - } - } -} diff --git a/modules/controlcenter/dashboard/PerformanceSection.qml b/modules/controlcenter/dashboard/PerformanceSection.qml deleted file mode 100644 index 12562834..00000000 --- a/modules/controlcenter/dashboard/PerformanceSection.qml +++ /dev/null @@ -1,107 +0,0 @@ -import ".." -import "../components" -import QtQuick -import QtQuick.Layouts -import Quickshell.Services.UPower -import Caelestia.Config -import Caelestia.Services -import qs.components -import qs.components.controls -import qs.services - -SectionContainer { - id: root - - required property var rootItem - // GPU toggle is hidden when type is Gpu.None (no GPU data available) - readonly property bool gpuAvailable: Gpu.type !== Gpu.None - // Battery toggle is hidden when no laptop battery is present - readonly property bool batteryAvailable: UPower.displayDevice.isLaptopBattery - - Layout.fillWidth: true - alignTop: true - - StyledText { - text: qsTr("Performance Resources") - font: Tokens.font.title.small - } - - ConnectedButtonGroup { - rootItem: root.rootItem - options: { - let opts = []; - if (root.batteryAvailable) - opts.push({ - "label": qsTr("Battery"), - "propertyName": "showBattery", - "onToggled": function (checked) { - root.rootItem.showBattery = checked; - root.rootItem.saveConfig(); - } - }); - - if (root.gpuAvailable) - opts.push({ - "label": qsTr("GPU"), - "propertyName": "showGpu", - "onToggled": function (checked) { - root.rootItem.showGpu = checked; - root.rootItem.saveConfig(); - } - }); - - opts.push({ - "label": qsTr("CPU"), - "propertyName": "showCpu", - "onToggled": function (checked) { - root.rootItem.showCpu = checked; - root.rootItem.saveConfig(); - } - }, { - "label": qsTr("Memory"), - "propertyName": "showMemory", - "onToggled": function (checked) { - root.rootItem.showMemory = checked; - root.rootItem.saveConfig(); - } - }, { - "label": qsTr("Storage"), - "propertyName": "showStorage", - "onToggled": function (checked) { - root.rootItem.showStorage = checked; - root.rootItem.saveConfig(); - } - }, { - "label": qsTr("Network"), - "propertyName": "showNetwork", - "onToggled": function (checked) { - root.rootItem.showNetwork = checked; - root.rootItem.saveConfig(); - } - }); - return opts; - } - } - - SliderInput { - Layout.fillWidth: true - - label: qsTr("Resource update interval") - value: root.rootItem.resourceUpdateInterval - from: 100 - to: 10000 - stepSize: 100 - suffix: "ms" - validator: IntValidator { - bottom: 100 - top: 10000 - } - formatValueFunction: val => Math.round(val).toString() - parseValueFunction: text => parseInt(text) - - onValueModified: newValue => { - root.rootItem.resourceUpdateInterval = Math.round(newValue); - root.rootItem.saveConfig(); - } - } -} diff --git a/modules/controlcenter/launcher/LauncherPane.qml b/modules/controlcenter/launcher/LauncherPane.qml deleted file mode 100644 index 51e5c760..00000000 --- a/modules/controlcenter/launcher/LauncherPane.qml +++ /dev/null @@ -1,665 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "../components" -import "../../launcher/services" -import "../../../utils/scripts/fuzzysort.js" as Fuzzy -import QtQuick -import QtQuick.Layouts -import Quickshell -import Quickshell.Widgets -import Caelestia -import Caelestia.Config -import qs.components -import qs.components.containers -import qs.components.controls -import qs.components.effects -import qs.services -import qs.utils - -Item { - id: root - - required property Session session - - property var selectedApp: root.session.launcher.active - property bool hideFromLauncherChecked: false - property bool favouriteChecked: false - property string searchText: "" - property list filteredApps: [] - - function updateToggleState() { - if (!root.selectedApp) { - root.hideFromLauncherChecked = false; - root.favouriteChecked = false; - return; - } - - const appId = root.selectedApp.id || root.selectedApp.entry?.id; - - root.hideFromLauncherChecked = GlobalConfig.launcher.hiddenApps && GlobalConfig.launcher.hiddenApps.length > 0 && Strings.testRegexList(GlobalConfig.launcher.hiddenApps, appId); - root.favouriteChecked = GlobalConfig.launcher.favouriteApps && GlobalConfig.launcher.favouriteApps.length > 0 && Strings.testRegexList(GlobalConfig.launcher.favouriteApps, appId); - } - - function saveHiddenApps(isHidden) { - if (!root.selectedApp) { - return; - } - - const appId = root.selectedApp.id || root.selectedApp.entry?.id; - - const hiddenApps = GlobalConfig.launcher.hiddenApps ? [...GlobalConfig.launcher.hiddenApps] : []; - - if (isHidden) { - if (!hiddenApps.includes(appId)) { - hiddenApps.push(appId); - } - } else { - const index = hiddenApps.indexOf(appId); - if (index !== -1) { - hiddenApps.splice(index, 1); - } - } - - GlobalConfig.launcher.hiddenApps = hiddenApps; - } - - function filterApps(search: string): list { - if (!search || search.trim() === "") { - const apps = []; - for (let i = 0; i < allAppsDb.apps.length; i++) { - apps.push(allAppsDb.apps[i]); - } - return apps; - } - - if (!allAppsDb.apps || allAppsDb.apps.length === 0) { - return []; - } - - const preparedApps = []; - for (let i = 0; i < allAppsDb.apps.length; i++) { - const app = allAppsDb.apps[i]; - const name = app.name || app.entry?.name || ""; - preparedApps.push({ - _item: app, - name: Fuzzy.prepare(name) - }); - } - - const results = Fuzzy.go(search, preparedApps, { - all: true, - keys: ["name"], - scoreFn: r => r[0].score - }); - - return results.sort((a, b) => b._score - a._score).map(r => r.obj._item); - } - - function updateFilteredApps() { - filteredApps = filterApps(searchText); - } - - anchors.fill: parent - - onSelectedAppChanged: { - root.session.launcher.active = root.selectedApp; - updateToggleState(); - } - - onSearchTextChanged: { - updateFilteredApps(); - } - - Component.onCompleted: { - updateFilteredApps(); - } - - Connections { - function onActiveChanged() { - root.selectedApp = root.session.launcher.active; - updateToggleState(); - } - - target: root.session.launcher - } - - AppDb { - id: allAppsDb - - path: `${Paths.state}/apps.sqlite` - favouriteApps: GlobalConfig.launcher.favouriteApps - entries: DesktopEntries.applications.values - } - - Connections { - function onAppsChanged() { - updateFilteredApps(); - } - - target: allAppsDb - } - - SplitPaneLayout { - anchors.fill: parent - - leftContent: Component { - ColumnLayout { - id: leftLauncherLayout - - anchors.fill: parent - - spacing: Tokens.spacing.small - - RowLayout { - spacing: Tokens.spacing.medium - - StyledText { - text: qsTr("Launcher") - font: Tokens.font.title.builders.medium.weight(Font.Medium).build() - } - - Item { - Layout.fillWidth: true - } - - ToggleButton { - toggled: !root.session.launcher.active - icon: "settings" - accent: "Primary" - iconSize: Tokens.font.body.medium.pointSize - horizontalPadding: Tokens.padding.medium - verticalPadding: Tokens.padding.small - tooltip: qsTr("Launcher settings") - - onClicked: { - if (root.session.launcher.active) { - root.session.launcher.active = null; - } else { - if (root.filteredApps.length > 0) { - root.session.launcher.active = root.filteredApps[0]; - } - } - } - } - } - - StyledText { - Layout.topMargin: Tokens.spacing.largeIncreased - text: qsTr("Applications (%1)").arg(root.searchText ? root.filteredApps.length : allAppsDb.apps.length) - font: Tokens.font.title.builders.small.weight(Font.Medium).build() - } - - StyledText { - text: qsTr("All applications available in the launcher") - color: Colours.palette.m3outline - } - - StyledRect { - Layout.fillWidth: true - Layout.topMargin: Tokens.spacing.medium - Layout.bottomMargin: Tokens.spacing.small - - color: Colours.layer(Colours.palette.m3surfaceContainer, 2) - radius: Tokens.rounding.full - - implicitHeight: Math.max(searchIcon.implicitHeight, searchField.implicitHeight, clearIcon.implicitHeight) - - MaterialIcon { - id: searchIcon - - anchors.verticalCenter: parent.verticalCenter - anchors.left: parent.left - anchors.leftMargin: Tokens.padding.medium - - text: "search" - color: Colours.palette.m3onSurfaceVariant - } - - StyledTextField { - id: searchField - - anchors.left: searchIcon.right - anchors.right: clearIcon.left - anchors.leftMargin: Tokens.spacing.small - anchors.rightMargin: Tokens.spacing.small - - topPadding: Tokens.padding.medium - bottomPadding: Tokens.padding.medium - - placeholderText: qsTr("Search applications...") - - onTextChanged: { - root.searchText = text; - } - } - - MaterialIcon { - id: clearIcon - - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - anchors.rightMargin: Tokens.padding.medium - - width: searchField.text ? implicitWidth : implicitWidth / 2 - opacity: { - if (!searchField.text) - return 0; - if (clearMouse.pressed) - return 0.7; - if (clearMouse.containsMouse) - return 0.8; - return 1; - } - - text: "close" - color: Colours.palette.m3onSurfaceVariant - - MouseArea { - id: clearMouse - - anchors.fill: parent - hoverEnabled: true - cursorShape: searchField.text ? Qt.PointingHandCursor : undefined - - onClicked: searchField.text = "" - } - - Behavior on width { - Anim { - type: Anim.StandardSmall - } - } - - Behavior on opacity { - Anim { - type: Anim.StandardSmall - } - } - } - } - - Loader { - id: appsListLoader - - Layout.fillWidth: true - Layout.fillHeight: true - asynchronous: true - active: true - - sourceComponent: StyledListView { - id: appsListView - - Layout.fillWidth: true - Layout.fillHeight: true - - model: root.filteredApps - spacing: Tokens.spacing.extraSmall - clip: true - - StyledScrollBar.vertical: StyledScrollBar { - flickable: parent - } - - delegate: StyledRect { - required property var modelData - - readonly property bool isSelected: root.selectedApp === modelData - - width: parent ? parent.width : 0 - implicitHeight: 40 - - color: isSelected ? Colours.layer(Colours.palette.m3surfaceContainer, 2) : "transparent" - radius: Tokens.rounding.large - - opacity: 0 - - Component.onCompleted: { - opacity = 1; - } - - Behavior on opacity { - NumberAnimation { - duration: 1000 - easing.type: Easing.OutCubic - } - } - - StateLayer { - onClicked: { - root.session.launcher.active = modelData; - } - } - - RowLayout { - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - anchors.margins: Tokens.padding.medium - - spacing: Tokens.spacing.medium - - IconImage { - asynchronous: true - Layout.alignment: Qt.AlignVCenter - implicitSize: 32 - source: { - const entry = modelData.entry; - return entry ? Quickshell.iconPath(entry.icon, "image-missing") : "image-missing"; - } - } - - StyledText { - Layout.fillWidth: true - text: modelData.name || modelData.entry?.name || qsTr("Unknown") - font: Tokens.font.body.medium - } - - Loader { - readonly property bool isHidden: modelData ? Strings.testRegexList(GlobalConfig.launcher.hiddenApps, modelData.id) : false - readonly property bool isFav: modelData ? Strings.testRegexList(GlobalConfig.launcher.favouriteApps, modelData.id) : false - - Layout.alignment: Qt.AlignVCenter - asynchronous: true - active: isHidden || isFav - - sourceComponent: isHidden ? hiddenIcon : (isFav ? favouriteIcon : null) - } - - Component { - id: hiddenIcon - - MaterialIcon { - text: "visibility_off" - fill: 1 - color: Colours.palette.m3primary - } - } - - Component { - id: favouriteIcon - - MaterialIcon { - text: "favorite" - fill: 1 - color: Colours.palette.m3primary - } - } - } - } - } - } - } - } - - rightContent: Component { - Item { - id: rightLauncherPane - - property var pane: root.session.launcher.active - property string paneId: pane ? (pane.id || pane.entry?.id || "") : "" - property Component targetComponent: settings - property Component nextComponent: settings - property var displayedApp: null - - function getComponentForPane() { - return pane ? appDetails : settings; - } - - Component.onCompleted: { - displayedApp = pane; - targetComponent = getComponentForPane(); - nextComponent = targetComponent; - } - - onPaneChanged: { - nextComponent = getComponentForPane(); - paneId = pane ? (pane.id || pane.entry?.id || "") : ""; - } - - onDisplayedAppChanged: { - if (displayedApp) { - const appId = displayedApp.id || displayedApp.entry?.id; - root.hideFromLauncherChecked = GlobalConfig.launcher.hiddenApps && GlobalConfig.launcher.hiddenApps.length > 0 && Strings.testRegexList(GlobalConfig.launcher.hiddenApps, appId); - root.favouriteChecked = GlobalConfig.launcher.favouriteApps && GlobalConfig.launcher.favouriteApps.length > 0 && Strings.testRegexList(GlobalConfig.launcher.favouriteApps, appId); - } else { - root.hideFromLauncherChecked = false; - root.favouriteChecked = false; - } - } - - Loader { - id: rightLauncherLoader - - property var displayedApp: rightLauncherPane.displayedApp - - anchors.fill: parent - - asynchronous: true - opacity: 1 - scale: 1 - transformOrigin: Item.Center - clip: false - - sourceComponent: rightLauncherPane.targetComponent - active: true - - onItemChanged: { - if (item && rightLauncherPane.pane && rightLauncherPane.displayedApp !== rightLauncherPane.pane) { - rightLauncherPane.displayedApp = rightLauncherPane.pane; - } - } - } - - Behavior on paneId { - PaneTransition { - target: rightLauncherLoader - propertyActions: [ - PropertyAction { - target: rightLauncherPane - property: "displayedApp" - value: rightLauncherPane.pane - }, - PropertyAction { - target: rightLauncherLoader - property: "active" - value: false - }, - PropertyAction { - target: rightLauncherPane - property: "targetComponent" - value: rightLauncherPane.nextComponent - }, - PropertyAction { - target: rightLauncherLoader - property: "active" - value: true - } - ] - } - } - } - } - } - - Component { - id: settings - - StyledFlickable { - id: settingsFlickable - - flickableDirection: Flickable.VerticalFlick - contentHeight: settingsInner.height - - StyledScrollBar.vertical: StyledScrollBar { - flickable: settingsFlickable - } - - Settings { - id: settingsInner - - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - session: root.session - } - } - } - - Component { - id: appDetails - - ColumnLayout { - id: appDetailsLayout - - readonly property var displayedApp: parent && parent.displayedApp !== undefined ? parent.displayedApp : null - - anchors.fill: parent - spacing: Tokens.spacing.medium - - SettingsHeader { - Layout.leftMargin: Tokens.padding.extraLargeIncreased - Layout.rightMargin: Tokens.padding.extraLargeIncreased - Layout.topMargin: Tokens.padding.extraLargeIncreased - visible: displayedApp === null - icon: "apps" - title: qsTr("Launcher Applications") - } - - Item { - Layout.alignment: Qt.AlignHCenter - Layout.leftMargin: Tokens.padding.extraLargeIncreased - Layout.rightMargin: Tokens.padding.extraLargeIncreased - Layout.topMargin: Tokens.padding.extraLargeIncreased - visible: displayedApp !== null - implicitWidth: Math.max(appIconImage.implicitWidth, appTitleText.implicitWidth) - implicitHeight: appIconImage.implicitHeight + Tokens.spacing.medium + appTitleText.implicitHeight - - ColumnLayout { - anchors.centerIn: parent - spacing: Tokens.spacing.medium - - IconImage { - id: appIconImage - - asynchronous: true - Layout.alignment: Qt.AlignHCenter - implicitSize: Tokens.font.body.large.pointSize * 3 * 2 - source: { - const app = appDetailsLayout.displayedApp; - if (!app) - return "image-missing"; - const entry = app.entry; - if (entry && entry.icon) { - return Quickshell.iconPath(entry.icon, "image-missing"); - } - return "image-missing"; - } - } - - StyledText { - id: appTitleText - - Layout.alignment: Qt.AlignHCenter - text: displayedApp ? (displayedApp.name || displayedApp.entry?.name || qsTr("Application Details")) : "" - font: Tokens.font.title.builders.medium.weight(Font.Bold).build() - } - } - } - - Item { - Layout.fillWidth: true - Layout.fillHeight: true - Layout.topMargin: Tokens.spacing.largeIncreased - Layout.leftMargin: Tokens.padding.extraLargeIncreased - Layout.rightMargin: Tokens.padding.extraLargeIncreased - - StyledFlickable { - id: detailsFlickable - - anchors.fill: parent - flickableDirection: Flickable.VerticalFlick - contentHeight: debugLayout.height - - StyledScrollBar.vertical: StyledScrollBar { - flickable: parent - } - - ColumnLayout { - id: debugLayout - - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - spacing: Tokens.spacing.medium - - SwitchRow { - Layout.topMargin: Tokens.spacing.medium - visible: appDetailsLayout.displayedApp !== null - label: qsTr("Mark as favourite") - checked: root.favouriteChecked - // disabled if: - // * app is hidden - // * app isn't in favouriteApps array but marked as favourite anyway - // ^^^ This means that this app is favourited because of a regex check - // this button can not toggle regexed apps - enabled: appDetailsLayout.displayedApp !== null && !root.hideFromLauncherChecked && (GlobalConfig.launcher.favouriteApps.indexOf(appDetailsLayout.displayedApp.id || appDetailsLayout.displayedApp.entry?.id) !== -1 || !root.favouriteChecked) - opacity: enabled ? 1 : 0.6 - onToggled: checked => { - root.favouriteChecked = checked; - const app = appDetailsLayout.displayedApp; - if (app) { - const appId = app.id || app.entry?.id; - const favouriteApps = GlobalConfig.launcher.favouriteApps ? [...GlobalConfig.launcher.favouriteApps] : []; - if (checked) { - if (!favouriteApps.includes(appId)) { - favouriteApps.push(appId); - } - } else { - const index = favouriteApps.indexOf(appId); - if (index !== -1) { - favouriteApps.splice(index, 1); - } - } - GlobalConfig.launcher.favouriteApps = favouriteApps; - } - } - } - SwitchRow { - Layout.topMargin: Tokens.spacing.medium - visible: appDetailsLayout.displayedApp !== null - label: qsTr("Hide from launcher") - checked: root.hideFromLauncherChecked - // disabled if: - // * app is favourited - // * app isn't in hiddenApps array but marked as hidden anyway - // ^^^ This means that this app is hidden because of a regex check - // this button can not toggle regexed apps - enabled: appDetailsLayout.displayedApp !== null && !root.favouriteChecked && (GlobalConfig.launcher.hiddenApps.indexOf(appDetailsLayout.displayedApp.id || appDetailsLayout.displayedApp.entry?.id) !== -1 || !root.hideFromLauncherChecked) - opacity: enabled ? 1 : 0.6 - onToggled: checked => { - root.hideFromLauncherChecked = checked; - const app = appDetailsLayout.displayedApp; - if (app) { - const appId = app.id || app.entry?.id; - const hiddenApps = GlobalConfig.launcher.hiddenApps ? [...GlobalConfig.launcher.hiddenApps] : []; - if (checked) { - if (!hiddenApps.includes(appId)) { - hiddenApps.push(appId); - } - } else { - const index = hiddenApps.indexOf(appId); - if (index !== -1) { - hiddenApps.splice(index, 1); - } - } - GlobalConfig.launcher.hiddenApps = hiddenApps; - } - } - } - } - } - } - } - } -} diff --git a/modules/controlcenter/launcher/Settings.qml b/modules/controlcenter/launcher/Settings.qml deleted file mode 100644 index 5d7581ea..00000000 --- a/modules/controlcenter/launcher/Settings.qml +++ /dev/null @@ -1,208 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "../components" -import QtQuick -import QtQuick.Layouts -import Caelestia.Config -import qs.components -import qs.components.controls -import qs.components.effects -import qs.services - -ColumnLayout { - id: root - - required property Session session - - spacing: Tokens.spacing.medium - - SettingsHeader { - icon: "apps" - title: qsTr("Launcher Settings") - } - - SectionHeader { - Layout.topMargin: Tokens.spacing.largeIncreased - title: qsTr("General") - description: qsTr("General launcher settings") - } - - SectionContainer { - ToggleRow { - label: qsTr("Enabled") - checked: Config.launcher.enabled - toggle.onToggled: { - GlobalConfig.launcher.enabled = checked; - } - } - - ToggleRow { - label: qsTr("Show on hover") - checked: Config.launcher.showOnHover - toggle.onToggled: { - GlobalConfig.launcher.showOnHover = checked; - } - } - - ToggleRow { - label: qsTr("Vim keybinds") - checked: GlobalConfig.launcher.vimKeybinds - toggle.onToggled: { - GlobalConfig.launcher.vimKeybinds = checked; - } - } - - ToggleRow { - label: qsTr("Enable dangerous actions") - checked: GlobalConfig.launcher.enableDangerousActions - toggle.onToggled: { - GlobalConfig.launcher.enableDangerousActions = checked; - } - } - } - - SectionHeader { - Layout.topMargin: Tokens.spacing.largeIncreased - title: qsTr("Display") - description: qsTr("Display and appearance settings") - } - - SectionContainer { - contentSpacing: Tokens.spacing.extraSmall - - PropertyRow { - label: qsTr("Max shown items") - value: qsTr("%1").arg(Config.launcher.maxShown) - } - - PropertyRow { - showTopMargin: true - label: qsTr("Max wallpapers") - value: qsTr("%1").arg(Config.launcher.maxWallpapers) - } - - PropertyRow { - showTopMargin: true - label: qsTr("Drag threshold") - value: qsTr("%1 px").arg(Config.launcher.dragThreshold) - } - } - - SectionHeader { - Layout.topMargin: Tokens.spacing.largeIncreased - title: qsTr("Prefixes") - description: qsTr("Command prefix settings") - } - - SectionContainer { - contentSpacing: Tokens.spacing.extraSmall - - PropertyRow { - label: qsTr("Special prefix") - value: GlobalConfig.launcher.specialPrefix || qsTr("None") - } - - PropertyRow { - showTopMargin: true - label: qsTr("Action prefix") - value: GlobalConfig.launcher.actionPrefix || qsTr("None") - } - } - - SectionHeader { - Layout.topMargin: Tokens.spacing.largeIncreased - title: qsTr("Fuzzy search") - description: qsTr("Fuzzy search settings") - } - - SectionContainer { - ToggleRow { - label: qsTr("Apps") - checked: GlobalConfig.launcher.useFuzzy.apps - toggle.onToggled: { - GlobalConfig.launcher.useFuzzy.apps = checked; - } - } - - ToggleRow { - label: qsTr("Actions") - checked: GlobalConfig.launcher.useFuzzy.actions - toggle.onToggled: { - GlobalConfig.launcher.useFuzzy.actions = checked; - } - } - - ToggleRow { - label: qsTr("Schemes") - checked: GlobalConfig.launcher.useFuzzy.schemes - toggle.onToggled: { - GlobalConfig.launcher.useFuzzy.schemes = checked; - } - } - - ToggleRow { - label: qsTr("Variants") - checked: GlobalConfig.launcher.useFuzzy.variants - toggle.onToggled: { - GlobalConfig.launcher.useFuzzy.variants = checked; - } - } - - ToggleRow { - label: qsTr("Wallpapers") - checked: GlobalConfig.launcher.useFuzzy.wallpapers - toggle.onToggled: { - GlobalConfig.launcher.useFuzzy.wallpapers = checked; - } - } - } - - SectionHeader { - Layout.topMargin: Tokens.spacing.largeIncreased - title: qsTr("Sizes") - description: qsTr("Size settings for launcher items") - } - - SectionContainer { - contentSpacing: Tokens.spacing.extraSmall - - PropertyRow { - label: qsTr("Item width") - value: qsTr("%1 px").arg(Tokens.sizes.launcher.itemWidth) - } - - PropertyRow { - showTopMargin: true - label: qsTr("Item height") - value: qsTr("%1 px").arg(Tokens.sizes.launcher.itemHeight) - } - - PropertyRow { - showTopMargin: true - label: qsTr("Wallpaper width") - value: qsTr("%1 px").arg(Tokens.sizes.launcher.wallpaperWidth) - } - - PropertyRow { - showTopMargin: true - label: qsTr("Wallpaper height") - value: qsTr("%1 px").arg(Tokens.sizes.launcher.wallpaperHeight) - } - } - - SectionHeader { - Layout.topMargin: Tokens.spacing.largeIncreased - title: qsTr("Hidden apps") - description: qsTr("Applications hidden from launcher") - } - - SectionContainer { - contentSpacing: Tokens.spacing.extraSmall - - PropertyRow { - label: qsTr("Total hidden") - value: qsTr("%1").arg(GlobalConfig.launcher.hiddenApps ? GlobalConfig.launcher.hiddenApps.length : 0) - } - } -} diff --git a/modules/controlcenter/network/EthernetDetails.qml b/modules/controlcenter/network/EthernetDetails.qml deleted file mode 100644 index e6d588c2..00000000 --- a/modules/controlcenter/network/EthernetDetails.qml +++ /dev/null @@ -1,118 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "../components" -import QtQuick -import QtQuick.Layouts -import Caelestia.Config -import qs.components -import qs.components.containers -import qs.components.controls -import qs.components.effects -import qs.services - -DeviceDetails { - id: root - - required property Session session - readonly property var ethernetDevice: root.session.ethernet.active - - device: ethernetDevice - - Component.onCompleted: { - if (ethernetDevice && ethernetDevice.interface) { - Nmcli.getEthernetDeviceDetails(ethernetDevice.interface, () => {}); - } - } - - onEthernetDeviceChanged: { - if (ethernetDevice && ethernetDevice.interface) { - Nmcli.getEthernetDeviceDetails(ethernetDevice.interface, () => {}); - } else { - Nmcli.ethernetDeviceDetails = null; - } - } - - headerComponent: Component { - ConnectionHeader { - icon: "cable" - title: root.ethernetDevice?.interface ?? qsTr("Unknown") - } - } - - sections: [ - Component { - ColumnLayout { - spacing: Tokens.spacing.medium - - SectionHeader { - title: qsTr("Connection status") - description: qsTr("Connection settings for this device") - } - - SectionContainer { - ToggleRow { - label: qsTr("Connected") - checked: root.ethernetDevice?.connected ?? false - toggle.onToggled: { - if (checked) { - Nmcli.connectEthernet(root.ethernetDevice?.connection || "", root.ethernetDevice?.interface || "", () => {}); - } else { - if (root.ethernetDevice?.connection) { - Nmcli.disconnectEthernet(root.ethernetDevice.connection, () => {}); - } - } - } - } - } - } - }, - Component { - ColumnLayout { - spacing: Tokens.spacing.medium - - SectionHeader { - title: qsTr("Device properties") - description: qsTr("Additional information") - } - - SectionContainer { - contentSpacing: Tokens.spacing.extraSmall - - PropertyRow { - label: qsTr("Interface") - value: root.ethernetDevice?.interface ?? qsTr("Unknown") - } - - PropertyRow { - showTopMargin: true - label: qsTr("Connection") - value: root.ethernetDevice?.connection || qsTr("Not connected") - } - - PropertyRow { - showTopMargin: true - label: qsTr("State") - value: root.ethernetDevice?.state ?? qsTr("Unknown") - } - } - } - }, - Component { - ColumnLayout { - spacing: Tokens.spacing.medium - - SectionHeader { - title: qsTr("Connection information") - description: qsTr("Network connection details") - } - - SectionContainer { - ConnectionInfoSection { - deviceDetails: Nmcli.ethernetDeviceDetails - } - } - } - } - ] -} diff --git a/modules/controlcenter/network/EthernetList.qml b/modules/controlcenter/network/EthernetList.qml deleted file mode 100644 index 38be9363..00000000 --- a/modules/controlcenter/network/EthernetList.qml +++ /dev/null @@ -1,177 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "../components" -import QtQuick -import QtQuick.Layouts -import Caelestia.Config -import qs.components -import qs.components.containers -import qs.components.controls -import qs.services - -DeviceList { - id: root - - required property Session session - - title: qsTr("Devices (%1)").arg(Nmcli.ethernetDevices.length) - description: qsTr("All available ethernet devices") - activeItem: session.ethernet.active - - model: Nmcli.ethernetDevices - - headerComponent: Component { - RowLayout { - spacing: Tokens.spacing.medium - - StyledText { - text: qsTr("Settings") - font: Tokens.font.title.builders.medium.weight(Font.Medium).build() - } - - Item { - Layout.fillWidth: true - } - - ToggleButton { - toggled: !root.session.ethernet.active - icon: "settings" - accent: "Primary" - iconSize: Tokens.font.body.medium.pointSize - horizontalPadding: Tokens.padding.medium - verticalPadding: Tokens.padding.small - - onClicked: { - if (root.session.ethernet.active) - root.session.ethernet.active = null; - else { - root.session.ethernet.active = root.view.model.get(0)?.modelData ?? null; - } - } - } - } - } - - delegate: Component { - StyledRect { - id: ethernetItem - - required property var modelData - readonly property bool isActive: root.activeItem && modelData && root.activeItem.interface === modelData.interface - - width: ListView.view ? ListView.view.width : undefined - implicitHeight: rowLayout.implicitHeight + Tokens.padding.medium * 2 - - color: Qt.alpha(Colours.tPalette.m3surfaceContainer, ethernetItem.isActive ? Colours.tPalette.m3surfaceContainer.a : 0) - radius: Tokens.rounding.large - - StateLayer { - id: stateLayer - - onClicked: { - root.session.ethernet.active = modelData; - } - } - - RowLayout { - id: rowLayout - - anchors.fill: parent - anchors.margins: Tokens.padding.medium - - spacing: Tokens.spacing.medium - - StyledRect { - implicitWidth: implicitHeight - implicitHeight: icon.implicitHeight + Tokens.padding.medium * 2 - - radius: Tokens.rounding.large - color: modelData.connected ? Colours.palette.m3primaryContainer : Colours.tPalette.m3surfaceContainerHigh - - StyledRect { - anchors.fill: parent - radius: parent.radius - color: Qt.alpha(modelData.connected ? Colours.palette.m3onPrimaryContainer : Colours.palette.m3onSurface, stateLayer.pressed ? 0.1 : stateLayer.containsMouse ? 0.08 : 0) - } - - MaterialIcon { - id: icon - - anchors.centerIn: parent - text: "cable" - fontStyle: Tokens.font.icon.large - fill: modelData.connected ? 1 : 0 - color: modelData.connected ? Colours.palette.m3onPrimaryContainer : Colours.palette.m3onSurface - - Behavior on fill { - Anim { - type: Anim.DefaultEffects - } - } - } - } - - ColumnLayout { - Layout.fillWidth: true - - spacing: 0 - - StyledText { - Layout.fillWidth: true - text: modelData.interface || qsTr("Unknown") - elide: Text.ElideRight - } - - RowLayout { - Layout.fillWidth: true - spacing: Tokens.spacing.medium - - StyledText { - Layout.fillWidth: true - text: modelData.connected ? qsTr("Connected") : qsTr("Disconnected") - color: modelData.connected ? Colours.palette.m3primary : Colours.palette.m3outline - font: Tokens.font.body.builders.small.weight(modelData.connected ? Font.Medium : Font.Normal).build() - elide: Text.ElideRight - } - } - } - - StyledRect { - id: connectBtn - - implicitWidth: implicitHeight - implicitHeight: connectIcon.implicitHeight + Tokens.padding.large - - radius: Tokens.rounding.full - color: Qt.alpha(Colours.palette.m3primaryContainer, modelData.connected ? 1 : 0) - - StateLayer { - onClicked: { - if (modelData.connected && modelData.connection) { - Nmcli.disconnectEthernet(modelData.connection, () => {}); - } else { - Nmcli.connectEthernet(modelData.connection || "", modelData.interface || "", () => {}); - } - } - - color: modelData.connected ? Colours.palette.m3onPrimaryContainer : Colours.palette.m3onSurface - } - - MaterialIcon { - id: connectIcon - - anchors.centerIn: parent - animate: true - text: modelData.connected ? "link_off" : "link" - color: modelData.connected ? Colours.palette.m3onPrimaryContainer : Colours.palette.m3onSurface - } - } - } - } - } - - onItemSelected: function (item) { - session.ethernet.active = item; - } -} diff --git a/modules/controlcenter/network/EthernetPane.qml b/modules/controlcenter/network/EthernetPane.qml deleted file mode 100644 index d66620f1..00000000 --- a/modules/controlcenter/network/EthernetPane.qml +++ /dev/null @@ -1,50 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "../components" -import QtQuick -import Quickshell.Widgets -import Caelestia.Config -import qs.components -import qs.components.containers - -SplitPaneWithDetails { - id: root - - required property Session session - - anchors.fill: parent - - activeItem: session.ethernet.active - paneIdGenerator: function (item) { - return item ? (item.interface || "") : ""; - } - - leftContent: Component { - EthernetList { - session: root.session - } - } - - rightDetailsComponent: Component { - EthernetDetails { - session: root.session - } - } - - rightSettingsComponent: Component { - StyledFlickable { - flickableDirection: Flickable.VerticalFlick - contentHeight: settingsInner.height - clip: true - - EthernetSettings { - id: settingsInner - - anchors.left: parent.left - anchors.right: parent.right - session: root.session - } - } - } -} diff --git a/modules/controlcenter/network/EthernetSettings.qml b/modules/controlcenter/network/EthernetSettings.qml deleted file mode 100644 index 00ef4452..00000000 --- a/modules/controlcenter/network/EthernetSettings.qml +++ /dev/null @@ -1,75 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "../components" -import QtQuick -import QtQuick.Layouts -import Caelestia.Config -import qs.components -import qs.components.controls -import qs.components.effects -import qs.services - -ColumnLayout { - id: root - - required property Session session - - spacing: Tokens.spacing.medium - - SettingsHeader { - icon: "cable" - title: qsTr("Ethernet settings") - } - - StyledText { - Layout.topMargin: Tokens.spacing.largeIncreased - text: qsTr("Ethernet devices") - font: Tokens.font.body.builders.large.weight(Font.Medium).build() - } - - StyledText { - text: qsTr("Available ethernet devices") - color: Colours.palette.m3outline - } - - StyledRect { - Layout.fillWidth: true - implicitHeight: ethernetInfo.implicitHeight + Tokens.padding.extraLargeIncreased - - radius: Tokens.rounding.large - color: Colours.tPalette.m3surfaceContainer - - ColumnLayout { - id: ethernetInfo - - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - anchors.margins: Tokens.padding.large - - spacing: Tokens.spacing.extraSmall - - StyledText { - text: qsTr("Total devices") - } - - StyledText { - text: qsTr("%1").arg(Nmcli.ethernetDevices.length) - color: Colours.palette.m3outline - font: Tokens.font.body.small - } - - StyledText { - Layout.topMargin: Tokens.spacing.medium - text: qsTr("Connected devices") - } - - StyledText { - text: qsTr("%1").arg(Nmcli.ethernetDevices.filter(d => d.connected).length) - color: Colours.palette.m3outline - font: Tokens.font.body.small - } - } - } -} diff --git a/modules/controlcenter/network/NetworkSettings.qml b/modules/controlcenter/network/NetworkSettings.qml deleted file mode 100644 index c0677d97..00000000 --- a/modules/controlcenter/network/NetworkSettings.qml +++ /dev/null @@ -1,170 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "../components" -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Caelestia.Config -import qs.components -import qs.components.containers -import qs.components.controls -import qs.components.effects -import qs.services - -ColumnLayout { - id: root - - required property Session session - - spacing: Tokens.spacing.medium - - SettingsHeader { - icon: "router" - title: qsTr("Network Settings") - } - - SectionHeader { - Layout.topMargin: Tokens.spacing.largeIncreased - title: qsTr("Ethernet") - description: qsTr("Ethernet device information") - } - - SectionContainer { - contentSpacing: Tokens.spacing.extraSmall - - PropertyRow { - label: qsTr("Total devices") - value: qsTr("%1").arg(Nmcli.ethernetDevices.length) - } - - PropertyRow { - showTopMargin: true - label: qsTr("Connected devices") - value: qsTr("%1").arg(Nmcli.ethernetDevices.filter(d => d.connected).length) - } - } - - SectionHeader { - Layout.topMargin: Tokens.spacing.largeIncreased - title: qsTr("Wireless") - description: qsTr("WiFi network settings") - } - - SectionContainer { - ToggleRow { - label: qsTr("WiFi enabled") - checked: Nmcli.wifiEnabled - toggle.onToggled: { - Nmcli.enableWifi(checked); - } - } - } - - SectionHeader { - Layout.topMargin: Tokens.spacing.largeIncreased - title: qsTr("VPN") - description: qsTr("VPN provider settings") - visible: GlobalConfig.utilities.vpn.enabled || GlobalConfig.utilities.vpn.provider.length > 0 - } - - SectionContainer { - visible: GlobalConfig.utilities.vpn.enabled || GlobalConfig.utilities.vpn.provider.length > 0 - - ToggleRow { - label: qsTr("VPN enabled") - checked: GlobalConfig.utilities.vpn.enabled - toggle.onToggled: { - GlobalConfig.utilities.vpn.enabled = checked; - } - } - - PropertyRow { - showTopMargin: true - label: qsTr("Providers") - value: qsTr("%1").arg(GlobalConfig.utilities.vpn.provider.length) - } - - TextButton { - Layout.fillWidth: true - Layout.topMargin: Tokens.spacing.medium - Layout.minimumHeight: Tokens.font.body.medium.pointSize + Tokens.padding.medium * 2 - text: qsTr("⚙ Manage VPN Providers") - inactiveColour: Colours.palette.m3secondaryContainer - inactiveOnColour: Colours.palette.m3onSecondaryContainer - - onClicked: { - vpnSettingsDialog.open(); - } - } - } - - SectionHeader { - Layout.topMargin: Tokens.spacing.largeIncreased - title: qsTr("Current connection") - description: qsTr("Active network connection information") - } - - SectionContainer { - contentSpacing: Tokens.spacing.extraSmall - - PropertyRow { - label: qsTr("Network") - value: Nmcli.active ? Nmcli.active.ssid : (Nmcli.activeEthernet ? Nmcli.activeEthernet.interface : qsTr("Not connected")) - } - - PropertyRow { - showTopMargin: true - visible: Nmcli.active !== null - label: qsTr("Signal strength") - value: Nmcli.active ? qsTr("%1%").arg(Nmcli.active.strength) : qsTr("N/A") - } - - PropertyRow { - showTopMargin: true - visible: Nmcli.active !== null - label: qsTr("Security") - value: Nmcli.active ? (Nmcli.active.isSecure ? qsTr("Secured") : qsTr("Open")) : qsTr("N/A") - } - - PropertyRow { - showTopMargin: true - visible: Nmcli.active !== null - label: qsTr("Frequency") - value: Nmcli.active ? qsTr("%1 MHz").arg(Nmcli.active.frequency) : qsTr("N/A") - } - } - - Popup { - id: vpnSettingsDialog - - parent: Overlay.overlay - anchors.centerIn: parent - width: Math.min(600, parent.width - Tokens.padding.extraLargeIncreased) - height: Math.min(700, parent.height - Tokens.padding.extraLargeIncreased) - - modal: true - closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside - - background: StyledRect { - color: Colours.palette.m3surface - radius: Tokens.rounding.extraLarge - } - - StyledFlickable { - anchors.fill: parent - anchors.margins: Tokens.padding.large * 1.5 - flickableDirection: Flickable.VerticalFlick - contentHeight: vpnSettingsContent.height - clip: true - - VpnSettings { - id: vpnSettingsContent - - anchors.left: parent.left - anchors.right: parent.right - session: root.session - } - } - } -} diff --git a/modules/controlcenter/network/NetworkingPane.qml b/modules/controlcenter/network/NetworkingPane.qml deleted file mode 100644 index bf2daa1a..00000000 --- a/modules/controlcenter/network/NetworkingPane.qml +++ /dev/null @@ -1,379 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "../components" -import "." -import QtQuick -import QtQuick.Layouts -import Quickshell -import Quickshell.Widgets -import Caelestia.Config -import qs.components -import qs.components.containers -import qs.components.controls -import qs.components.effects -import qs.services -import qs.utils - -Item { - id: root - - required property Session session - - anchors.fill: parent - - SplitPaneLayout { - id: splitLayout - - anchors.fill: parent - - leftContent: Component { - StyledFlickable { - id: leftFlickable - - flickableDirection: Flickable.VerticalFlick - contentHeight: leftContent.height - - StyledScrollBar.vertical: StyledScrollBar { - flickable: leftFlickable - } - - ColumnLayout { - id: leftContent - - anchors.left: parent.left - anchors.right: parent.right - spacing: Tokens.spacing.medium - - RowLayout { - Layout.fillWidth: true - spacing: Tokens.spacing.medium - - StyledText { - text: qsTr("Network") - font: Tokens.font.body.builders.large.weight(Font.Medium).build() - } - - Item { - Layout.fillWidth: true - } - - ToggleButton { - toggled: Nmcli.wifiEnabled - icon: "wifi" - accent: "Tertiary" - iconSize: Tokens.font.body.medium.pointSize - horizontalPadding: Tokens.padding.medium - verticalPadding: Tokens.padding.small - tooltip: qsTr("Toggle WiFi") - - onClicked: { - Nmcli.toggleWifi(null); - } - } - - ToggleButton { - toggled: Nmcli.scanning - icon: "wifi_find" - accent: "Secondary" - iconSize: Tokens.font.body.medium.pointSize - horizontalPadding: Tokens.padding.medium - verticalPadding: Tokens.padding.small - tooltip: qsTr("Scan for networks") - - onClicked: { - Nmcli.rescanWifi(); - } - } - - ToggleButton { - toggled: !root.session.ethernet.active && !root.session.network.active - icon: "settings" - accent: "Primary" - iconSize: Tokens.font.body.medium.pointSize - horizontalPadding: Tokens.padding.medium - verticalPadding: Tokens.padding.small - tooltip: qsTr("Network settings") - - onClicked: { - if (root.session.ethernet.active || root.session.network.active) { - root.session.ethernet.active = null; - root.session.network.active = null; - } else { - if (Nmcli.ethernetDevices.length > 0) { - root.session.ethernet.active = Nmcli.ethernetDevices[0]; - } else if (Nmcli.networks.length > 0) { - root.session.network.active = Nmcli.networks[0]; - } - } - } - } - } - - CollapsibleSection { - id: vpnListSection - - Layout.fillWidth: true - title: qsTr("VPN") - expanded: true - - Loader { - Layout.fillWidth: true - asynchronous: true - sourceComponent: Component { - VpnList { - session: root.session - showHeader: false - } - } - } - } - - CollapsibleSection { - id: ethernetListSection - - Layout.fillWidth: true - title: qsTr("Ethernet") - expanded: true - - Loader { - Layout.fillWidth: true - asynchronous: true - sourceComponent: Component { - EthernetList { - session: root.session - showHeader: false - } - } - } - } - - CollapsibleSection { - id: wirelessListSection - - Layout.fillWidth: true - title: qsTr("Wireless") - expanded: true - - Loader { - Layout.fillWidth: true - asynchronous: true - sourceComponent: Component { - WirelessList { - session: root.session - showHeader: false - } - } - } - } - } - } - } - - rightContent: Component { - Item { - id: rightPaneItem - - property var vpnPane: root.session && root.session.vpn ? root.session.vpn.active : null - property var ethernetPane: root.session && root.session.ethernet ? root.session.ethernet.active : null - property var wirelessPane: root.session && root.session.network ? root.session.network.active : null - property var pane: vpnPane || ethernetPane || wirelessPane - property string paneId: vpnPane ? ("vpn:" + (vpnPane.name || "")) : (ethernetPane ? ("eth:" + (ethernetPane.interface || "")) : (wirelessPane ? ("wifi:" + (wirelessPane.ssid || wirelessPane.bssid || "")) : "settings")) - property Component targetComponent: settingsComponent - property Component nextComponent: settingsComponent - - function getComponentForPane() { - if (vpnPane) - return vpnDetailsComponent; - if (ethernetPane) - return ethernetDetailsComponent; - if (wirelessPane) - return wirelessDetailsComponent; - return settingsComponent; - } - - Component.onCompleted: { - targetComponent = getComponentForPane(); - nextComponent = targetComponent; - } - - Connections { - function onActiveChanged() { - // Clear others when VPN is selected - if (root.session && root.session.vpn && root.session.vpn.active) { - if (root.session.ethernet && root.session.ethernet.active) - root.session.ethernet.active = null; - if (root.session.network && root.session.network.active) - root.session.network.active = null; - } - rightPaneItem.nextComponent = rightPaneItem.getComponentForPane(); - } - - target: root.session && root.session.vpn ? root.session.vpn : null - enabled: target !== null - } - - Connections { - function onActiveChanged() { - // Clear others when ethernet is selected - if (root.session && root.session.ethernet && root.session.ethernet.active) { - if (root.session.vpn && root.session.vpn.active) - root.session.vpn.active = null; - if (root.session.network && root.session.network.active) - root.session.network.active = null; - } - rightPaneItem.nextComponent = rightPaneItem.getComponentForPane(); - } - - target: root.session && root.session.ethernet ? root.session.ethernet : null - enabled: target !== null - } - - Connections { - function onActiveChanged() { - // Clear others when wireless is selected - if (root.session && root.session.network && root.session.network.active) { - if (root.session.vpn && root.session.vpn.active) - root.session.vpn.active = null; - if (root.session.ethernet && root.session.ethernet.active) - root.session.ethernet.active = null; - } - rightPaneItem.nextComponent = rightPaneItem.getComponentForPane(); - } - - target: root.session && root.session.network ? root.session.network : null - enabled: target !== null - } - - Loader { - id: rightLoader - - anchors.fill: parent - - opacity: 1 - scale: 1 - transformOrigin: Item.Center - clip: false - - asynchronous: true - sourceComponent: rightPaneItem.targetComponent - } - - Behavior on paneId { - PaneTransition { - target: rightLoader - propertyActions: [ - PropertyAction { - target: rightPaneItem - property: "targetComponent" - value: rightPaneItem.nextComponent - } - ] - } - } - } - } - } - - Component { - id: settingsComponent - - StyledFlickable { - id: settingsFlickable - - flickableDirection: Flickable.VerticalFlick - contentHeight: settingsInner.height - - StyledScrollBar.vertical: StyledScrollBar { - flickable: settingsFlickable - } - - NetworkSettings { - id: settingsInner - - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - session: root.session - } - } - } - - Component { - id: ethernetDetailsComponent - - StyledFlickable { - id: ethernetFlickable - - flickableDirection: Flickable.VerticalFlick - contentHeight: ethernetDetailsInner.height - - StyledScrollBar.vertical: StyledScrollBar { - flickable: ethernetFlickable - } - - EthernetDetails { - id: ethernetDetailsInner - - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - session: root.session - } - } - } - - Component { - id: wirelessDetailsComponent - - StyledFlickable { - id: wirelessFlickable - - flickableDirection: Flickable.VerticalFlick - contentHeight: wirelessDetailsInner.height - - StyledScrollBar.vertical: StyledScrollBar { - flickable: wirelessFlickable - } - - WirelessDetails { - id: wirelessDetailsInner - - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - session: root.session - } - } - } - - Component { - id: vpnDetailsComponent - - StyledFlickable { - id: vpnFlickable - - flickableDirection: Flickable.VerticalFlick - contentHeight: vpnDetailsInner.height - - StyledScrollBar.vertical: StyledScrollBar { - flickable: vpnFlickable - } - - VpnDetails { - id: vpnDetailsInner - - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - session: root.session - } - } - } - - WirelessPasswordDialog { - anchors.fill: parent - session: root.session - z: 1000 - } -} diff --git a/modules/controlcenter/network/VpnDetails.qml b/modules/controlcenter/network/VpnDetails.qml deleted file mode 100644 index 983cc1a1..00000000 --- a/modules/controlcenter/network/VpnDetails.qml +++ /dev/null @@ -1,542 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "../components" -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Caelestia.Config -import qs.components -import qs.components.containers -import qs.components.controls -import qs.components.effects -import qs.services -import qs.utils - -DeviceDetails { - id: root - - required property Session session - readonly property var vpnProvider: root.session.vpn.active - readonly property bool providerEnabled: { - if (!vpnProvider || vpnProvider.index === undefined) - return false; - const provider = GlobalConfig.utilities.vpn.provider[vpnProvider.index]; - return provider && typeof provider === "object" && provider.enabled === true; - } - - device: vpnProvider - - headerComponent: Component { - ConnectionHeader { - icon: "vpn_key" - title: root.vpnProvider?.displayName ?? qsTr("Unknown") - } - } - - sections: [ - Component { - ColumnLayout { - spacing: Tokens.spacing.medium - - SectionHeader { - title: qsTr("Connection status") - description: qsTr("VPN connection settings") - } - - SectionContainer { - ToggleRow { - label: qsTr("Enable this provider") - checked: root.providerEnabled - toggle.onToggled: { - if (!root.vpnProvider) - return; - const providers = []; - const index = root.vpnProvider.index; - - // Copy providers and update enabled state - for (let i = 0; i < GlobalConfig.utilities.vpn.provider.length; i++) { - const p = GlobalConfig.utilities.vpn.provider[i]; - if (typeof p === "object") { - const newProvider = { - name: p.name, - displayName: p.displayName, - interface: p.interface - }; - - if (checked) { - // Enable this one, disable others - newProvider.enabled = (i === index); - } else { - // Just disable this one - newProvider.enabled = (i === index) ? false : (p.enabled !== false); - } - - if (p.connectCmd && p.connectCmd.length > 0) { - newProvider.connectCmd = p.connectCmd; - } - if (p.disconnectCmd && p.disconnectCmd.length > 0) { - newProvider.disconnectCmd = p.disconnectCmd; - } - - providers.push(newProvider); - } else { - providers.push(p); - } - } - - GlobalConfig.utilities.vpn.provider = providers; - } - } - - RowLayout { - Layout.fillWidth: true - Layout.topMargin: Tokens.spacing.medium - spacing: Tokens.spacing.medium - - TextButton { - Layout.fillWidth: true - Layout.minimumHeight: Tokens.font.body.medium.pointSize + Tokens.padding.medium * 2 - visible: root.providerEnabled - enabled: !VPN.connecting - inactiveColour: Colours.palette.m3primaryContainer - inactiveOnColour: Colours.palette.m3onPrimaryContainer - text: VPN.connected ? qsTr("Disconnect") : qsTr("Connect") - - onClicked: { - VPN.toggle(); - } - } - - TextButton { - Layout.fillWidth: true - text: qsTr("Edit Provider") - inactiveColour: Colours.palette.m3secondaryContainer - inactiveOnColour: Colours.palette.m3onSecondaryContainer - - onClicked: { - const provider = GlobalConfig.utilities.vpn.provider[root.vpnProvider.index]; - editVpnDialog.editIndex = root.vpnProvider.index; - editVpnDialog.providerName = root.vpnProvider.name; - editVpnDialog.displayName = root.vpnProvider.displayName; - editVpnDialog.interfaceName = root.vpnProvider.interface; - editVpnDialog.connectCmd = (provider && provider.connectCmd) ? provider.connectCmd.join(" ") : ""; - editVpnDialog.disconnectCmd = (provider && provider.disconnectCmd) ? provider.disconnectCmd.join(" ") : ""; - editVpnDialog.open(); - } - } - - TextButton { - Layout.fillWidth: true - text: qsTr("Delete Provider") - inactiveColour: Colours.palette.m3errorContainer - inactiveOnColour: Colours.palette.m3onErrorContainer - - onClicked: { - const providers = []; - for (let i = 0; i < GlobalConfig.utilities.vpn.provider.length; i++) { - if (i !== root.vpnProvider.index) { - providers.push(GlobalConfig.utilities.vpn.provider[i]); - } - } - GlobalConfig.utilities.vpn.provider = providers; - root.session.vpn.active = null; - } - } - } - - TextButton { - Layout.fillWidth: true - Layout.topMargin: Tokens.spacing.medium - visible: root.providerEnabled && VPN.status.state === "needs-auth" && VPN.status.authUrl !== "" - text: qsTr("Open Login Page") - inactiveColour: Colours.palette.m3tertiaryContainer - inactiveOnColour: Colours.palette.m3onTertiaryContainer - - onClicked: { - Qt.openUrlExternally(VPN.status.authUrl); - } - } - - StyledText { - Layout.fillWidth: true - Layout.topMargin: Tokens.spacing.medium - visible: root.providerEnabled && VPN.status.state === "needs-auth" && VPN.status.authUrl === "" - text: qsTr("Click 'Connect' to generate authentication URL") - font: Tokens.font.body.small - color: Colours.palette.m3onSurfaceVariant - horizontalAlignment: Text.AlignHCenter - wrapMode: Text.WordWrap - } - } - } - }, - Component { - ColumnLayout { - spacing: Tokens.spacing.medium - - SectionHeader { - title: qsTr("Provider details") - description: qsTr("VPN provider information") - } - - SectionContainer { - contentSpacing: Tokens.spacing.extraSmall - - PropertyRow { - label: qsTr("Provider") - value: root.vpnProvider?.name ?? qsTr("Unknown") - } - - PropertyRow { - showTopMargin: true - label: qsTr("Display name") - value: root.vpnProvider?.displayName ?? qsTr("Unknown") - } - - PropertyRow { - showTopMargin: true - label: qsTr("Interface") - value: root.vpnProvider?.interface || qsTr("N/A") - } - - PropertyRow { - showTopMargin: true - label: qsTr("Status") - value: { - if (!root.providerEnabled) - return qsTr("Disabled"); - if (VPN.connecting) - return qsTr("Connecting..."); - - switch (VPN.status.state) { - case "connected": - return qsTr("Connected"); - case "disconnected": - return qsTr("Disconnected"); - case "connecting": - return qsTr("Connecting..."); - case "needs-auth": - return qsTr("Authentication required"); - case "error": - return qsTr("Error"); - default: - return qsTr("Unknown"); - } - } - } - - PropertyRow { - visible: VPN.status.reason !== "" - showTopMargin: true - label: qsTr("Details") - value: VPN.status.reason - } - - PropertyRow { - showTopMargin: true - label: qsTr("Enabled") - value: root.providerEnabled ? qsTr("Yes") : qsTr("No") - } - } - } - } - ] - - // Edit VPN Dialog - Popup { - id: editVpnDialog - - property int editIndex: -1 - property string providerName: "" - property string displayName: "" - property string interfaceName: "" - property string connectCmd: "" - property string disconnectCmd: "" - - function closeWithAnimation(): void { - close(); - } - - parent: Overlay.overlay - anchors.centerIn: parent - width: Math.min(400, parent.width - Tokens.padding.extraLargeIncreased) - padding: Tokens.padding.large * 1.5 - - modal: true - closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside - - opacity: 0 - scale: 0.7 - - enter: Transition { - Anim { - property: "opacity" - from: 0 - to: 1 - type: Anim.FastSpatial - } - Anim { - property: "scale" - from: 0.7 - to: 1 - type: Anim.FastSpatial - } - } - - exit: Transition { - Anim { - property: "opacity" - from: 1 - to: 0 - type: Anim.FastSpatial - } - Anim { - property: "scale" - from: 1 - to: 0.7 - type: Anim.FastSpatial - } - } - - Overlay.modal: Rectangle { - color: Qt.rgba(0, 0, 0, 0.4 * editVpnDialog.opacity) - } - - background: StyledRect { - color: Colours.palette.m3surfaceContainerHigh - radius: Tokens.rounding.extraLarge - - Elevation { - anchors.fill: parent - radius: parent.radius - level: 3 - z: -1 - } - } - - contentItem: ColumnLayout { - spacing: Tokens.spacing.medium - - StyledText { - text: qsTr("Edit VPN Provider") - font: Tokens.font.body.builders.large.weight(Font.Medium).build() - } - - ColumnLayout { - Layout.fillWidth: true - spacing: Tokens.spacing.medium / 2 - - StyledText { - text: qsTr("Display Name") - font: Tokens.font.body.small - color: Colours.palette.m3onSurfaceVariant - } - - StyledRect { - Layout.fillWidth: true - implicitHeight: 40 - color: displayNameField.activeFocus ? Colours.layer(Colours.palette.m3surfaceContainer, 3) : Colours.layer(Colours.palette.m3surfaceContainer, 2) - radius: Tokens.rounding.medium - border.width: 1 - border.color: displayNameField.activeFocus ? Colours.palette.m3primary : Qt.alpha(Colours.palette.m3outline, 0.3) - - Behavior on color { - CAnim {} - } - Behavior on border.color { - CAnim {} - } - - StyledTextField { - id: displayNameField - - anchors.centerIn: parent - width: parent.width - Tokens.padding.medium - horizontalAlignment: TextInput.AlignLeft - text: editVpnDialog.displayName - onTextChanged: editVpnDialog.displayName = text - } - } - } - - ColumnLayout { - Layout.fillWidth: true - spacing: Tokens.spacing.medium / 2 - - StyledText { - text: qsTr("Interface (e.g., wg0, torguard)") - font: Tokens.font.body.small - color: Colours.palette.m3onSurfaceVariant - } - - StyledRect { - Layout.fillWidth: true - implicitHeight: 40 - color: interfaceNameField.activeFocus ? Colours.layer(Colours.palette.m3surfaceContainer, 3) : Colours.layer(Colours.palette.m3surfaceContainer, 2) - radius: Tokens.rounding.medium - border.width: 1 - border.color: interfaceNameField.activeFocus ? Colours.palette.m3primary : Qt.alpha(Colours.palette.m3outline, 0.3) - - Behavior on color { - CAnim {} - } - Behavior on border.color { - CAnim {} - } - - StyledTextField { - id: interfaceNameField - - anchors.centerIn: parent - width: parent.width - Tokens.padding.medium - horizontalAlignment: TextInput.AlignLeft - text: editVpnDialog.interfaceName - onTextChanged: editVpnDialog.interfaceName = text - } - } - } - - ColumnLayout { - Layout.fillWidth: true - spacing: Tokens.spacing.medium / 2 - visible: editVpnDialog.connectCmd.length > 0 - - StyledText { - text: qsTr("Connect Command") - font: Tokens.font.body.small - color: Colours.palette.m3onSurfaceVariant - } - - StyledRect { - Layout.fillWidth: true - implicitHeight: 40 - color: connectCmdFieldEdit.activeFocus ? Colours.layer(Colours.palette.m3surfaceContainer, 3) : Colours.layer(Colours.palette.m3surfaceContainer, 2) - radius: Tokens.rounding.medium - border.width: 1 - border.color: connectCmdFieldEdit.activeFocus ? Colours.palette.m3primary : Qt.alpha(Colours.palette.m3outline, 0.3) - - Behavior on color { - CAnim {} - } - Behavior on border.color { - CAnim {} - } - - StyledTextField { - id: connectCmdFieldEdit - - anchors.centerIn: parent - width: parent.width - Tokens.padding.medium - horizontalAlignment: TextInput.AlignLeft - text: editVpnDialog.connectCmd - onTextChanged: editVpnDialog.connectCmd = text - } - } - } - - ColumnLayout { - Layout.fillWidth: true - spacing: Tokens.spacing.medium / 2 - visible: editVpnDialog.disconnectCmd.length > 0 - - StyledText { - text: qsTr("Disconnect Command") - font: Tokens.font.body.small - color: Colours.palette.m3onSurfaceVariant - } - - StyledRect { - Layout.fillWidth: true - implicitHeight: 40 - color: disconnectCmdFieldEdit.activeFocus ? Colours.layer(Colours.palette.m3surfaceContainer, 3) : Colours.layer(Colours.palette.m3surfaceContainer, 2) - radius: Tokens.rounding.medium - border.width: 1 - border.color: disconnectCmdFieldEdit.activeFocus ? Colours.palette.m3primary : Qt.alpha(Colours.palette.m3outline, 0.3) - - Behavior on color { - CAnim {} - } - Behavior on border.color { - CAnim {} - } - - StyledTextField { - id: disconnectCmdFieldEdit - - anchors.centerIn: parent - width: parent.width - Tokens.padding.medium - horizontalAlignment: TextInput.AlignLeft - text: editVpnDialog.disconnectCmd - onTextChanged: editVpnDialog.disconnectCmd = text - } - } - } - - RowLayout { - Layout.topMargin: Tokens.spacing.medium - Layout.fillWidth: true - spacing: Tokens.spacing.medium - - TextButton { - Layout.fillWidth: true - text: qsTr("Cancel") - inactiveColour: Colours.tPalette.m3surfaceContainerHigh - inactiveOnColour: Colours.palette.m3onSurface - onClicked: editVpnDialog.closeWithAnimation() - } - - TextButton { - Layout.fillWidth: true - text: qsTr("Save") - enabled: editVpnDialog.interfaceName.length > 0 - inactiveColour: Colours.palette.m3primaryContainer - inactiveOnColour: Colours.palette.m3onPrimaryContainer - - onClicked: { - const providers = []; - const oldProvider = GlobalConfig.utilities.vpn.provider[editVpnDialog.editIndex]; - const wasEnabled = typeof oldProvider === "object" ? (oldProvider.enabled !== false) : true; - - for (let i = 0; i < GlobalConfig.utilities.vpn.provider.length; i++) { - if (i === editVpnDialog.editIndex) { - const hasCommands = editVpnDialog.connectCmd.length > 0 && editVpnDialog.disconnectCmd.length > 0; - const newProvider = { - displayName: editVpnDialog.displayName || editVpnDialog.interfaceName, - enabled: wasEnabled, - interface: editVpnDialog.interfaceName, - name: editVpnDialog.providerName - }; - - if (hasCommands) { - newProvider.connectCmd = editVpnDialog.connectCmd.split(" ").filter(s => s.length > 0); - newProvider.disconnectCmd = editVpnDialog.disconnectCmd.split(" ").filter(s => s.length > 0); - } - - providers.push(newProvider); - } else { - const p = GlobalConfig.utilities.vpn.provider[i]; - const reconstructed = { - displayName: p.displayName, - enabled: p.enabled, - interface: p.interface, - name: p.name - }; - if (p.connectCmd && p.connectCmd.length > 0) { - reconstructed.connectCmd = p.connectCmd; - } - if (p.disconnectCmd && p.disconnectCmd.length > 0) { - reconstructed.disconnectCmd = p.disconnectCmd; - } - providers.push(reconstructed); - } - } - - GlobalConfig.utilities.vpn.provider = providers; - editVpnDialog.closeWithAnimation(); - } - } - } - } - } -} diff --git a/modules/controlcenter/network/VpnList.qml b/modules/controlcenter/network/VpnList.qml deleted file mode 100644 index b1b7b01b..00000000 --- a/modules/controlcenter/network/VpnList.qml +++ /dev/null @@ -1,827 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Quickshell -import Caelestia.Config -import qs.components -import qs.components.controls -import qs.components.effects -import qs.services - -ColumnLayout { - id: root - - required property Session session - property bool showHeader: true - property int pendingSwitchIndex: -1 - - spacing: Tokens.spacing.medium - - Connections { - function onConnectedChanged() { - if (!VPN.connected && root.pendingSwitchIndex >= 0) { - const targetIndex = root.pendingSwitchIndex; - root.pendingSwitchIndex = -1; - - const providers = []; - for (let i = 0; i < GlobalConfig.utilities.vpn.provider.length; i++) { - const p = GlobalConfig.utilities.vpn.provider[i]; - if (typeof p === "object") { - const newProvider = { - name: p.name, - displayName: p.displayName, - interface: p.interface, - enabled: (i === targetIndex) - }; - if (p.connectCmd && p.connectCmd.length > 0) { - newProvider.connectCmd = p.connectCmd; - } - if (p.disconnectCmd && p.disconnectCmd.length > 0) { - newProvider.disconnectCmd = p.disconnectCmd; - } - providers.push(newProvider); - } else { - providers.push(p); - } - } - GlobalConfig.utilities.vpn.provider = providers; - - Qt.callLater(function () { - VPN.toggle(); - }); - } - } - - target: VPN - } - - TextButton { - Layout.fillWidth: true - text: qsTr("+ Add VPN Provider") - inactiveColour: Colours.palette.m3primaryContainer - inactiveOnColour: Colours.palette.m3onPrimaryContainer - - onClicked: { - vpnDialog.showProviderSelection(); - } - } - - ListView { - id: listView - - Layout.fillWidth: true - Layout.preferredHeight: contentHeight - - interactive: false - spacing: Tokens.spacing.medium - - model: ScriptModel { - values: GlobalConfig.utilities.vpn.provider.map((provider, index) => { - const isObject = typeof provider === "object"; - const name = isObject ? (provider.name || "custom") : String(provider); - const displayName = isObject ? (provider.displayName || name) : name; - const iface = isObject ? (provider.interface || "") : ""; - const enabled = isObject ? (provider.enabled === true) : false; - - return { - index: index, - name: name, - displayName: displayName, - interface: iface, - provider: provider, - enabled: enabled - }; - }) - } - - delegate: Component { - StyledRect { - required property var modelData - required property int index - - width: ListView.view ? ListView.view.width : undefined - implicitHeight: rowLayout.implicitHeight + Tokens.padding.medium * 2 - - color: Qt.alpha(Colours.tPalette.m3surfaceContainer, (root.session && root.session.vpn && root.session.vpn.active === modelData) ? Colours.tPalette.m3surfaceContainer.a : 0) - radius: Tokens.rounding.large - - StateLayer { - onClicked: { - if (root.session && root.session.vpn) { - root.session.vpn.active = modelData; - } - } - } - - RowLayout { - id: rowLayout - - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - anchors.margins: Tokens.padding.medium - - spacing: Tokens.spacing.medium - - StyledRect { - implicitWidth: implicitHeight - implicitHeight: icon.implicitHeight + Tokens.padding.medium * 2 - - radius: Tokens.rounding.large - color: modelData.enabled && VPN.connected ? Colours.palette.m3primaryContainer : Colours.tPalette.m3surfaceContainerHigh - - MaterialIcon { - id: icon - - anchors.centerIn: parent - text: modelData.enabled && VPN.connected ? "vpn_key" : "vpn_key_off" - fontStyle: Tokens.font.icon.large - fill: modelData.enabled && VPN.connected ? 1 : 0 - color: modelData.enabled && VPN.connected ? Colours.palette.m3onPrimaryContainer : Colours.palette.m3onSurface - } - } - - ColumnLayout { - Layout.fillWidth: true - - spacing: 0 - - StyledText { - Layout.fillWidth: true - elide: Text.ElideRight - maximumLineCount: 1 - - text: modelData.displayName || qsTr("Unknown") - } - - RowLayout { - Layout.fillWidth: true - spacing: Tokens.spacing.medium - - StyledText { - Layout.fillWidth: true - text: { - if (!modelData.enabled) - return qsTr("Disabled"); - - if (VPN.connecting) - return qsTr("Connecting..."); - - switch (VPN.status.state) { - case "connected": - return qsTr("Connected"); - case "disconnected": - return qsTr("Enabled"); - case "connecting": - return qsTr("Connecting..."); - case "needs-auth": - return qsTr("Auth required"); - case "error": - return qsTr("Error"); - default: - return qsTr("Enabled"); - } - } - color: { - if (!modelData.enabled) - return Colours.palette.m3outline; - if (VPN.status.state === "connected") - return Colours.palette.m3primary; - if (VPN.status.state === "error") - return Colours.palette.m3error; - if (VPN.status.state === "needs-auth") - return Colours.palette.m3tertiary; - return Colours.palette.m3onSurface; - } - font: Tokens.font.body.builders.small.weight(modelData.enabled && VPN.connected ? Font.Medium : Font.Normal).build() - elide: Text.ElideRight - } - } - } - - StyledRect { - implicitWidth: implicitHeight - implicitHeight: connectIcon.implicitHeight + Tokens.padding.large - - radius: Tokens.rounding.full - color: Qt.alpha(Colours.palette.m3primaryContainer, VPN.connected && modelData.enabled ? 1 : 0) - - StateLayer { - onClicked: { - const clickedIndex = modelData.index; - - if (modelData.enabled) { - VPN.toggle(); - } else { - if (VPN.connected) { - root.pendingSwitchIndex = clickedIndex; - VPN.toggle(); - } else { - const providers = []; - for (let i = 0; i < GlobalConfig.utilities.vpn.provider.length; i++) { - const p = GlobalConfig.utilities.vpn.provider[i]; - if (typeof p === "object") { - const newProvider = { - name: p.name, - displayName: p.displayName, - interface: p.interface, - enabled: (i === clickedIndex) - }; - if (p.connectCmd && p.connectCmd.length > 0) { - newProvider.connectCmd = p.connectCmd; - } - if (p.disconnectCmd && p.disconnectCmd.length > 0) { - newProvider.disconnectCmd = p.disconnectCmd; - } - providers.push(newProvider); - } else { - providers.push(p); - } - } - GlobalConfig.utilities.vpn.provider = providers; - - Qt.callLater(function () { - VPN.toggle(); - }); - } - } - } - - enabled: !VPN.connecting - } - - MaterialIcon { - id: connectIcon - - anchors.centerIn: parent - text: VPN.connected && modelData.enabled ? "link_off" : "link" - color: VPN.connected && modelData.enabled ? Colours.palette.m3onPrimaryContainer : Colours.palette.m3onSurface - } - } - - StyledRect { - implicitWidth: implicitHeight - implicitHeight: deleteIcon.implicitHeight + Tokens.padding.large - - radius: Tokens.rounding.full - color: "transparent" - - StateLayer { - onClicked: { - const providers = []; - for (let i = 0; i < GlobalConfig.utilities.vpn.provider.length; i++) { - if (i !== modelData.index) { - const p = GlobalConfig.utilities.vpn.provider[i]; - const reconstructed = { - name: p.name, - displayName: p.displayName, - interface: p.interface, - enabled: p.enabled - }; - if (p.connectCmd && p.connectCmd.length > 0) { - reconstructed.connectCmd = p.connectCmd; - } - if (p.disconnectCmd && p.disconnectCmd.length > 0) { - reconstructed.disconnectCmd = p.disconnectCmd; - } - providers.push(reconstructed); - } - } - GlobalConfig.utilities.vpn.provider = providers; - } - } - - MaterialIcon { - id: deleteIcon - - anchors.centerIn: parent - text: "delete" - color: Colours.palette.m3onSurface - } - } - } - } - } - } - - Popup { - id: vpnDialog - - property string currentState: "selection" - property int editIndex: -1 - property string providerName: "" - property string displayName: "" - property string interfaceName: "" - property string connectCmd: "" - property string disconnectCmd: "" - - function showProviderSelection(): void { - currentState = "selection"; - open(); - } - - function closeWithAnimation(): void { - close(); - } - - function showAddForm(providerType: string, defaultDisplayName: string): void { - editIndex = -1; - providerName = providerType; - displayName = defaultDisplayName; - interfaceName = ""; - connectCmd = ""; - disconnectCmd = ""; - - if (currentState === "selection") { - transitionToForm.start(); - } else { - currentState = "form"; - isClosing = false; - open(); - } - } - - function showEditForm(index: int): void { - const provider = GlobalConfig.utilities.vpn.provider[index]; - const isObject = typeof provider === "object"; - - editIndex = index; - providerName = isObject ? (provider.name || "custom") : String(provider); - displayName = isObject ? (provider.displayName || providerName) : providerName; - interfaceName = isObject ? (provider.interface || "") : ""; - connectCmd = isObject && provider.connectCmd ? provider.connectCmd.join(" ") : ""; - disconnectCmd = isObject && provider.disconnectCmd ? provider.disconnectCmd.join(" ") : ""; - - currentState = "form"; - open(); - } - - parent: Overlay.overlay - x: Math.round((parent.width - width) / 2) - y: Math.round((parent.height - height) / 2) - implicitWidth: Math.min(400, parent.width - Tokens.padding.extraLargeIncreased) - padding: Tokens.padding.large * 1.5 - - modal: true - closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside - - opacity: 0 - scale: 0.7 - - enter: Transition { - ParallelAnimation { - Anim { - property: "opacity" - from: 0 - to: 1 - type: Anim.Emphasized - } - Anim { - property: "scale" - from: 0.7 - to: 1 - type: Anim.Emphasized - } - } - } - - exit: Transition { - ParallelAnimation { - Anim { - property: "opacity" - from: 1 - to: 0 - type: Anim.EmphasizedSmall - } - Anim { - property: "scale" - from: 1 - to: 0.7 - type: Anim.EmphasizedSmall - } - } - } - - Overlay.modal: Rectangle { - color: Qt.rgba(0, 0, 0, 0.4 * vpnDialog.opacity) - } - - onClosed: { - currentState = "selection"; - } - - background: StyledRect { - color: Colours.palette.m3surfaceContainerHigh - radius: Tokens.rounding.extraLarge - - Elevation { - anchors.fill: parent - radius: parent.radius - level: 3 - z: -1 - } - - Behavior on implicitHeight { - Anim { - type: Anim.Emphasized - } - } - } - - contentItem: Item { - implicitHeight: vpnDialog.currentState === "selection" ? selectionContent.implicitHeight : formContent.implicitHeight - - Behavior on implicitHeight { - Anim { - type: Anim.Emphasized - } - } - - ColumnLayout { - id: selectionContent - - anchors.fill: parent - spacing: Tokens.spacing.medium - visible: vpnDialog.currentState === "selection" - opacity: vpnDialog.currentState === "selection" ? 1 : 0 - - Behavior on opacity { - Anim { - type: Anim.EmphasizedSmall - } - } - - StyledText { - text: qsTr("Add VPN Provider") - font: Tokens.font.body.builders.large.weight(Font.Medium).build() - } - - StyledText { - Layout.fillWidth: true - text: qsTr("Choose a provider to add") - wrapMode: Text.WordWrap - color: Colours.palette.m3outline - font: Tokens.font.body.small - } - - TextButton { - Layout.topMargin: Tokens.spacing.medium - Layout.fillWidth: true - text: qsTr("NetBird") - inactiveColour: Colours.tPalette.m3surfaceContainerHigh - inactiveOnColour: Colours.palette.m3onSurface - onClicked: { - const providers = []; - for (let i = 0; i < GlobalConfig.utilities.vpn.provider.length; i++) { - providers.push(GlobalConfig.utilities.vpn.provider[i]); - } - providers.push({ - name: "netbird", - displayName: "NetBird", - interface: "wt0" - }); - GlobalConfig.utilities.vpn.provider = providers; - vpnDialog.closeWithAnimation(); - } - } - - TextButton { - Layout.fillWidth: true - text: qsTr("Tailscale") - inactiveColour: Colours.tPalette.m3surfaceContainerHigh - inactiveOnColour: Colours.palette.m3onSurface - onClicked: { - const providers = []; - for (let i = 0; i < GlobalConfig.utilities.vpn.provider.length; i++) { - providers.push(GlobalConfig.utilities.vpn.provider[i]); - } - providers.push({ - name: "tailscale", - displayName: "Tailscale", - interface: "tailscale0" - }); - GlobalConfig.utilities.vpn.provider = providers; - vpnDialog.closeWithAnimation(); - } - } - - TextButton { - Layout.fillWidth: true - text: qsTr("Cloudflare WARP") - inactiveColour: Colours.tPalette.m3surfaceContainerHigh - inactiveOnColour: Colours.palette.m3onSurface - onClicked: { - const providers = []; - for (let i = 0; i < GlobalConfig.utilities.vpn.provider.length; i++) { - providers.push(GlobalConfig.utilities.vpn.provider[i]); - } - providers.push({ - name: "warp", - displayName: "Cloudflare WARP", - interface: "CloudflareWARP" - }); - GlobalConfig.utilities.vpn.provider = providers; - vpnDialog.closeWithAnimation(); - } - } - - TextButton { - Layout.fillWidth: true - text: qsTr("WireGuard") - inactiveColour: Colours.tPalette.m3surfaceContainerHigh - inactiveOnColour: Colours.palette.m3onSurface - onClicked: { - vpnDialog.showAddForm("wireguard", "WireGuard"); - } - } - - TextButton { - Layout.fillWidth: true - text: qsTr("Custom") - inactiveColour: Colours.tPalette.m3surfaceContainerHigh - inactiveOnColour: Colours.palette.m3onSurface - onClicked: { - vpnDialog.showAddForm("custom", "Custom VPN"); - } - } - - TextButton { - Layout.topMargin: Tokens.spacing.medium - Layout.fillWidth: true - text: qsTr("Cancel") - inactiveColour: Colours.palette.m3secondaryContainer - inactiveOnColour: Colours.palette.m3onSecondaryContainer - onClicked: vpnDialog.closeWithAnimation() - } - } - - ColumnLayout { - id: formContent - - anchors.fill: parent - spacing: Tokens.spacing.medium - visible: vpnDialog.currentState === "form" - opacity: vpnDialog.currentState === "form" ? 1 : 0 - - Behavior on opacity { - Anim { - type: Anim.EmphasizedSmall - } - } - - StyledText { - text: vpnDialog.editIndex >= 0 ? qsTr("Edit VPN Provider") : qsTr("Add %1 VPN").arg(vpnDialog.displayName) - font: Tokens.font.body.builders.large.weight(Font.Medium).build() - } - - ColumnLayout { - Layout.fillWidth: true - spacing: Tokens.spacing.medium / 2 - - StyledText { - text: qsTr("Display Name") - font: Tokens.font.body.small - color: Colours.palette.m3onSurfaceVariant - } - - StyledRect { - Layout.fillWidth: true - implicitHeight: 40 - color: displayNameField.activeFocus ? Colours.layer(Colours.palette.m3surfaceContainer, 3) : Colours.layer(Colours.palette.m3surfaceContainer, 2) - radius: Tokens.rounding.medium - border.width: 1 - border.color: displayNameField.activeFocus ? Colours.palette.m3primary : Qt.alpha(Colours.palette.m3outline, 0.3) - - Behavior on color { - CAnim {} - } - Behavior on border.color { - CAnim {} - } - - StyledTextField { - id: displayNameField - - anchors.centerIn: parent - width: parent.width - Tokens.padding.medium - horizontalAlignment: TextInput.AlignLeft - text: vpnDialog.displayName - onTextChanged: vpnDialog.displayName = text - } - } - } - - ColumnLayout { - Layout.fillWidth: true - spacing: Tokens.spacing.medium / 2 - - StyledText { - text: qsTr("Interface (e.g., wg0, torguard)") - font: Tokens.font.body.small - color: Colours.palette.m3onSurfaceVariant - } - - StyledRect { - Layout.fillWidth: true - implicitHeight: 40 - color: interfaceNameField.activeFocus ? Colours.layer(Colours.palette.m3surfaceContainer, 3) : Colours.layer(Colours.palette.m3surfaceContainer, 2) - radius: Tokens.rounding.medium - border.width: 1 - border.color: interfaceNameField.activeFocus ? Colours.palette.m3primary : Qt.alpha(Colours.palette.m3outline, 0.3) - - Behavior on color { - CAnim {} - } - Behavior on border.color { - CAnim {} - } - - StyledTextField { - id: interfaceNameField - - anchors.centerIn: parent - width: parent.width - Tokens.padding.medium - horizontalAlignment: TextInput.AlignLeft - text: vpnDialog.interfaceName - onTextChanged: vpnDialog.interfaceName = text - } - } - } - - ColumnLayout { - Layout.fillWidth: true - spacing: Tokens.spacing.medium / 2 - visible: vpnDialog.editIndex >= 0 ? (vpnDialog.connectCmd.length > 0) : (vpnDialog.providerName === "custom") - - StyledText { - text: qsTr("Connect Command (e.g., wg-quick up wg0)") - font: Tokens.font.body.small - color: Colours.palette.m3onSurfaceVariant - } - - StyledRect { - Layout.fillWidth: true - implicitHeight: 40 - color: connectCmdField.activeFocus ? Colours.layer(Colours.palette.m3surfaceContainer, 3) : Colours.layer(Colours.palette.m3surfaceContainer, 2) - radius: Tokens.rounding.medium - border.width: 1 - border.color: connectCmdField.activeFocus ? Colours.palette.m3primary : Qt.alpha(Colours.palette.m3outline, 0.3) - - Behavior on color { - CAnim {} - } - Behavior on border.color { - CAnim {} - } - - StyledTextField { - id: connectCmdField - - anchors.centerIn: parent - width: parent.width - Tokens.padding.medium - horizontalAlignment: TextInput.AlignLeft - text: vpnDialog.connectCmd - onTextChanged: vpnDialog.connectCmd = text - } - } - } - - ColumnLayout { - Layout.fillWidth: true - spacing: Tokens.spacing.medium / 2 - visible: vpnDialog.editIndex >= 0 ? (vpnDialog.connectCmd.length > 0) : (vpnDialog.providerName === "custom") - - StyledText { - text: qsTr("Disconnect Command (e.g., wg-quick down wg0)") - font: Tokens.font.body.small - color: Colours.palette.m3onSurfaceVariant - } - - StyledRect { - Layout.fillWidth: true - implicitHeight: 40 - color: disconnectCmdField.activeFocus ? Colours.layer(Colours.palette.m3surfaceContainer, 3) : Colours.layer(Colours.palette.m3surfaceContainer, 2) - radius: Tokens.rounding.medium - border.width: 1 - border.color: disconnectCmdField.activeFocus ? Colours.palette.m3primary : Qt.alpha(Colours.palette.m3outline, 0.3) - - Behavior on color { - CAnim {} - } - Behavior on border.color { - CAnim {} - } - - StyledTextField { - id: disconnectCmdField - - anchors.centerIn: parent - width: parent.width - Tokens.padding.medium - horizontalAlignment: TextInput.AlignLeft - text: vpnDialog.disconnectCmd - onTextChanged: vpnDialog.disconnectCmd = text - } - } - } - - RowLayout { - Layout.topMargin: Tokens.spacing.medium - Layout.fillWidth: true - spacing: Tokens.spacing.medium - - TextButton { - Layout.fillWidth: true - text: qsTr("Cancel") - inactiveColour: Colours.tPalette.m3surfaceContainerHigh - inactiveOnColour: Colours.palette.m3onSurface - onClicked: vpnDialog.closeWithAnimation() - } - - TextButton { - Layout.fillWidth: true - text: qsTr("Save") - enabled: { - const hasCommands = vpnDialog.connectCmd.length > 0 || vpnDialog.disconnectCmd.length > 0; - if (hasCommands) { - return vpnDialog.interfaceName.length > 0 && vpnDialog.connectCmd.length > 0 && vpnDialog.disconnectCmd.length > 0; - } - return vpnDialog.interfaceName.length > 0; - } - inactiveColour: Colours.palette.m3primaryContainer - inactiveOnColour: Colours.palette.m3onPrimaryContainer - - onClicked: { - const providers = []; - const hasCommands = vpnDialog.connectCmd.length > 0 && vpnDialog.disconnectCmd.length > 0; - const newProvider = { - displayName: vpnDialog.displayName || vpnDialog.interfaceName, - enabled: false, - interface: vpnDialog.interfaceName, - name: vpnDialog.providerName - }; - - if (hasCommands) { - newProvider.connectCmd = vpnDialog.connectCmd.split(" ").filter(s => s.length > 0); - newProvider.disconnectCmd = vpnDialog.disconnectCmd.split(" ").filter(s => s.length > 0); - } - - if (vpnDialog.editIndex >= 0) { - const oldProvider = GlobalConfig.utilities.vpn.provider[vpnDialog.editIndex]; - if (typeof oldProvider === "object" && oldProvider.enabled !== undefined) { - newProvider.enabled = oldProvider.enabled; - } - - for (let i = 0; i < GlobalConfig.utilities.vpn.provider.length; i++) { - if (i === vpnDialog.editIndex) { - providers.push(newProvider); - } else { - providers.push(GlobalConfig.utilities.vpn.provider[i]); - } - } - } else { - for (let i = 0; i < GlobalConfig.utilities.vpn.provider.length; i++) { - providers.push(GlobalConfig.utilities.vpn.provider[i]); - } - providers.push(newProvider); - } - - GlobalConfig.utilities.vpn.provider = providers; - vpnDialog.closeWithAnimation(); - } - } - } - } - } - - SequentialAnimation { - id: transitionToForm - - ParallelAnimation { - Anim { - target: selectionContent - property: "opacity" - to: 0 - type: Anim.EmphasizedSmall - } - } - - ScriptAction { - script: { - vpnDialog.currentState = "form"; - } - } - - ParallelAnimation { - Anim { - target: formContent - property: "opacity" - to: 1 - type: Anim.EmphasizedSmall - } - } - } - } -} diff --git a/modules/controlcenter/network/VpnSettings.qml b/modules/controlcenter/network/VpnSettings.qml deleted file mode 100644 index 328292e5..00000000 --- a/modules/controlcenter/network/VpnSettings.qml +++ /dev/null @@ -1,257 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "../components" -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Quickshell -import Caelestia.Config -import qs.components -import qs.components.containers -import qs.components.controls -import qs.components.effects -import qs.services - -ColumnLayout { - id: root - - required property Session session - - spacing: Tokens.spacing.medium - - SettingsHeader { - icon: "vpn_key" - title: qsTr("VPN Settings") - } - - SectionHeader { - Layout.topMargin: Tokens.spacing.largeIncreased - title: qsTr("General") - description: qsTr("VPN configuration") - } - - SectionContainer { - ToggleRow { - label: qsTr("VPN enabled") - checked: GlobalConfig.utilities.vpn.enabled - toggle.onToggled: { - GlobalConfig.utilities.vpn.enabled = checked; - } - } - } - - SectionHeader { - Layout.topMargin: Tokens.spacing.largeIncreased - title: qsTr("Providers") - description: qsTr("Manage VPN providers") - } - - SectionContainer { - contentSpacing: Tokens.spacing.medium - - ListView { - Layout.fillWidth: true - Layout.preferredHeight: contentHeight - - interactive: false - spacing: Tokens.spacing.medium - - model: ScriptModel { - values: GlobalConfig.utilities.vpn.provider.map((provider, index) => { - const isObject = typeof provider === "object"; - const name = isObject ? (provider.name || "custom") : String(provider); - const displayName = isObject ? (provider.displayName || name) : name; - const iface = isObject ? (provider.interface || "") : ""; - - return { - index: index, - name: name, - displayName: displayName, - interface: iface, - provider: provider, - isActive: index === 0 - }; - }) - } - - delegate: Component { - StyledRect { - required property var modelData - required property int index - - width: ListView.view ? ListView.view.width : undefined - implicitHeight: 60 - color: Colours.tPalette.m3surfaceContainerHigh - radius: Tokens.rounding.large - - RowLayout { - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - anchors.margins: Tokens.padding.medium - spacing: Tokens.spacing.medium - - MaterialIcon { - text: modelData.isActive ? "vpn_key" : "vpn_key_off" - fontStyle: Tokens.font.icon.large - color: modelData.isActive ? Colours.palette.m3primary : Colours.palette.m3outline - } - - ColumnLayout { - Layout.fillWidth: true - spacing: 0 - - StyledText { - text: modelData.displayName - font: Tokens.font.body.builders.medium.weight(modelData.isActive ? Font.Medium : Font.Normal).build() - } - - StyledText { - text: qsTr("%1 • %2").arg(modelData.name).arg(modelData.interface || qsTr("No interface")) - font: Tokens.font.body.small - color: Colours.palette.m3outline - } - } - - IconButton { - icon: modelData.isActive ? "arrow_downward" : "arrow_upward" - visible: !modelData.isActive || GlobalConfig.utilities.vpn.provider.length > 1 - onClicked: { - const providers = []; - for (let i = 0; i < GlobalConfig.utilities.vpn.provider.length; i++) { - const p = GlobalConfig.utilities.vpn.provider[i]; - const reconstructed = { - name: p.name, - displayName: p.displayName, - interface: p.interface, - enabled: p.enabled - }; - if (p.connectCmd && p.connectCmd.length > 0) { - reconstructed.connectCmd = p.connectCmd; - } - if (p.disconnectCmd && p.disconnectCmd.length > 0) { - reconstructed.disconnectCmd = p.disconnectCmd; - } - providers.push(reconstructed); - } - - if (modelData.isActive && index < providers.length - 1) { - // Move down - const temp = providers[index]; - providers[index] = providers[index + 1]; - providers[index + 1] = temp; - } else if (!modelData.isActive) { - // Make active (move to top) - const provider = providers.splice(index, 1)[0]; - providers.unshift(provider); - } - - GlobalConfig.utilities.vpn.provider = providers; - } - } - - IconButton { - icon: "delete" - onClicked: { - const providers = []; - for (let i = 0; i < GlobalConfig.utilities.vpn.provider.length; i++) { - if (i !== index) { - const p = GlobalConfig.utilities.vpn.provider[i]; - const reconstructed = { - name: p.name, - displayName: p.displayName, - interface: p.interface, - enabled: p.enabled - }; - if (p.connectCmd && p.connectCmd.length > 0) { - reconstructed.connectCmd = p.connectCmd; - } - if (p.disconnectCmd && p.disconnectCmd.length > 0) { - reconstructed.disconnectCmd = p.disconnectCmd; - } - providers.push(reconstructed); - } - } - GlobalConfig.utilities.vpn.provider = providers; - } - } - } - } - } - } - - TextButton { - Layout.fillWidth: true - Layout.topMargin: Tokens.spacing.medium - text: qsTr("+ Add Provider") - inactiveColour: Colours.palette.m3primaryContainer - inactiveOnColour: Colours.palette.m3onPrimaryContainer - - onClicked: { - addProviderDialog.open(); - } - } - } - - SectionHeader { - Layout.topMargin: Tokens.spacing.largeIncreased - title: qsTr("Quick Add") - description: qsTr("Add common VPN providers") - } - - SectionContainer { - contentSpacing: Tokens.spacing.medium - - TextButton { - Layout.fillWidth: true - text: qsTr("+ Add NetBird") - inactiveColour: Colours.tPalette.m3surfaceContainerHigh - inactiveOnColour: Colours.palette.m3onSurface - - onClicked: { - const providers = [...GlobalConfig.utilities.vpn.provider]; - providers.push({ - name: "netbird", - displayName: "NetBird", - interface: "wt0" - }); - GlobalConfig.utilities.vpn.provider = providers; - } - } - - TextButton { - Layout.fillWidth: true - text: qsTr("+ Add Tailscale") - inactiveColour: Colours.tPalette.m3surfaceContainerHigh - inactiveOnColour: Colours.palette.m3onSurface - - onClicked: { - const providers = [...GlobalConfig.utilities.vpn.provider]; - providers.push({ - name: "tailscale", - displayName: "Tailscale", - interface: "tailscale0" - }); - GlobalConfig.utilities.vpn.provider = providers; - } - } - - TextButton { - Layout.fillWidth: true - text: qsTr("+ Add Cloudflare WARP") - inactiveColour: Colours.tPalette.m3surfaceContainerHigh - inactiveOnColour: Colours.palette.m3onSurface - - onClicked: { - const providers = [...GlobalConfig.utilities.vpn.provider]; - providers.push({ - name: "warp", - displayName: "Cloudflare WARP", - interface: "CloudflareWARP" - }); - GlobalConfig.utilities.vpn.provider = providers; - } - } - } -} diff --git a/modules/controlcenter/network/WirelessDetails.qml b/modules/controlcenter/network/WirelessDetails.qml deleted file mode 100644 index 51123a29..00000000 --- a/modules/controlcenter/network/WirelessDetails.qml +++ /dev/null @@ -1,213 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "../components" -import "." -import QtQuick -import QtQuick.Layouts -import Caelestia.Config -import qs.components -import qs.components.containers -import qs.components.controls -import qs.components.effects -import qs.services -import qs.utils - -DeviceDetails { - id: root - - required property Session session - readonly property var network: root.session.network.active - - function checkSavedProfile(): void { - if (network && network.ssid) { - Nmcli.loadSavedConnections(() => {}); - } - } - - function updateDeviceDetails(): void { - if (network && network.ssid) { - const isActive = network.active || (Nmcli.active && Nmcli.active.ssid === network.ssid); - if (isActive) { - Nmcli.getWirelessDeviceDetails(""); - } else { - Nmcli.wirelessDeviceDetails = null; - } - } else { - Nmcli.wirelessDeviceDetails = null; - } - } - - device: network - - Component.onCompleted: { - updateDeviceDetails(); - checkSavedProfile(); - } - - onNetworkChanged: { - connectionUpdateTimer.stop(); - if (network && network.ssid) { - connectionUpdateTimer.start(); - } - updateDeviceDetails(); - checkSavedProfile(); - } - - headerComponent: Component { - ConnectionHeader { - icon: root.network?.isSecure ? "lock" : "wifi" - title: root.network?.ssid ?? qsTr("Unknown") - } - } - - sections: [ - Component { - ColumnLayout { - spacing: Tokens.spacing.medium - - SectionHeader { - title: qsTr("Connection status") - description: qsTr("Connection settings for this network") - } - - SectionContainer { - ToggleRow { - label: qsTr("Connected") - checked: root.network?.active ?? false - toggle.onToggled: { - if (checked) { - NetworkConnection.handleConnect(root.network, root.session, null); - } else { - Nmcli.disconnectFromNetwork(); - } - } - } - - TextButton { - Layout.fillWidth: true - Layout.topMargin: Tokens.spacing.medium - Layout.minimumHeight: Tokens.font.body.medium.pointSize + Tokens.padding.medium * 2 - visible: { - if (!root.network || !root.network.ssid) { - return false; - } - return Nmcli.hasSavedProfile(root.network.ssid); - } - inactiveColour: Colours.palette.m3secondaryContainer - inactiveOnColour: Colours.palette.m3onSecondaryContainer - text: qsTr("Forget Network") - - onClicked: { - if (root.network && root.network.ssid) { - if (root.network.active) { - Nmcli.disconnectFromNetwork(); - } - Nmcli.forgetNetwork(root.network.ssid); - } - } - } - } - } - }, - Component { - ColumnLayout { - spacing: Tokens.spacing.medium - - SectionHeader { - title: qsTr("Network properties") - description: qsTr("Additional information") - } - - SectionContainer { - contentSpacing: Tokens.spacing.extraSmall - - PropertyRow { - label: qsTr("SSID") - value: root.network?.ssid ?? qsTr("Unknown") - } - - PropertyRow { - showTopMargin: true - label: qsTr("BSSID") - value: root.network?.bssid ?? qsTr("Unknown") - } - - PropertyRow { - showTopMargin: true - label: qsTr("Signal strength") - value: root.network ? qsTr("%1%").arg(root.network.strength) : qsTr("N/A") - } - - PropertyRow { - showTopMargin: true - label: qsTr("Frequency") - value: root.network ? qsTr("%1 MHz").arg(root.network.frequency) : qsTr("N/A") - } - - PropertyRow { - showTopMargin: true - label: qsTr("Security") - value: root.network ? (root.network.isSecure ? root.network.security : qsTr("Open")) : qsTr("N/A") - } - } - } - }, - Component { - ColumnLayout { - spacing: Tokens.spacing.medium - - SectionHeader { - title: qsTr("Connection information") - description: qsTr("Network connection details") - } - - SectionContainer { - ConnectionInfoSection { - deviceDetails: Nmcli.wirelessDeviceDetails - } - } - } - } - ] - - Connections { - function onActiveChanged() { - updateDeviceDetails(); - } - function onWirelessDeviceDetailsChanged() { - if (network && network.ssid) { - const isActive = network.active || (Nmcli.active && Nmcli.active.ssid === network.ssid); - if (isActive && Nmcli.wirelessDeviceDetails && Nmcli.wirelessDeviceDetails !== null) { - connectionUpdateTimer.stop(); - } - } - } - - target: Nmcli - } - - Timer { - id: connectionUpdateTimer - - interval: 500 - repeat: true - running: network && network.ssid - onTriggered: { - if (network) { - const isActive = network.active || (Nmcli.active && Nmcli.active.ssid === network.ssid); - if (isActive) { - if (!Nmcli.wirelessDeviceDetails || Nmcli.wirelessDeviceDetails === null) { - Nmcli.getWirelessDeviceDetails("", () => {}); - } else { - connectionUpdateTimer.stop(); - } - } else { - if (Nmcli.wirelessDeviceDetails !== null) { - Nmcli.wirelessDeviceDetails = null; - } - } - } - } - } -} diff --git a/modules/controlcenter/network/WirelessList.qml b/modules/controlcenter/network/WirelessList.qml deleted file mode 100644 index 6dc29d69..00000000 --- a/modules/controlcenter/network/WirelessList.qml +++ /dev/null @@ -1,225 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "../components" -import "." -import QtQuick -import QtQuick.Layouts -import Quickshell -import Caelestia.Config -import qs.components -import qs.components.containers -import qs.components.controls -import qs.components.effects -import qs.services -import qs.utils - -DeviceList { - id: root - - required property Session session - - function checkSavedProfileForNetwork(ssid: string): void { - if (ssid && ssid.length > 0) { - Nmcli.loadSavedConnections(() => {}); - } - } - - title: qsTr("Networks (%1)").arg(Nmcli.networks.length) - description: qsTr("All available WiFi networks") - activeItem: session.network.active - - titleSuffix: Component { - StyledText { - visible: Nmcli.scanning - text: qsTr("Scanning...") - color: Colours.palette.m3primary - font: Tokens.font.title.small - } - } - - model: ScriptModel { - values: [...Nmcli.networks].sort((a, b) => { - if (a.active !== b.active) - return b.active - a.active; - return b.strength - a.strength; - }) - } - - headerComponent: Component { - RowLayout { - spacing: Tokens.spacing.medium - - StyledText { - text: qsTr("Settings") - font: Tokens.font.title.builders.medium.weight(Font.Medium).build() - } - - Item { - Layout.fillWidth: true - } - - ToggleButton { - toggled: Nmcli.wifiEnabled - icon: "wifi" - accent: "Tertiary" - iconSize: Tokens.font.body.medium.pointSize - horizontalPadding: Tokens.padding.medium - verticalPadding: Tokens.padding.small - - onClicked: { - Nmcli.toggleWifi(null); - } - } - - ToggleButton { - toggled: Nmcli.scanning - icon: "wifi_find" - accent: "Secondary" - iconSize: Tokens.font.body.medium.pointSize - horizontalPadding: Tokens.padding.medium - verticalPadding: Tokens.padding.small - - onClicked: { - Nmcli.rescanWifi(); - } - } - - ToggleButton { - toggled: !root.session.network.active - icon: "settings" - accent: "Primary" - iconSize: Tokens.font.body.medium.pointSize - horizontalPadding: Tokens.padding.medium - verticalPadding: Tokens.padding.small - - onClicked: { - if (root.session.network.active) - root.session.network.active = null; - else { - root.session.network.active = root.view.model.get(0)?.modelData ?? null; - } - } - } - } - } - - delegate: Component { - StyledRect { - required property var modelData - - width: ListView.view ? ListView.view.width : undefined - implicitHeight: rowLayout.implicitHeight + Tokens.padding.medium * 2 - - color: Qt.alpha(Colours.tPalette.m3surfaceContainer, root.activeItem === modelData ? Colours.tPalette.m3surfaceContainer.a : 0) - radius: Tokens.rounding.large - - StateLayer { - onClicked: { - root.session.network.active = modelData; - if (modelData && modelData.ssid) { - root.checkSavedProfileForNetwork(modelData.ssid); - } - } - } - - RowLayout { - id: rowLayout - - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - anchors.margins: Tokens.padding.medium - - spacing: Tokens.spacing.medium - - StyledRect { - implicitWidth: implicitHeight - implicitHeight: icon.implicitHeight + Tokens.padding.medium * 2 - - radius: Tokens.rounding.large - color: modelData.active ? Colours.palette.m3primaryContainer : Colours.tPalette.m3surfaceContainerHigh - - MaterialIcon { - id: icon - - anchors.centerIn: parent - text: Icons.getNetworkIcon(modelData.strength, modelData.isSecure) - fontStyle: Tokens.font.icon.large - fill: modelData.active ? 1 : 0 - color: modelData.active ? Colours.palette.m3onPrimaryContainer : Colours.palette.m3onSurface - } - } - - ColumnLayout { - Layout.fillWidth: true - - spacing: 0 - - StyledText { - Layout.fillWidth: true - elide: Text.ElideRight - maximumLineCount: 1 - - text: modelData.ssid || qsTr("Unknown") - } - - RowLayout { - Layout.fillWidth: true - spacing: Tokens.spacing.medium - - StyledText { - Layout.fillWidth: true - text: { - if (modelData.active) - return qsTr("Connected"); - if (modelData.isSecure && modelData.security && modelData.security.length > 0) { - return modelData.security; - } - if (modelData.isSecure) - return qsTr("Secured"); - return qsTr("Open"); - } - color: modelData.active ? Colours.palette.m3primary : Colours.palette.m3outline - font: Tokens.font.body.builders.small.weight(modelData.active ? Font.Medium : Font.Normal).build() - elide: Text.ElideRight - } - } - } - - StyledRect { - implicitWidth: implicitHeight - implicitHeight: connectIcon.implicitHeight + Tokens.padding.large - - radius: Tokens.rounding.full - color: Qt.alpha(Colours.palette.m3primaryContainer, modelData.active ? 1 : 0) - - StateLayer { - onClicked: { - if (modelData.active) { - Nmcli.disconnectFromNetwork(); - } else { - NetworkConnection.handleConnect(modelData, root.session, null); - } - } - } - - MaterialIcon { - id: connectIcon - - anchors.centerIn: parent - text: modelData.active ? "link_off" : "link" - color: modelData.active ? Colours.palette.m3onPrimaryContainer : Colours.palette.m3onSurface - } - } - } - } - } - - onItemSelected: function (item) { - session.network.active = item; - if (item && item.ssid) { - checkSavedProfileForNetwork(item.ssid); - } - } -} diff --git a/modules/controlcenter/network/WirelessPane.qml b/modules/controlcenter/network/WirelessPane.qml deleted file mode 100644 index 43689176..00000000 --- a/modules/controlcenter/network/WirelessPane.qml +++ /dev/null @@ -1,57 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "../components" -import QtQuick -import Quickshell.Widgets -import Caelestia.Config -import qs.components -import qs.components.containers - -SplitPaneWithDetails { - id: root - - required property Session session - - anchors.fill: parent - - activeItem: session.network.active - paneIdGenerator: function (item) { - return item ? (item.ssid || item.bssid || "") : ""; - } - - leftContent: Component { - WirelessList { - session: root.session - } - } - - rightDetailsComponent: Component { - WirelessDetails { - session: root.session - } - } - - rightSettingsComponent: Component { - StyledFlickable { - flickableDirection: Flickable.VerticalFlick - contentHeight: settingsInner.height - clip: true - - WirelessSettings { - id: settingsInner - - anchors.left: parent.left - anchors.right: parent.right - session: root.session - } - } - } - - overlayComponent: Component { - WirelessPasswordDialog { - anchors.fill: parent - session: root.session - } - } -} diff --git a/modules/controlcenter/network/WirelessPasswordDialog.qml b/modules/controlcenter/network/WirelessPasswordDialog.qml deleted file mode 100644 index 4e793a53..00000000 --- a/modules/controlcenter/network/WirelessPasswordDialog.qml +++ /dev/null @@ -1,522 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "." -import QtQuick -import QtQuick.Layouts -import Quickshell -import Caelestia.Config -import qs.components -import qs.components.containers -import qs.components.controls -import qs.components.effects -import qs.services -import qs.utils - -Item { - id: root - - required property Session session - - readonly property var network: { - if (session.network.pendingNetwork) { - return session.network.pendingNetwork; - } - if (session.network.active) { - return session.network.active; - } - return null; - } - - property bool isClosing: false - - function checkConnectionStatus(): void { - if (!root.visible || !connectButton.connecting) { - return; - } - - const isConnected = root.network && Nmcli.active && Nmcli.active.ssid && Nmcli.active.ssid.toLowerCase().trim() === root.network.ssid.toLowerCase().trim(); - - if (isConnected) { - connectionSuccessTimer.start(); - return; - } - - if (Nmcli.pendingConnection === null && connectButton.connecting) { - if (connectionMonitor.repeatCount > 10) { - connectionMonitor.stop(); - connectButton.connecting = false; - connectButton.hasError = true; - connectButton.enabled = true; - connectButton.text = qsTr("Connect"); - passwordContainer.passwordBuffer = ""; - if (root.network && root.network.ssid) { - Nmcli.forgetNetwork(root.network.ssid); - } - } - } - } - - function closeDialog(): void { - if (isClosing) { - return; - } - - isClosing = true; - passwordContainer.passwordBuffer = ""; - connectButton.connecting = false; - connectButton.hasError = false; - connectButton.text = qsTr("Connect"); - connectionMonitor.stop(); - } - - visible: session.network.showPasswordDialog || isClosing - enabled: session.network.showPasswordDialog && !isClosing - focus: enabled - - Keys.onEscapePressed: { - closeDialog(); - } - - Rectangle { - anchors.fill: parent - color: Qt.rgba(0, 0, 0, 0.5) - opacity: root.session.network.showPasswordDialog && !root.isClosing ? 1 : 0 - - Behavior on opacity { - Anim {} - } - - MouseArea { - anchors.fill: parent - onClicked: closeDialog() - } - } - - StyledRect { - id: dialog - - anchors.centerIn: parent - - implicitWidth: 400 - implicitHeight: content.implicitHeight + Tokens.padding.extraLargeIncreased - - radius: Tokens.rounding.large - color: Colours.tPalette.m3surface - opacity: root.session.network.showPasswordDialog && !root.isClosing ? 1 : 0 - scale: root.session.network.showPasswordDialog && !root.isClosing ? 1 : 0.7 - Keys.onEscapePressed: closeDialog() - - Behavior on opacity { - Anim {} - } - - Behavior on scale { - Anim {} - } - - ParallelAnimation { - running: root.isClosing - onFinished: { - if (root.isClosing) { - root.session.network.showPasswordDialog = false; - root.isClosing = false; - } - } - - Anim { - target: dialog - property: "opacity" - to: 0 - } - Anim { - target: dialog - property: "scale" - to: 0.7 - } - } - - ColumnLayout { - id: content - - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - anchors.margins: Tokens.padding.large - - spacing: Tokens.spacing.medium - - MaterialIcon { - Layout.alignment: Qt.AlignHCenter - text: "lock" - fontStyle: Tokens.font.icon.builders.extraLarge.scale(2).build() - } - - StyledText { - Layout.alignment: Qt.AlignHCenter - text: qsTr("Enter password") - font: Tokens.font.body.builders.large.weight(Font.Medium).build() - } - - StyledText { - Layout.alignment: Qt.AlignHCenter - text: root.network ? qsTr("Network: %1").arg(root.network.ssid) : "" - color: Colours.palette.m3outline - font: Tokens.font.body.small - } - - StyledText { - id: statusText - - Layout.alignment: Qt.AlignHCenter - Layout.topMargin: Tokens.spacing.small - visible: connectButton.connecting || connectButton.hasError - text: { - if (connectButton.hasError) { - return qsTr("Connection failed. Please check your password and try again."); - } - if (connectButton.connecting) { - return qsTr("Connecting..."); - } - return ""; - } - color: connectButton.hasError ? Colours.palette.m3error : Colours.palette.m3onSurfaceVariant - font: Tokens.font.body.builders.small.weight(Font.Normal).build() - wrapMode: Text.WordWrap - Layout.maximumWidth: parent.width - Tokens.padding.extraLargeIncreased - } - - Item { - id: passwordContainer - - property string passwordBuffer: "" - - Layout.topMargin: Tokens.spacing.largeIncreased - Layout.fillWidth: true - implicitHeight: Math.max(48, charList.implicitHeight + Tokens.padding.medium * 2) - focus: true - Keys.onPressed: event => { - if (!activeFocus) { - forceActiveFocus(); - } - - if (event.key === Qt.Key_Escape) { - event.accepted = false; - closeDialog(); - } - - if (connectButton.hasError && event.text && event.text.length > 0) { - connectButton.hasError = false; - } - - if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) { - if (connectButton.enabled) { - connectButton.clicked(); - } - event.accepted = true; - } else if (event.key === Qt.Key_Backspace) { - if (event.modifiers & Qt.ControlModifier) { - passwordBuffer = ""; - } else { - passwordBuffer = passwordBuffer.slice(0, -1); - } - event.accepted = true; - } else if (event.text && event.text.length > 0) { - if (event.key === Qt.Key_Tab) { - event.accepted = false; - return; - } - passwordBuffer += event.text; - event.accepted = true; - } - } - - Connections { - function onShowPasswordDialogChanged(): void { - if (root.session.network.showPasswordDialog) { - Qt.callLater(() => { - passwordContainer.forceActiveFocus(); - passwordContainer.passwordBuffer = ""; - connectButton.hasError = false; - }); - } - } - - target: root.session.network - } - - Connections { - function onVisibleChanged(): void { - if (root.visible) { - Qt.callLater(() => { - passwordContainer.forceActiveFocus(); - }); - } - } - - target: root - } - - StyledRect { - anchors.fill: parent - radius: Tokens.rounding.large - color: passwordContainer.activeFocus ? Qt.lighter(Colours.tPalette.m3surfaceContainer, 1.05) : Colours.tPalette.m3surfaceContainer - border.width: passwordContainer.activeFocus || connectButton.hasError ? 4 : (root.visible ? 1 : 0) - border.color: { - if (connectButton.hasError) { - return Colours.palette.m3error; - } - if (passwordContainer.activeFocus) { - return Colours.palette.m3primary; - } - return root.visible ? Colours.palette.m3outline : "transparent"; - } - - Behavior on border.color { - CAnim {} - } - - Behavior on border.width { - CAnim {} - } - - Behavior on color { - CAnim {} - } - } - - StateLayer { - onClicked: { - passwordContainer.forceActiveFocus(); - } - - hoverEnabled: false - cursorShape: Qt.IBeamCursor - } - - StyledText { - id: placeholder - - anchors.centerIn: parent - text: qsTr("Password") - color: Colours.palette.m3outline - font: Tokens.font.mono.medium - opacity: passwordContainer.passwordBuffer ? 0 : 1 - - Behavior on opacity { - Anim {} - } - } - - ListView { - id: charList - - readonly property int fullWidth: count * (implicitHeight + spacing) - spacing - - anchors.centerIn: parent - implicitWidth: fullWidth - implicitHeight: Tokens.font.body.medium.pointSize - - orientation: Qt.Horizontal - spacing: Tokens.spacing.extraSmall - interactive: false - - model: ScriptModel { - values: passwordContainer.passwordBuffer.split("") - } - - delegate: StyledRect { - id: ch - - implicitWidth: implicitHeight - implicitHeight: charList.implicitHeight - - color: Colours.palette.m3onSurface - radius: Tokens.rounding.medium / 2 - - opacity: 0 - scale: 0 - Component.onCompleted: { - opacity = 1; - scale = 1; - } - ListView.onRemove: removeAnim.start() - - SequentialAnimation { - id: removeAnim - - PropertyAction { - target: ch - property: "ListView.delayRemove" - value: true - } - ParallelAnimation { - Anim { - target: ch - property: "opacity" - to: 0 - } - Anim { - target: ch - property: "scale" - to: 0.5 - } - } - PropertyAction { - target: ch - property: "ListView.delayRemove" - value: false - } - } - - Behavior on opacity { - Anim {} - } - - Behavior on scale { - Anim { - type: Anim.FastSpatial - } - } - } - - Behavior on implicitWidth { - Anim {} - } - } - } - - RowLayout { - Layout.topMargin: Tokens.spacing.medium - Layout.fillWidth: true - spacing: Tokens.spacing.medium - - TextButton { - id: cancelButton - - Layout.fillWidth: true - Layout.minimumHeight: Tokens.font.body.medium.pointSize + Tokens.padding.medium * 2 - inactiveColour: Colours.palette.m3secondaryContainer - inactiveOnColour: Colours.palette.m3onSecondaryContainer - text: qsTr("Cancel") - - onClicked: root.closeDialog() - } - - TextButton { - id: connectButton - - property bool connecting: false - property bool hasError: false - - Layout.fillWidth: true - Layout.minimumHeight: Tokens.font.body.medium.pointSize + Tokens.padding.medium * 2 - inactiveColour: Colours.palette.m3primary - inactiveOnColour: Colours.palette.m3onPrimary - text: qsTr("Connect") - enabled: passwordContainer.passwordBuffer.length > 0 && !connecting - - onClicked: { - if (!root.network || connecting) { - return; - } - - const password = passwordContainer.passwordBuffer; - if (!password || password.length === 0) { - return; - } - - hasError = false; - connecting = true; - enabled = false; - text = qsTr("Connecting..."); - - NetworkConnection.connectWithPassword(root.network, password, result => { - if (result && result.success) {} else if (result && result.needsPassword) { - connectionMonitor.stop(); - connecting = false; - hasError = true; - enabled = true; - text = qsTr("Connect"); - passwordContainer.passwordBuffer = ""; - if (root.network && root.network.ssid) { - Nmcli.forgetNetwork(root.network.ssid); - } - } else { - connectionMonitor.stop(); - connecting = false; - hasError = true; - enabled = true; - text = qsTr("Connect"); - passwordContainer.passwordBuffer = ""; - if (root.network && root.network.ssid) { - Nmcli.forgetNetwork(root.network.ssid); - } - } - }); - - connectionMonitor.start(); - } - } - } - } - } - - Timer { - id: connectionMonitor - - property int repeatCount: 0 - - interval: 1000 - repeat: true - triggeredOnStart: false - onTriggered: { - repeatCount++; - checkConnectionStatus(); - } - - onRunningChanged: { - if (!running) { - repeatCount = 0; - } - } - } - - Timer { - id: connectionSuccessTimer - - interval: 500 - onTriggered: { - if (root.visible && Nmcli.active && Nmcli.active.ssid) { - const stillConnected = Nmcli.active.ssid.toLowerCase().trim() === root.network.ssid.toLowerCase().trim(); - if (stillConnected) { - connectionMonitor.stop(); - connectButton.connecting = false; - connectButton.text = qsTr("Connect"); - closeDialog(); - } - } - } - } - - Connections { - function onActiveChanged() { - if (root.visible) { - checkConnectionStatus(); - } - } - function onConnectionFailed(ssid: string) { - if (root.visible && root.network && root.network.ssid === ssid && connectButton.connecting) { - connectionMonitor.stop(); - connectButton.connecting = false; - connectButton.hasError = true; - connectButton.enabled = true; - connectButton.text = qsTr("Connect"); - passwordContainer.passwordBuffer = ""; - Nmcli.forgetNetwork(ssid); - } - } - - target: Nmcli - } -} diff --git a/modules/controlcenter/network/WirelessSettings.qml b/modules/controlcenter/network/WirelessSettings.qml deleted file mode 100644 index bf55497a..00000000 --- a/modules/controlcenter/network/WirelessSettings.qml +++ /dev/null @@ -1,73 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "../components" -import QtQuick -import QtQuick.Layouts -import Caelestia.Config -import qs.components -import qs.components.controls -import qs.components.effects -import qs.services - -ColumnLayout { - id: root - - required property Session session - - spacing: Tokens.spacing.medium - - SettingsHeader { - icon: "wifi" - title: qsTr("Network settings") - } - - SectionHeader { - Layout.topMargin: Tokens.spacing.largeIncreased - title: qsTr("WiFi status") - description: qsTr("General WiFi settings") - } - - SectionContainer { - ToggleRow { - label: qsTr("WiFi enabled") - checked: Nmcli.wifiEnabled - toggle.onToggled: { - Nmcli.enableWifi(checked); - } - } - } - - SectionHeader { - Layout.topMargin: Tokens.spacing.largeIncreased - title: qsTr("Network information") - description: qsTr("Current network connection") - } - - SectionContainer { - contentSpacing: Tokens.spacing.extraSmall - - PropertyRow { - label: qsTr("Connected network") - value: Nmcli.active ? Nmcli.active.ssid : qsTr("Not connected") - } - - PropertyRow { - showTopMargin: true - label: qsTr("Signal strength") - value: Nmcli.active ? qsTr("%1%").arg(Nmcli.active.strength) : qsTr("N/A") - } - - PropertyRow { - showTopMargin: true - label: qsTr("Security") - value: Nmcli.active ? (Nmcli.active.isSecure ? qsTr("Secured") : qsTr("Open")) : qsTr("N/A") - } - - PropertyRow { - showTopMargin: true - label: qsTr("Frequency") - value: Nmcli.active ? qsTr("%1 MHz").arg(Nmcli.active.frequency) : qsTr("N/A") - } - } -} diff --git a/modules/controlcenter/notifications/NotificationsPane.qml b/modules/controlcenter/notifications/NotificationsPane.qml deleted file mode 100644 index 90ccf25d..00000000 --- a/modules/controlcenter/notifications/NotificationsPane.qml +++ /dev/null @@ -1,425 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "../components" -import QtQuick -import QtQuick.Layouts -import Quickshell -import Quickshell.Widgets -import Caelestia.Config -import qs.components -import qs.components.containers -import qs.components.controls -import qs.components.effects -import qs.services - -Item { - id: root - - required property Session session - - property bool notificationsExpire: GlobalConfig.notifs.expire ?? true - property string notificationsFullscreen: GlobalConfig.notifs.fullscreen ?? "on" - property bool notificationsOpenExpanded: Config.notifs.openExpanded ?? false - property int notificationsDefaultExpireTimeout: GlobalConfig.notifs.defaultExpireTimeout ?? 5000 - property int notificationsGroupPreviewNum: Config.notifs.groupPreviewNum ?? 3 - - property int maxToasts: Config.utilities.maxToasts ?? 4 - property string toastsFullscreen: Config.utilities.toasts.fullscreen ?? "off" - property bool chargingChanged: GlobalConfig.utilities.toasts.chargingChanged ?? true - property bool gameModeChanged: GlobalConfig.utilities.toasts.gameModeChanged ?? true - property bool dndChanged: GlobalConfig.utilities.toasts.dndChanged ?? true - property bool audioOutputChanged: GlobalConfig.utilities.toasts.audioOutputChanged ?? true - property bool audioInputChanged: GlobalConfig.utilities.toasts.audioInputChanged ?? true - property bool capsLockChanged: GlobalConfig.utilities.toasts.capsLockChanged ?? true - property bool numLockChanged: GlobalConfig.utilities.toasts.numLockChanged ?? true - property bool kbLayoutChanged: GlobalConfig.utilities.toasts.kbLayoutChanged ?? true - property bool vpnChanged: GlobalConfig.utilities.toasts.vpnChanged ?? true - property bool nowPlaying: GlobalConfig.utilities.toasts.nowPlaying ?? false - - function saveConfig(): void { - GlobalConfig.notifs.expire = root.notificationsExpire; - GlobalConfig.notifs.fullscreen = root.notificationsFullscreen; - GlobalConfig.notifs.openExpanded = root.notificationsOpenExpanded; - GlobalConfig.notifs.defaultExpireTimeout = root.notificationsDefaultExpireTimeout; - GlobalConfig.notifs.groupPreviewNum = root.notificationsGroupPreviewNum; - - GlobalConfig.utilities.maxToasts = root.maxToasts; - GlobalConfig.utilities.toasts.fullscreen = root.toastsFullscreen; - GlobalConfig.utilities.toasts.chargingChanged = root.chargingChanged; - GlobalConfig.utilities.toasts.gameModeChanged = root.gameModeChanged; - GlobalConfig.utilities.toasts.dndChanged = root.dndChanged; - GlobalConfig.utilities.toasts.audioOutputChanged = root.audioOutputChanged; - GlobalConfig.utilities.toasts.audioInputChanged = root.audioInputChanged; - GlobalConfig.utilities.toasts.capsLockChanged = root.capsLockChanged; - GlobalConfig.utilities.toasts.numLockChanged = root.numLockChanged; - GlobalConfig.utilities.toasts.kbLayoutChanged = root.kbLayoutChanged; - GlobalConfig.utilities.toasts.vpnChanged = root.vpnChanged; - GlobalConfig.utilities.toasts.nowPlaying = root.nowPlaying; - } - - anchors.fill: parent - - ClippingRectangle { - id: notificationsClippingRect - - anchors.fill: parent - anchors.margins: Tokens.padding.medium - anchors.leftMargin: 0 - anchors.rightMargin: Tokens.padding.medium - - color: "transparent" - radius: notificationsBorder.innerRadius - - Loader { - id: notificationsLoader - - anchors.fill: parent - anchors.margins: Tokens.padding.large + Tokens.padding.medium - anchors.leftMargin: Tokens.padding.large - anchors.rightMargin: Tokens.padding.large - - sourceComponent: notificationsContentComponent - } - } - - InnerBorder { - id: notificationsBorder - - leftThickness: 0 - rightThickness: Tokens.padding.medium - } - - Component { - id: notificationsContentComponent - - StyledFlickable { - id: notificationsFlickable - - flickableDirection: Flickable.VerticalFlick - contentHeight: notificationsLayout.height - - StyledScrollBar.vertical: StyledScrollBar { - flickable: notificationsFlickable - } - - RowLayout { - id: notificationsLayout - - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - spacing: Tokens.spacing.medium - - ColumnLayout { - Layout.fillWidth: true - Layout.maximumWidth: 500 - Layout.alignment: Qt.AlignTop - spacing: Tokens.spacing.medium - - SectionContainer { - Layout.fillWidth: true - alignTop: true - - StyledText { - text: qsTr("Notifications") - font: Tokens.font.title.small - } - - SplitButtonRow { - id: notificationsFullscreenSelector - - function syncActiveItem(): void { - active = root.notificationsFullscreen === "off" ? notificationsFullscreenOffItem : notificationsFullscreenOnItem; - } - - label: qsTr("Show in fullscreen") - menuItems: [notificationsFullscreenOffItem, notificationsFullscreenOnItem] - - Component.onCompleted: syncActiveItem() - - Connections { - function onNotificationsFullscreenChanged(): void { - notificationsFullscreenSelector.syncActiveItem(); - } - - target: root - } - - MenuItem { - id: notificationsFullscreenOffItem - - text: qsTr("Off") - icon: "notifications_off" - activeText: qsTr("Off") - onClicked: { - root.notificationsFullscreen = "off"; - root.saveConfig(); - } - } - - MenuItem { - id: notificationsFullscreenOnItem - - text: qsTr("On") - icon: "notifications" - activeText: qsTr("On") - onClicked: { - root.notificationsFullscreen = "on"; - root.saveConfig(); - } - } - } - - SwitchRow { - label: qsTr("Expire automatically") - checked: root.notificationsExpire - onToggled: checked => { - root.notificationsExpire = checked; - root.saveConfig(); - } - } - - SwitchRow { - label: qsTr("Open expanded") - checked: root.notificationsOpenExpanded - onToggled: checked => { - root.notificationsOpenExpanded = checked; - root.saveConfig(); - } - } - - SpinBoxRow { - label: qsTr("Default timeout") - value: root.notificationsDefaultExpireTimeout - min: 1000 - max: 60000 - step: 500 - onValueModified: value => { - root.notificationsDefaultExpireTimeout = value; - root.saveConfig(); - } - } - - SpinBoxRow { - label: qsTr("Group preview count") - value: root.notificationsGroupPreviewNum - min: 1 - max: 10 - step: 1 - onValueModified: value => { - root.notificationsGroupPreviewNum = value; - root.saveConfig(); - } - } - } - } - - ColumnLayout { - Layout.fillWidth: true - Layout.alignment: Qt.AlignTop - spacing: Tokens.spacing.medium - - SectionContainer { - Layout.fillWidth: true - alignTop: true - - StyledText { - text: qsTr("Toast settings") - font: Tokens.font.title.small - } - - SplitButtonRow { - id: toastFullscreenSelector - - function syncActiveItem(): void { - if (root.toastsFullscreen === "all") { - active = toastFullscreenAllItem; - return; - } - - if (root.toastsFullscreen === "important") { - active = toastFullscreenImportantItem; - return; - } - - active = toastFullscreenOffItem; - } - - Layout.fillWidth: true - z: expanded ? 100 : 0 - label: qsTr("Show in fullscreen") - menuItems: [toastFullscreenOffItem, toastFullscreenImportantItem, toastFullscreenAllItem] - - Component.onCompleted: syncActiveItem() - - Connections { - function onToastsFullscreenChanged(): void { - toastFullscreenSelector.syncActiveItem(); - } - - target: root - } - - MenuItem { - id: toastFullscreenOffItem - - text: qsTr("Off") - icon: "notifications_off" - activeText: qsTr("Off") - onClicked: { - root.toastsFullscreen = "off"; - root.saveConfig(); - } - } - - MenuItem { - id: toastFullscreenImportantItem - - text: qsTr("Important") - icon: "priority_high" - activeText: qsTr("Important") - onClicked: { - root.toastsFullscreen = "important"; - root.saveConfig(); - } - } - - MenuItem { - id: toastFullscreenAllItem - - text: qsTr("On") - icon: "notifications" - activeText: qsTr("On") - onClicked: { - root.toastsFullscreen = "all"; - root.saveConfig(); - } - } - } - - SpinBoxRow { - Layout.fillWidth: true - label: qsTr("Visible toasts") - value: root.maxToasts - min: 1 - max: 10 - step: 1 - onValueModified: value => { - root.maxToasts = value; - root.saveConfig(); - } - } - - GridLayout { - Layout.fillWidth: true - columns: 2 - columnSpacing: Tokens.spacing.medium - rowSpacing: Tokens.spacing.medium - - SwitchRow { - Layout.fillWidth: true - label: qsTr("Charging changes") - checked: root.chargingChanged - onToggled: checked => { - root.chargingChanged = checked; - root.saveConfig(); - } - } - - SwitchRow { - Layout.fillWidth: true - label: qsTr("Game mode changes") - checked: root.gameModeChanged - onToggled: checked => { - root.gameModeChanged = checked; - root.saveConfig(); - } - } - - SwitchRow { - Layout.fillWidth: true - label: qsTr("Do not disturb") - checked: root.dndChanged - onToggled: checked => { - root.dndChanged = checked; - root.saveConfig(); - } - } - - SwitchRow { - Layout.fillWidth: true - label: qsTr("Audio output changes") - checked: root.audioOutputChanged - onToggled: checked => { - root.audioOutputChanged = checked; - root.saveConfig(); - } - } - - SwitchRow { - Layout.fillWidth: true - label: qsTr("Audio input changes") - checked: root.audioInputChanged - onToggled: checked => { - root.audioInputChanged = checked; - root.saveConfig(); - } - } - - SwitchRow { - Layout.fillWidth: true - label: qsTr("Caps lock changes") - checked: root.capsLockChanged - onToggled: checked => { - root.capsLockChanged = checked; - root.saveConfig(); - } - } - - SwitchRow { - Layout.fillWidth: true - label: qsTr("Num lock changes") - checked: root.numLockChanged - onToggled: checked => { - root.numLockChanged = checked; - root.saveConfig(); - } - } - - SwitchRow { - Layout.fillWidth: true - label: qsTr("Keyboard layout changes") - checked: root.kbLayoutChanged - onToggled: checked => { - root.kbLayoutChanged = checked; - root.saveConfig(); - } - } - - SwitchRow { - Layout.fillWidth: true - label: qsTr("VPN changes") - checked: root.vpnChanged - onToggled: checked => { - root.vpnChanged = checked; - root.saveConfig(); - } - } - - SwitchRow { - Layout.fillWidth: true - label: qsTr("Now playing") - checked: root.nowPlaying - onToggled: checked => { - root.nowPlaying = checked; - root.saveConfig(); - } - } - } - } - } - } - } - } -} diff --git a/modules/controlcenter/state/BluetoothState.qml b/modules/controlcenter/state/BluetoothState.qml deleted file mode 100644 index 9b16bfe5..00000000 --- a/modules/controlcenter/state/BluetoothState.qml +++ /dev/null @@ -1,12 +0,0 @@ -import QtQuick -import Quickshell.Bluetooth - -QtObject { - id: root - - property BluetoothDevice active: null - property BluetoothAdapter currentAdapter: Bluetooth.defaultAdapter - property bool editingAdapterName: false - property bool fabMenuOpen: false - property bool editingDeviceName: false -} diff --git a/modules/controlcenter/state/EthernetState.qml b/modules/controlcenter/state/EthernetState.qml deleted file mode 100644 index 58f5fc8c..00000000 --- a/modules/controlcenter/state/EthernetState.qml +++ /dev/null @@ -1,7 +0,0 @@ -import QtQuick - -QtObject { - id: root - - property var active: null -} diff --git a/modules/controlcenter/state/LauncherState.qml b/modules/controlcenter/state/LauncherState.qml deleted file mode 100644 index 58f5fc8c..00000000 --- a/modules/controlcenter/state/LauncherState.qml +++ /dev/null @@ -1,7 +0,0 @@ -import QtQuick - -QtObject { - id: root - - property var active: null -} diff --git a/modules/controlcenter/state/NetworkState.qml b/modules/controlcenter/state/NetworkState.qml deleted file mode 100644 index f9324c83..00000000 --- a/modules/controlcenter/state/NetworkState.qml +++ /dev/null @@ -1,9 +0,0 @@ -import QtQuick - -QtObject { - id: root - - property var active: null - property bool showPasswordDialog: false - property var pendingNetwork: null -} diff --git a/modules/controlcenter/state/VpnState.qml b/modules/controlcenter/state/VpnState.qml deleted file mode 100644 index aa911f11..00000000 --- a/modules/controlcenter/state/VpnState.qml +++ /dev/null @@ -1,5 +0,0 @@ -import QtQuick - -QtObject { - property var active: null -} diff --git a/modules/controlcenter/taskbar/TaskbarPane.qml b/modules/controlcenter/taskbar/TaskbarPane.qml deleted file mode 100644 index f4ed385d..00000000 --- a/modules/controlcenter/taskbar/TaskbarPane.qml +++ /dev/null @@ -1,792 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "../components" -import QtQuick -import QtQuick.Layouts -import Quickshell -import Quickshell.Widgets -import Caelestia.Config -import qs.components -import qs.components.containers -import qs.components.controls -import qs.components.effects -import qs.services -import qs.utils - -Item { - id: root - - required property Session session - - property bool activeWindowCompact: Config.bar.activeWindow.compact ?? false - property bool activeWindowInverted: Config.bar.activeWindow.inverted ?? false - property bool clockShowIcon: Config.bar.clock.showIcon ?? true - property bool clockBackground: Config.bar.clock.background ?? false - property bool clockShowDate: Config.bar.clock.showDate ?? false - property bool persistent: Config.bar.persistent ?? true - property bool showOnHover: Config.bar.showOnHover ?? true - property int dragThreshold: Config.bar.dragThreshold ?? 20 - property bool showAudio: Config.bar.status.showAudio ?? true - property bool showMicrophone: Config.bar.status.showMicrophone ?? true - property bool showKbLayout: Config.bar.status.showKbLayout ?? false - property bool showNetwork: Config.bar.status.showNetwork ?? true - property bool showWifi: Config.bar.status.showWifi ?? true - property bool showBluetooth: Config.bar.status.showBluetooth ?? true - property bool showBattery: Config.bar.status.showBattery ?? true - property bool showLockStatus: Config.bar.status.showLockStatus ?? true - property bool trayBackground: Config.bar.tray.background ?? false - property bool trayCompact: Config.bar.tray.compact ?? false - property bool trayRecolour: Config.bar.tray.recolour ?? false - property int workspacesShown: Config.bar.workspaces.shown ?? 5 - property bool workspacesActiveIndicator: Config.bar.workspaces.activeIndicator ?? true - property bool workspacesOccupiedBg: Config.bar.workspaces.occupiedBg ?? false - property bool workspacesShowWindows: Config.bar.workspaces.showWindows ?? false - property int workspacesMaxWindowIcons: Config.bar.workspaces.maxWindowIcons ?? 0 - property bool workspacesPerMonitor: GlobalConfig.bar.workspaces.perMonitorWorkspaces ?? true - property bool scrollWorkspaces: Config.bar.scrollActions.workspaces ?? true - property bool scrollVolume: Config.bar.scrollActions.volume ?? true - property bool scrollBrightness: Config.bar.scrollActions.brightness ?? true - property bool popoutActiveWindow: Config.bar.popouts.activeWindow ?? true - property bool popoutTray: Config.bar.popouts.tray ?? true - property bool popoutStatusIcons: Config.bar.popouts.statusIcons ?? true - property list monitorNames: Hypr.monitorNames() - property list excludedScreens: Config.bar.excludedScreens ?? [] - - function saveConfig(entryIndex, entryEnabled) { - GlobalConfig.bar.activeWindow.compact = root.activeWindowCompact; - GlobalConfig.bar.activeWindow.inverted = root.activeWindowInverted; - GlobalConfig.bar.clock.background = root.clockBackground; - GlobalConfig.bar.clock.showDate = root.clockShowDate; - GlobalConfig.bar.clock.showIcon = root.clockShowIcon; - GlobalConfig.bar.persistent = root.persistent; - GlobalConfig.bar.showOnHover = root.showOnHover; - GlobalConfig.bar.dragThreshold = root.dragThreshold; - GlobalConfig.bar.status.showAudio = root.showAudio; - GlobalConfig.bar.status.showMicrophone = root.showMicrophone; - GlobalConfig.bar.status.showKbLayout = root.showKbLayout; - GlobalConfig.bar.status.showNetwork = root.showNetwork; - GlobalConfig.bar.status.showWifi = root.showWifi; - GlobalConfig.bar.status.showBluetooth = root.showBluetooth; - GlobalConfig.bar.status.showBattery = root.showBattery; - GlobalConfig.bar.status.showLockStatus = root.showLockStatus; - GlobalConfig.bar.tray.background = root.trayBackground; - GlobalConfig.bar.tray.compact = root.trayCompact; - GlobalConfig.bar.tray.recolour = root.trayRecolour; - GlobalConfig.bar.workspaces.shown = root.workspacesShown; - GlobalConfig.bar.workspaces.activeIndicator = root.workspacesActiveIndicator; - GlobalConfig.bar.workspaces.occupiedBg = root.workspacesOccupiedBg; - GlobalConfig.bar.workspaces.showWindows = root.workspacesShowWindows; - GlobalConfig.bar.workspaces.maxWindowIcons = root.workspacesMaxWindowIcons; - GlobalConfig.bar.workspaces.perMonitorWorkspaces = root.workspacesPerMonitor; - GlobalConfig.bar.scrollActions.workspaces = root.scrollWorkspaces; - GlobalConfig.bar.scrollActions.volume = root.scrollVolume; - GlobalConfig.bar.scrollActions.brightness = root.scrollBrightness; - GlobalConfig.bar.popouts.activeWindow = root.popoutActiveWindow; - GlobalConfig.bar.popouts.tray = root.popoutTray; - GlobalConfig.bar.popouts.statusIcons = root.popoutStatusIcons; - GlobalConfig.bar.excludedScreens = root.excludedScreens; - - const entries = []; - for (let i = 0; i < entriesModel.count; i++) { - const entry = entriesModel.get(i); - let enabled = entry.enabled; - if (entryIndex !== undefined && i === entryIndex) { - enabled = entryEnabled; - } - entries.push({ - id: entry.id, - enabled: enabled - }); - } - GlobalConfig.bar.entries = entries; - } - - anchors.fill: parent - - Component.onCompleted: { - if (Config.bar.entries) { - entriesModel.clear(); - for (let i = 0; i < Config.bar.entries.length; i++) { - const entry = Config.bar.entries[i]; - entriesModel.append({ - id: entry.id, - enabled: entry.enabled !== false - }); - } - } - } - - ListModel { - id: entriesModel - } - - ClippingRectangle { - id: taskbarClippingRect - - anchors.fill: parent - anchors.margins: Tokens.padding.medium - anchors.leftMargin: 0 - anchors.rightMargin: Tokens.padding.medium - - radius: taskbarBorder.innerRadius - color: "transparent" - - Loader { - id: taskbarLoader - - anchors.fill: parent - anchors.margins: Tokens.padding.large + Tokens.padding.medium - anchors.leftMargin: Tokens.padding.large - anchors.rightMargin: Tokens.padding.large - - asynchronous: true - sourceComponent: taskbarContentComponent - } - } - - InnerBorder { - id: taskbarBorder - - leftThickness: 0 - rightThickness: Tokens.padding.medium - } - - Component { - id: taskbarContentComponent - - StyledFlickable { - id: sidebarFlickable - - flickableDirection: Flickable.VerticalFlick - contentHeight: sidebarLayout.height - - StyledScrollBar.vertical: StyledScrollBar { - flickable: sidebarFlickable - } - - ColumnLayout { - id: sidebarLayout - - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - - spacing: Tokens.spacing.medium - - RowLayout { - spacing: Tokens.spacing.medium - - StyledText { - text: qsTr("Taskbar") - font: Tokens.font.title.builders.medium.weight(Font.Medium).build() - } - } - - SectionContainer { - Layout.fillWidth: true - alignTop: true - - StyledText { - text: qsTr("Status Icons") - font: Tokens.font.title.small - } - - ConnectedButtonGroup { - rootItem: root - - options: [ - { - label: qsTr("Speakers"), - propertyName: "showAudio", - onToggled: function (checked) { - root.showAudio = checked; - root.saveConfig(); - } - }, - { - label: qsTr("Microphone"), - propertyName: "showMicrophone", - onToggled: function (checked) { - root.showMicrophone = checked; - root.saveConfig(); - } - }, - { - label: qsTr("Keyboard"), - propertyName: "showKbLayout", - onToggled: function (checked) { - root.showKbLayout = checked; - root.saveConfig(); - } - }, - { - label: qsTr("Network"), - propertyName: "showNetwork", - onToggled: function (checked) { - root.showNetwork = checked; - root.saveConfig(); - } - }, - { - label: qsTr("Wifi"), - propertyName: "showWifi", - onToggled: function (checked) { - root.showWifi = checked; - root.saveConfig(); - } - }, - { - label: qsTr("Bluetooth"), - propertyName: "showBluetooth", - onToggled: function (checked) { - root.showBluetooth = checked; - root.saveConfig(); - } - }, - { - label: qsTr("Battery"), - propertyName: "showBattery", - onToggled: function (checked) { - root.showBattery = checked; - root.saveConfig(); - } - }, - { - label: qsTr("Capslock"), - propertyName: "showLockStatus", - onToggled: function (checked) { - root.showLockStatus = checked; - root.saveConfig(); - } - } - ] - } - } - - RowLayout { - id: mainRowLayout - - Layout.fillWidth: true - spacing: Tokens.spacing.medium - - ColumnLayout { - id: leftColumnLayout - - Layout.fillWidth: true - Layout.alignment: Qt.AlignTop - spacing: Tokens.spacing.medium - - SectionContainer { - Layout.fillWidth: true - alignTop: true - - StyledText { - text: qsTr("Workspaces") - font: Tokens.font.title.small - } - - StyledRect { - Layout.fillWidth: true - implicitHeight: workspacesShownRow.implicitHeight + Tokens.padding.extraLargeIncreased - radius: Tokens.rounding.large - color: Colours.layer(Colours.palette.m3surfaceContainer, 2) - - Behavior on implicitHeight { - Anim {} - } - - RowLayout { - id: workspacesShownRow - - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - anchors.margins: Tokens.padding.large - spacing: Tokens.spacing.medium - - StyledText { - Layout.fillWidth: true - text: qsTr("Shown") - } - - CustomSpinBox { - min: 1 - max: 20 - value: root.workspacesShown - onValueModified: value => { - root.workspacesShown = value; - root.saveConfig(); - } - } - } - } - - StyledRect { - Layout.fillWidth: true - implicitHeight: workspacesActiveIndicatorRow.implicitHeight + Tokens.padding.extraLargeIncreased - radius: Tokens.rounding.large - color: Colours.layer(Colours.palette.m3surfaceContainer, 2) - - Behavior on implicitHeight { - Anim {} - } - - RowLayout { - id: workspacesActiveIndicatorRow - - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - anchors.margins: Tokens.padding.large - spacing: Tokens.spacing.medium - - StyledText { - Layout.fillWidth: true - text: qsTr("Active indicator") - } - - StyledSwitch { - checked: root.workspacesActiveIndicator - onToggled: { - root.workspacesActiveIndicator = checked; - root.saveConfig(); - } - } - } - } - - StyledRect { - Layout.fillWidth: true - implicitHeight: workspacesOccupiedBgRow.implicitHeight + Tokens.padding.extraLargeIncreased - radius: Tokens.rounding.large - color: Colours.layer(Colours.palette.m3surfaceContainer, 2) - - Behavior on implicitHeight { - Anim {} - } - - RowLayout { - id: workspacesOccupiedBgRow - - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - anchors.margins: Tokens.padding.large - spacing: Tokens.spacing.medium - - StyledText { - Layout.fillWidth: true - text: qsTr("Occupied background") - } - - StyledSwitch { - checked: root.workspacesOccupiedBg - onToggled: { - root.workspacesOccupiedBg = checked; - root.saveConfig(); - } - } - } - } - - StyledRect { - Layout.fillWidth: true - implicitHeight: workspacesShowWindowsRow.implicitHeight + Tokens.padding.extraLargeIncreased - radius: Tokens.rounding.large - color: Colours.layer(Colours.palette.m3surfaceContainer, 2) - - Behavior on implicitHeight { - Anim {} - } - - RowLayout { - id: workspacesShowWindowsRow - - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - anchors.margins: Tokens.padding.large - spacing: Tokens.spacing.medium - - StyledText { - Layout.fillWidth: true - text: qsTr("Show windows") - } - - StyledSwitch { - checked: root.workspacesShowWindows - onToggled: { - root.workspacesShowWindows = checked; - root.saveConfig(); - } - } - } - } - - StyledRect { - Layout.fillWidth: true - implicitHeight: workspacesMaxWindowIconsRow.implicitHeight + Tokens.padding.extraLargeIncreased - radius: Tokens.rounding.large - color: Colours.layer(Colours.palette.m3surfaceContainer, 2) - - Behavior on implicitHeight { - Anim {} - } - - RowLayout { - id: workspacesMaxWindowIconsRow - - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - anchors.margins: Tokens.padding.large - spacing: Tokens.spacing.medium - - StyledText { - Layout.fillWidth: true - text: qsTr("Max window icons") - } - - CustomSpinBox { - min: 0 - max: 20 - value: root.workspacesMaxWindowIcons - onValueModified: value => { - root.workspacesMaxWindowIcons = value; - root.saveConfig(); - } - } - } - } - - StyledRect { - Layout.fillWidth: true - implicitHeight: workspacesPerMonitorRow.implicitHeight + Tokens.padding.extraLargeIncreased - radius: Tokens.rounding.large - color: Colours.layer(Colours.palette.m3surfaceContainer, 2) - - Behavior on implicitHeight { - Anim {} - } - - RowLayout { - id: workspacesPerMonitorRow - - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - anchors.margins: Tokens.padding.large - spacing: Tokens.spacing.medium - - StyledText { - Layout.fillWidth: true - text: qsTr("Per monitor workspaces") - } - - StyledSwitch { - checked: root.workspacesPerMonitor - onToggled: { - root.workspacesPerMonitor = checked; - root.saveConfig(); - } - } - } - } - } - - SectionContainer { - Layout.fillWidth: true - alignTop: true - - StyledText { - text: qsTr("Scroll Actions") - font: Tokens.font.title.small - } - - ConnectedButtonGroup { - rootItem: root - - options: [ - { - label: qsTr("Workspaces"), - propertyName: "scrollWorkspaces", - onToggled: function (checked) { - root.scrollWorkspaces = checked; - root.saveConfig(); - } - }, - { - label: qsTr("Volume"), - propertyName: "scrollVolume", - onToggled: function (checked) { - root.scrollVolume = checked; - root.saveConfig(); - } - }, - { - label: qsTr("Brightness"), - propertyName: "scrollBrightness", - onToggled: function (checked) { - root.scrollBrightness = checked; - root.saveConfig(); - } - } - ] - } - } - } - - ColumnLayout { - id: middleColumnLayout - - Layout.fillWidth: true - Layout.alignment: Qt.AlignTop - spacing: Tokens.spacing.medium - - SectionContainer { - Layout.fillWidth: true - alignTop: true - - StyledText { - text: qsTr("Clock") - font: Tokens.font.title.small - } - - SwitchRow { - label: qsTr("Background") - checked: root.clockBackground - onToggled: checked => { - root.clockBackground = checked; - root.saveConfig(); - } - } - - SwitchRow { - label: qsTr("Show date") - checked: root.clockShowDate - onToggled: checked => { - root.clockShowDate = checked; - root.saveConfig(); - } - } - - SwitchRow { - label: qsTr("Show clock icon") - checked: root.clockShowIcon - onToggled: checked => { - root.clockShowIcon = checked; - root.saveConfig(); - } - } - } - - SectionContainer { - Layout.fillWidth: true - alignTop: true - - StyledText { - text: qsTr("Bar Behavior") - font: Tokens.font.title.small - } - - SwitchRow { - label: qsTr("Persistent") - checked: root.persistent - onToggled: checked => { - root.persistent = checked; - root.saveConfig(); - } - } - - SwitchRow { - label: qsTr("Show on hover") - checked: root.showOnHover - onToggled: checked => { - root.showOnHover = checked; - root.saveConfig(); - } - } - - SectionContainer { - contentSpacing: Tokens.spacing.medium - - SliderInput { - Layout.fillWidth: true - - label: qsTr("Drag threshold") - value: root.dragThreshold - from: 0 - to: 100 - suffix: "px" - validator: IntValidator { - bottom: 0 - top: 100 - } - formatValueFunction: val => Math.round(val).toString() - parseValueFunction: text => parseInt(text) - - onValueModified: newValue => { - root.dragThreshold = Math.round(newValue); - root.saveConfig(); - } - } - } - } - - SectionContainer { - Layout.fillWidth: true - alignTop: true - - StyledText { - text: qsTr("Active window") - font: Tokens.font.title.small - } - - SwitchRow { - label: qsTr("Compact") - checked: root.activeWindowCompact - onToggled: checked => { - root.activeWindowCompact = checked; - root.saveConfig(); - } - } - - SwitchRow { - label: qsTr("Inverted") - checked: root.activeWindowInverted - onToggled: checked => { - root.activeWindowInverted = checked; - root.saveConfig(); - } - } - } - } - - ColumnLayout { - id: rightColumnLayout - - Layout.fillWidth: true - Layout.alignment: Qt.AlignTop - spacing: Tokens.spacing.medium - - SectionContainer { - Layout.fillWidth: true - alignTop: true - - StyledText { - text: qsTr("Popouts") - font: Tokens.font.title.small - } - - SwitchRow { - label: qsTr("Active window") - checked: root.popoutActiveWindow - onToggled: checked => { - root.popoutActiveWindow = checked; - root.saveConfig(); - } - } - - SwitchRow { - label: qsTr("Tray") - checked: root.popoutTray - onToggled: checked => { - root.popoutTray = checked; - root.saveConfig(); - } - } - - SwitchRow { - label: qsTr("Status icons") - checked: root.popoutStatusIcons - onToggled: checked => { - root.popoutStatusIcons = checked; - root.saveConfig(); - } - } - } - - SectionContainer { - Layout.fillWidth: true - alignTop: true - - StyledText { - text: qsTr("Tray Settings") - font: Tokens.font.title.small - } - - ConnectedButtonGroup { - rootItem: root - - options: [ - { - label: qsTr("Background"), - propertyName: "trayBackground", - onToggled: function (checked) { - root.trayBackground = checked; - root.saveConfig(); - } - }, - { - label: qsTr("Compact"), - propertyName: "trayCompact", - onToggled: function (checked) { - root.trayCompact = checked; - root.saveConfig(); - } - }, - { - label: qsTr("Recolour"), - propertyName: "trayRecolour", - onToggled: function (checked) { - root.trayRecolour = checked; - root.saveConfig(); - } - } - ] - } - } - - SectionContainer { - Layout.fillWidth: true - alignTop: true - - StyledText { - text: qsTr("Monitors") - font: Tokens.font.title.small - } - - ConnectedButtonGroup { - rootItem: root - // max 3 options per line - rows: Math.ceil(root.monitorNames.length / 3) - - options: root.monitorNames.map(e => ({ - label: qsTr(e), - propertyName: `monitor${e}`, - onToggled: function (_) { - // if the given monitor is in the excluded list, it should be added back - let addedBack = excludedScreens.includes(e); - if (addedBack) { - const index = excludedScreens.indexOf(e); - if (index !== -1) { - excludedScreens.splice(index, 1); - } - } else { - if (!excludedScreens.includes(e)) { - excludedScreens.push(e); - } - } - root.saveConfig(); - }, - state: !Strings.testRegexList(root.excludedScreens, e) - })) - } - } - } - } - } - } - } -} diff --git a/plugin/src/Caelestia/Config/CMakeLists.txt b/plugin/src/Caelestia/Config/CMakeLists.txt index 75593177..15e4b7c2 100644 --- a/plugin/src/Caelestia/Config/CMakeLists.txt +++ b/plugin/src/Caelestia/Config/CMakeLists.txt @@ -15,7 +15,6 @@ qml_module(caelestia-config backgroundconfig.hpp barconfig.hpp borderconfig.hpp - controlcenterconfig.hpp dashboardconfig.hpp generalconfig.hpp launcherconfig.hpp diff --git a/plugin/src/Caelestia/Config/config.cpp b/plugin/src/Caelestia/Config/config.cpp index 6e15f1d2..b09ddb83 100644 --- a/plugin/src/Caelestia/Config/config.cpp +++ b/plugin/src/Caelestia/Config/config.cpp @@ -3,7 +3,6 @@ #include "backgroundconfig.hpp" #include "barconfig.hpp" #include "borderconfig.hpp" -#include "controlcenterconfig.hpp" #include "dashboardconfig.hpp" #include "generalconfig.hpp" #include "launcherconfig.hpp" @@ -41,7 +40,6 @@ GlobalConfig::GlobalConfig(QObject* parent) , m_bar(new BarConfig(this)) , m_border(new BorderConfig(this)) , m_dashboard(new DashboardConfig(this)) - , m_controlCenter(new ControlCenterConfig(this)) , m_launcher(new LauncherConfig(this)) , m_lock(new LockConfig(this)) , m_nexus(new NexusConfig(this)) @@ -64,7 +62,6 @@ GlobalConfig::GlobalConfig(GlobalConfig* fallback, const QString& filePath, cons , m_bar(new BarConfig(this)) , m_border(new BorderConfig(this)) , m_dashboard(new DashboardConfig(this)) - , m_controlCenter(new ControlCenterConfig(this)) , m_launcher(new LauncherConfig(this)) , m_lock(new LockConfig(this)) , m_nexus(new NexusConfig(this)) diff --git a/plugin/src/Caelestia/Config/config.hpp b/plugin/src/Caelestia/Config/config.hpp index 5b5cd9a0..1418e980 100644 --- a/plugin/src/Caelestia/Config/config.hpp +++ b/plugin/src/Caelestia/Config/config.hpp @@ -10,7 +10,6 @@ class AppearanceConfig; class BackgroundConfig; class BarConfig; class BorderConfig; -class ControlCenterConfig; class DashboardConfig; class GeneralConfig; class LauncherConfig; @@ -33,7 +32,6 @@ class GlobalConfig : public RootConfig { Q_MOC_INCLUDE("backgroundconfig.hpp") Q_MOC_INCLUDE("barconfig.hpp") Q_MOC_INCLUDE("borderconfig.hpp") - Q_MOC_INCLUDE("controlcenterconfig.hpp") Q_MOC_INCLUDE("dashboardconfig.hpp") Q_MOC_INCLUDE("generalconfig.hpp") Q_MOC_INCLUDE("launcherconfig.hpp") @@ -55,7 +53,6 @@ class GlobalConfig : public RootConfig { CONFIG_SUBOBJECT(BarConfig, bar) CONFIG_SUBOBJECT(BorderConfig, border) CONFIG_SUBOBJECT(DashboardConfig, dashboard) - CONFIG_SUBOBJECT(ControlCenterConfig, controlCenter) CONFIG_SUBOBJECT(LauncherConfig, launcher) CONFIG_SUBOBJECT(LockConfig, lock) CONFIG_SUBOBJECT(NexusConfig, nexus) diff --git a/plugin/src/Caelestia/Config/configattached.cpp b/plugin/src/Caelestia/Config/configattached.cpp index b5420b69..38901470 100644 --- a/plugin/src/Caelestia/Config/configattached.cpp +++ b/plugin/src/Caelestia/Config/configattached.cpp @@ -71,7 +71,6 @@ CONFIG_ATTACHED_GETTER(BackgroundConfig, background) CONFIG_ATTACHED_GETTER(BarConfig, bar) CONFIG_ATTACHED_GETTER(BorderConfig, border) CONFIG_ATTACHED_GETTER(DashboardConfig, dashboard) -CONFIG_ATTACHED_GETTER(ControlCenterConfig, controlCenter) CONFIG_ATTACHED_GETTER(LauncherConfig, launcher) CONFIG_ATTACHED_GETTER(LockConfig, lock) CONFIG_ATTACHED_GETTER(NexusConfig, nexus) diff --git a/plugin/src/Caelestia/Config/configattached.hpp b/plugin/src/Caelestia/Config/configattached.hpp index 19054bde..13f3bf6c 100644 --- a/plugin/src/Caelestia/Config/configattached.hpp +++ b/plugin/src/Caelestia/Config/configattached.hpp @@ -16,7 +16,6 @@ class Config : public QQuickAttachedPropertyPropagator, public QQmlParserStatus Q_MOC_INCLUDE("backgroundconfig.hpp") Q_MOC_INCLUDE("barconfig.hpp") Q_MOC_INCLUDE("borderconfig.hpp") - Q_MOC_INCLUDE("controlcenterconfig.hpp") Q_MOC_INCLUDE("dashboardconfig.hpp") Q_MOC_INCLUDE("generalconfig.hpp") Q_MOC_INCLUDE("launcherconfig.hpp") @@ -38,7 +37,6 @@ class Config : public QQuickAttachedPropertyPropagator, public QQmlParserStatus Q_PROPERTY(const caelestia::config::BarConfig* bar READ bar NOTIFY sourceChanged) Q_PROPERTY(const caelestia::config::BorderConfig* border READ border NOTIFY sourceChanged) Q_PROPERTY(const caelestia::config::DashboardConfig* dashboard READ dashboard NOTIFY sourceChanged) - Q_PROPERTY(const caelestia::config::ControlCenterConfig* controlCenter READ controlCenter NOTIFY sourceChanged) Q_PROPERTY(const caelestia::config::LauncherConfig* launcher READ launcher NOTIFY sourceChanged) Q_PROPERTY(const caelestia::config::LockConfig* lock READ lock NOTIFY sourceChanged) Q_PROPERTY(const caelestia::config::NexusConfig* nexus READ nexus NOTIFY sourceChanged) @@ -63,7 +61,6 @@ public: [[nodiscard]] const BarConfig* bar() const; [[nodiscard]] const BorderConfig* border() const; [[nodiscard]] const DashboardConfig* dashboard() const; - [[nodiscard]] const ControlCenterConfig* controlCenter() const; [[nodiscard]] const LauncherConfig* launcher() const; [[nodiscard]] const LockConfig* lock() const; [[nodiscard]] const NexusConfig* nexus() const; diff --git a/plugin/src/Caelestia/Config/launcherconfig.hpp b/plugin/src/Caelestia/Config/launcherconfig.hpp index 049e213a..49764599 100644 --- a/plugin/src/Caelestia/Config/launcherconfig.hpp +++ b/plugin/src/Caelestia/Config/launcherconfig.hpp @@ -122,7 +122,7 @@ class LauncherConfig : public ConfigObject { { u"name"_s, u"Settings"_s }, { u"icon"_s, u"settings"_s }, { u"description"_s, u"Configure the shell"_s }, - { u"command"_s, QStringList{ u"caelestia"_s, u"shell"_s, u"controlCenter"_s, u"open"_s } }, + { u"command"_s, QStringList{ u"caelestia"_s, u"shell"_s, u"nexus"_s, u"open"_s } }, }), }) diff --git a/plugin/src/Caelestia/Config/tokens.hpp b/plugin/src/Caelestia/Config/tokens.hpp index 3d0267f4..83218c65 100644 --- a/plugin/src/Caelestia/Config/tokens.hpp +++ b/plugin/src/Caelestia/Config/tokens.hpp @@ -311,18 +311,6 @@ public: : ConfigObject(parent) {} }; -class ControlCenterTokens : public ConfigObject { - Q_OBJECT - QML_ANONYMOUS - - CONFIG_PROPERTY(qreal, heightMult, 0.7) - CONFIG_PROPERTY(qreal, ratio, 16.0 / 9.0) - -public: - explicit ControlCenterTokens(QObject* parent = nullptr) - : ConfigObject(parent) {} -}; - class NexusTokens : public ConfigObject { Q_OBJECT QML_ANONYMOUS @@ -352,7 +340,6 @@ class SizeTokens : public ConfigObject { CONFIG_SUBOBJECT(UtilitiesTokens, utilities) CONFIG_SUBOBJECT(LockTokens, lock) CONFIG_SUBOBJECT(WInfoTokens, winfo) - CONFIG_SUBOBJECT(ControlCenterTokens, controlCenter) CONFIG_SUBOBJECT(NexusTokens, nexus) public: @@ -368,7 +355,6 @@ public: , m_utilities(new UtilitiesTokens(this)) , m_lock(new LockTokens(this)) , m_winfo(new WInfoTokens(this)) - , m_controlCenter(new ControlCenterTokens(this)) , m_nexus(new NexusTokens(this)) {} };