summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/areapicker/Picker.qml300
-rw-r--r--modules/background/DesktopClock.qml169
-rw-r--r--modules/background/Visualiser.qml151
-rw-r--r--modules/background/Wallpaper.qml111
-rw-r--r--modules/bar/components/workspaces/SpecialWorkspaces.qml359
-rw-r--r--modules/controlcenter/appearance/AppearancePane.qml259
-rw-r--r--modules/controlcenter/appearance/sections/BackgroundSection.qml297
-rw-r--r--modules/controlcenter/appearance/sections/ColorSchemeSection.qml146
-rw-r--r--modules/controlcenter/appearance/sections/FontsSection.qml280
-rw-r--r--modules/controlcenter/launcher/LauncherPane.qml597
-rw-r--r--modules/controlcenter/network/NetworkSettings.qml72
-rw-r--r--modules/controlcenter/network/NetworkingPane.qml69
-rw-r--r--modules/controlcenter/network/VpnDetails.qml367
-rw-r--r--modules/controlcenter/network/VpnList.qml646
-rw-r--r--modules/controlcenter/network/VpnSettings.qml232
-rw-r--r--modules/controlcenter/state/VpnState.qml5
-rw-r--r--modules/controlcenter/taskbar/TaskbarPane.qml646
-rw-r--r--modules/launcher/items/SchemeItem.qml104
-rw-r--r--modules/launcher/items/VariantItem.qml80
-rw-r--r--modules/launcher/services/Apps.qml2
-rw-r--r--modules/lock/Center.qml415
-rw-r--r--modules/lock/Fetch.qml165
-rw-r--r--modules/lock/NotifDock.qml145
-rw-r--r--modules/lock/NotifGroup.qml316
-rw-r--r--modules/lock/WeatherInfo.qml176
-rw-r--r--modules/utilities/RecordingDeleteModal.qml207
-rw-r--r--modules/utilities/cards/RecordingList.qml241
27 files changed, 6 insertions, 6551 deletions
diff --git a/modules/areapicker/Picker.qml b/modules/areapicker/Picker.qml
deleted file mode 100644
index 35b35a2..0000000
--- a/modules/areapicker/Picker.qml
+++ /dev/null
@@ -1,300 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.components
-import qs.services
-import qs.config
-import Caelestia
-import Quickshell
-import Quickshell.Wayland
-import QtQuick
-import QtQuick.Effects
-
-MouseArea {
- id: root
-
- required property LazyLoader loader
- required property ShellScreen screen
-
- property bool onClient
-
- property real realBorderWidth: onClient ? (Hypr.options["general:border_size"] ?? 1) : 2
- property real realRounding: onClient ? (Hypr.options["decoration:rounding"] ?? 0) : 0
-
- property real ssx
- property real ssy
-
- property real sx: 0
- property real sy: 0
- property real ex: screen.width
- property real ey: screen.height
-
- property real rsx: Math.min(sx, ex)
- property real rsy: Math.min(sy, ey)
- property real sw: Math.abs(sx - ex)
- property real sh: Math.abs(sy - ey)
-
- property list<var> clients: {
- const mon = Hypr.monitorFor(screen);
- if (!mon)
- return [];
-
- const special = mon.lastIpcObject.specialWorkspace;
- const wsId = special.name ? special.id : mon.activeWorkspace.id;
-
- return Hypr.toplevels.values.filter(c => c.workspace?.id === wsId).sort((a, b) => {
- // Pinned first, then fullscreen, then floating, then any other
- const ac = a.lastIpcObject;
- const bc = b.lastIpcObject;
- return (bc.pinned - ac.pinned) || ((bc.fullscreen !== 0) - (ac.fullscreen !== 0)) || (bc.floating - ac.floating);
- });
- }
-
- function checkClientRects(x: real, y: real): void {
- for (const client of clients) {
- if (!client)
- continue;
-
- let {
- at: [cx, cy],
- size: [cw, ch]
- } = client.lastIpcObject;
- cx -= screen.x;
- cy -= screen.y;
- if (cx <= x && cy <= y && cx + cw >= x && cy + ch >= y) {
- onClient = true;
- sx = cx;
- sy = cy;
- ex = cx + cw;
- ey = cy + ch;
- break;
- }
- }
- }
-
- function save(): void {
- const tmpfile = Qt.resolvedUrl(`/tmp/caelestia-picker-${Quickshell.processId}-${Date.now()}.png`);
- CUtils.saveItem(screencopy, tmpfile, Qt.rect(Math.ceil(rsx), Math.ceil(rsy), Math.floor(sw), Math.floor(sh)), path => {
- if (root.loader.clipboardOnly) {
- Quickshell.execDetached(["sh", "-c", "wl-copy --type image/png < " + path]);
- Quickshell.execDetached(["notify-send", "-a", "caelestia-cli", "-i", path, "Screenshot taken", "Screenshot copied to clipboard"]);
- } else {
- Quickshell.execDetached(["swappy", "-f", path]);
- }
- });
- closeAnim.start();
- }
-
- onClientsChanged: checkClientRects(mouseX, mouseY)
-
- anchors.fill: parent
- opacity: 0
- hoverEnabled: true
- cursorShape: Qt.CrossCursor
-
- Component.onCompleted: {
- Hypr.extras.refreshOptions();
-
- // Break binding if frozen
- if (loader.freeze)
- clients = clients;
-
- opacity = 1;
-
- const c = clients[0];
- if (c) {
- const cx = c.lastIpcObject.at[0] - screen.x;
- const cy = c.lastIpcObject.at[1] - screen.y;
- onClient = true;
- sx = cx;
- sy = cy;
- ex = cx + c.lastIpcObject.size[0];
- ey = cy + c.lastIpcObject.size[1];
- } else {
- sx = screen.width / 2 - 100;
- sy = screen.height / 2 - 100;
- ex = screen.width / 2 + 100;
- ey = screen.height / 2 + 100;
- }
- }
-
- onPressed: event => {
- ssx = event.x;
- ssy = event.y;
- }
-
- onReleased: {
- if (closeAnim.running)
- return;
-
- if (root.loader.freeze) {
- save();
- } else {
- overlay.visible = border.visible = false;
- screencopy.visible = false;
- screencopy.active = true;
- }
- }
-
- onPositionChanged: event => {
- const x = event.x;
- const y = event.y;
-
- if (pressed) {
- onClient = false;
- sx = ssx;
- sy = ssy;
- ex = x;
- ey = y;
- } else {
- checkClientRects(x, y);
- }
- }
-
- focus: true
- Keys.onEscapePressed: closeAnim.start()
-
- SequentialAnimation {
- id: closeAnim
-
- PropertyAction {
- target: root.loader
- property: "closing"
- value: true
- }
- ParallelAnimation {
- Anim {
- target: root
- property: "opacity"
- to: 0
- duration: Appearance.anim.durations.large
- }
- ExAnim {
- target: root
- properties: "rsx,rsy"
- to: 0
- }
- ExAnim {
- target: root
- property: "sw"
- to: root.screen.width
- }
- ExAnim {
- target: root
- property: "sh"
- to: root.screen.height
- }
- }
- PropertyAction {
- target: root.loader
- property: "activeAsync"
- value: false
- }
- }
-
- Loader {
- id: screencopy
-
- anchors.fill: parent
-
- active: root.loader.freeze
-
- sourceComponent: ScreencopyView {
- captureSource: root.screen
-
- onHasContentChanged: {
- if (hasContent && !root.loader.freeze) {
- overlay.visible = border.visible = true;
- root.save();
- }
- }
- }
- }
-
- StyledRect {
- id: overlay
-
- anchors.fill: parent
- color: Colours.palette.m3secondaryContainer
- opacity: 0.3
-
- layer.enabled: true
- layer.effect: MultiEffect {
- maskSource: selectionWrapper
- maskEnabled: true
- maskInverted: true
- maskSpreadAtMin: 1
- maskThresholdMin: 0.5
- }
- }
-
- Item {
- id: selectionWrapper
-
- anchors.fill: parent
- layer.enabled: true
- visible: false
-
- Rectangle {
- id: selectionRect
-
- radius: root.realRounding
- x: root.rsx
- y: root.rsy
- implicitWidth: root.sw
- implicitHeight: root.sh
- }
- }
-
- Rectangle {
- id: border
-
- color: "transparent"
- radius: root.realRounding > 0 ? root.realRounding + root.realBorderWidth : 0
- border.width: root.realBorderWidth
- border.color: Colours.palette.m3primary
-
- x: selectionRect.x - root.realBorderWidth
- y: selectionRect.y - root.realBorderWidth
- implicitWidth: selectionRect.implicitWidth + root.realBorderWidth * 2
- implicitHeight: selectionRect.implicitHeight + root.realBorderWidth * 2
-
- Behavior on border.color {
- CAnim {}
- }
- }
-
- Behavior on opacity {
- Anim {
- duration: Appearance.anim.durations.large
- }
- }
-
- Behavior on rsx {
- enabled: !root.pressed
-
- ExAnim {}
- }
-
- Behavior on rsy {
- enabled: !root.pressed
-
- ExAnim {}
- }
-
- Behavior on sw {
- enabled: !root.pressed
-
- ExAnim {}
- }
-
- Behavior on sh {
- enabled: !root.pressed
-
- ExAnim {}
- }
-
- component ExAnim: Anim {
- duration: Appearance.anim.durations.expressiveDefaultSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
- }
-}
diff --git a/modules/background/DesktopClock.qml b/modules/background/DesktopClock.qml
deleted file mode 100644
index 77fe447..0000000
--- a/modules/background/DesktopClock.qml
+++ /dev/null
@@ -1,169 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.components
-import qs.services
-import qs.config
-import QtQuick
-import QtQuick.Layouts
-import QtQuick.Effects
-
-Item {
- id: root
-
- required property Item wallpaper
- required property real absX
- required property real absY
-
- property real scale: Config.background.desktopClock.scale
- readonly property bool bgEnabled: Config.background.desktopClock.background.enabled
- readonly property bool blurEnabled: bgEnabled && Config.background.desktopClock.background.blur
- readonly property bool invertColors: Config.background.desktopClock.invertColors
- readonly property bool useLightSet: Colours.light ? !invertColors : invertColors
- readonly property color safePrimary: useLightSet ? Colours.palette.m3primaryContainer : Colours.palette.m3primary
- readonly property color safeSecondary: useLightSet ? Colours.palette.m3secondaryContainer : Colours.palette.m3secondary
- readonly property color safeTertiary: useLightSet ? Colours.palette.m3tertiaryContainer : Colours.palette.m3tertiary
-
- implicitWidth: layout.implicitWidth + (Appearance.padding.large * 4 * root.scale)
- implicitHeight: layout.implicitHeight + (Appearance.padding.large * 2 * root.scale)
-
- Item {
- id: clockContainer
-
- anchors.fill: parent
-
- layer.enabled: Config.background.desktopClock.shadow.enabled
- layer.effect: MultiEffect {
- shadowEnabled: true
- shadowColor: Colours.palette.m3shadow
- shadowOpacity: Config.background.desktopClock.shadow.opacity
- shadowBlur: Config.background.desktopClock.shadow.blur
- }
-
- Loader {
- anchors.fill: parent
- active: root.blurEnabled
-
- sourceComponent: MultiEffect {
- source: ShaderEffectSource {
- sourceItem: root.wallpaper
- sourceRect: Qt.rect(root.absX, root.absY, root.width, root.height)
- }
- maskSource: backgroundPlate
- maskEnabled: true
- blurEnabled: true
- blur: 1
- blurMax: 64
- autoPaddingEnabled: false
- }
- }
-
- StyledRect {
- id: backgroundPlate
-
- visible: root.bgEnabled
- anchors.fill: parent
- radius: Appearance.rounding.large * root.scale
- opacity: Config.background.desktopClock.background.opacity
- color: Colours.palette.m3surface
-
- layer.enabled: root.blurEnabled
- }
-
- RowLayout {
- id: layout
-
- anchors.centerIn: parent
- spacing: Appearance.spacing.larger * root.scale
-
- RowLayout {
- spacing: Appearance.spacing.small
-
- StyledText {
- text: Time.hourStr
- font.pointSize: Appearance.font.size.extraLarge * 3 * root.scale
- font.weight: Font.Bold
- color: root.safePrimary
- }
-
- StyledText {
- text: ":"
- font.pointSize: Appearance.font.size.extraLarge * 3 * root.scale
- color: root.safeTertiary
- opacity: 0.8
- Layout.topMargin: -Appearance.padding.large * 1.5 * root.scale
- }
-
- StyledText {
- text: Time.minuteStr
- font.pointSize: Appearance.font.size.extraLarge * 3 * root.scale
- font.weight: Font.Bold
- color: root.safeSecondary
- }
-
- Loader {
- Layout.alignment: Qt.AlignTop
- Layout.topMargin: Appearance.padding.large * 1.4 * root.scale
-
- active: Config.services.useTwelveHourClock
- visible: active
-
- sourceComponent: StyledText {
- text: Time.amPmStr
- font.pointSize: Appearance.font.size.large * root.scale
- color: root.safeSecondary
- }
- }
- }
-
- StyledRect {
- Layout.fillHeight: true
- Layout.preferredWidth: 4 * root.scale
- Layout.topMargin: Appearance.spacing.larger * root.scale
- Layout.bottomMargin: Appearance.spacing.larger * root.scale
- radius: Appearance.rounding.full
- color: root.safePrimary
- opacity: 0.8
- }
-
- ColumnLayout {
- spacing: 0
-
- StyledText {
- text: Time.format("MMMM").toUpperCase()
- font.pointSize: Appearance.font.size.large * root.scale
- font.letterSpacing: 4
- font.weight: Font.Bold
- color: root.safeSecondary
- }
-
- StyledText {
- text: Time.format("dd")
- font.pointSize: Appearance.font.size.extraLarge * root.scale
- font.letterSpacing: 2
- font.weight: Font.Medium
- color: root.safePrimary
- }
-
- StyledText {
- text: Time.format("dddd")
- font.pointSize: Appearance.font.size.larger * root.scale
- font.letterSpacing: 2
- color: root.safeSecondary
- }
- }
- }
- }
-
- Behavior on scale {
- Anim {
- duration: Appearance.anim.durations.expressiveDefaultSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
- }
- }
-
- Behavior on implicitWidth {
- Anim {
- duration: Appearance.anim.durations.small
- }
- }
-}
diff --git a/modules/background/Visualiser.qml b/modules/background/Visualiser.qml
deleted file mode 100644
index c9bb9ef..0000000
--- a/modules/background/Visualiser.qml
+++ /dev/null
@@ -1,151 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.components
-import qs.services
-import qs.config
-import Caelestia.Services
-import Quickshell
-import Quickshell.Widgets
-import QtQuick
-import QtQuick.Effects
-
-Item {
- id: root
-
- required property ShellScreen screen
- required property Wallpaper wallpaper
-
- readonly property bool shouldBeActive: Config.background.visualiser.enabled && (!Config.background.visualiser.autoHide || (Hypr.monitorFor(screen)?.activeWorkspace?.toplevels?.values.every(t => t.lastIpcObject?.floating) ?? true))
- property real offset: shouldBeActive ? 0 : screen.height * 0.2
-
- opacity: shouldBeActive ? 1 : 0
-
- Loader {
- anchors.fill: parent
- active: root.opacity > 0 && Config.background.visualiser.blur
-
- sourceComponent: MultiEffect {
- source: root.wallpaper
- maskSource: wrapper
- maskEnabled: true
- blurEnabled: true
- blur: 1
- blurMax: 32
- autoPaddingEnabled: false
- }
- }
-
- Item {
- id: wrapper
-
- anchors.fill: parent
- layer.enabled: true
-
- Loader {
- anchors.fill: parent
- anchors.topMargin: root.offset
- anchors.bottomMargin: -root.offset
-
- active: root.opacity > 0
-
- sourceComponent: Item {
- ServiceRef {
- service: Audio.cava
- }
-
- Item {
- id: content
-
- anchors.fill: parent
- anchors.margins: Config.border.thickness
- anchors.leftMargin: Visibilities.bars.get(root.screen).exclusiveZone + Appearance.spacing.small * Config.background.visualiser.spacing
-
- Side {
- content: content
- }
- Side {
- content: content
- isRight: true
- }
-
- Behavior on anchors.leftMargin {
- Anim {}
- }
- }
- }
- }
- }
-
- Behavior on offset {
- Anim {}
- }
-
- Behavior on opacity {
- Anim {}
- }
-
- component Side: Repeater {
- id: side
-
- required property Item content
- property bool isRight
-
- model: Config.services.visualiserBars
-
- ClippingRectangle {
- id: bar
-
- required property int modelData
- property real value: Math.max(0, Math.min(1, Audio.cava.values[side.isRight ? modelData : side.count - modelData - 1]))
-
- clip: true
-
- x: modelData * ((side.content.width * 0.4) / Config.services.visualiserBars) + (side.isRight ? side.content.width * 0.6 : 0)
- implicitWidth: (side.content.width * 0.4) / Config.services.visualiserBars - Appearance.spacing.small * Config.background.visualiser.spacing
-
- y: side.content.height - height
- implicitHeight: bar.value * side.content.height * 0.4
-
- color: "transparent"
- topLeftRadius: Appearance.rounding.small * Config.background.visualiser.rounding
- topRightRadius: Appearance.rounding.small * Config.background.visualiser.rounding
-
- Rectangle {
- topLeftRadius: parent.topLeftRadius
- topRightRadius: parent.topRightRadius
-
- gradient: Gradient {
- orientation: Gradient.Vertical
-
- GradientStop {
- position: 0
- color: Qt.alpha(Colours.palette.m3primary, 0.7)
-
- Behavior on color {
- CAnim {}
- }
- }
- GradientStop {
- position: 1
- color: Qt.alpha(Colours.palette.m3inversePrimary, 0.7)
-
- Behavior on color {
- CAnim {}
- }
- }
- }
-
- anchors.left: parent.left
- anchors.right: parent.right
- y: parent.height - height
- implicitHeight: side.content.height * 0.4
- }
-
- Behavior on value {
- Anim {
- duration: Appearance.anim.durations.small
- }
- }
- }
- }
-}
diff --git a/modules/background/Wallpaper.qml b/modules/background/Wallpaper.qml
deleted file mode 100644
index 9b91530..0000000
--- a/modules/background/Wallpaper.qml
+++ /dev/null
@@ -1,111 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.components
-import qs.components.images
-import qs.components.filedialog
-import qs.services
-import qs.config
-import qs.utils
-import QtQuick
-
-Item {
- id: root
-
- property string source: Paths.wallpaper
- property Image current: one
-
- anchors.fill: parent
-
- onSourceChanged: {
- if (!source)
- current = null;
- else if (current === one)
- two.update();
- else
- one.update();
- }
-
- Component.onCompleted: {
- if (source)
- Qt.callLater(() => one.update());
- }
-
- Loader {
- anchors.fill: parent
-
- active: !root.source
-
- sourceComponent: StyledRect {
- color: Colours.palette.m3surfaceContainer
-
- Row {
- anchors.centerIn: parent
- spacing: Appearance.spacing.large
-
- MaterialIcon {
- text: "sentiment_stressed"
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: Appearance.font.size.extraLarge * 5
- }
-
- Column {
- anchors.verticalCenter: parent.verticalCenter
- spacing: Appearance.spacing.small
-
- StyledText {
- text: qsTr("Wallpaper missing?")
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: Appearance.font.size.extraLarge * 2
- font.bold: true
- }
- }
- }
- }
- }
-
- Img {
- id: one
- }
-
- Img {
- id: two
- }
-
- component Img: CachingImage {
- id: img
-
- function update(): void {
- if (path === root.source)
- root.current = this;
- else
- path = root.source;
- }
-
- anchors.fill: parent
-
- opacity: 0
- scale: 0.8
-
- onStatusChanged: {
- if (status === Image.Ready)
- root.current = this;
- }
-
- states: State {
- name: "visible"
- when: root.current === img
-
- PropertyChanges {
- img.opacity: 1
- img.scale: 1
- }
- }
-
- transitions: Transition {
- Anim {
- target: img
- properties: "opacity,scale"
- }
- }
- }
-}
diff --git a/modules/bar/components/workspaces/SpecialWorkspaces.qml b/modules/bar/components/workspaces/SpecialWorkspaces.qml
deleted file mode 100644
index ad85af8..0000000
--- a/modules/bar/components/workspaces/SpecialWorkspaces.qml
+++ /dev/null
@@ -1,359 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.components
-import qs.components.effects
-import qs.services
-import qs.utils
-import qs.config
-import Quickshell
-import Quickshell.Hyprland
-import QtQuick
-import QtQuick.Layouts
-
-Item {
- id: root
-
- required property ShellScreen screen
- readonly property HyprlandMonitor monitor: Hypr.monitorFor(screen)
- readonly property string activeSpecial: (Config.bar.workspaces.perMonitorWorkspaces ? monitor : Hypr.focusedMonitor)?.lastIpcObject?.specialWorkspace?.name ?? ""
-
- layer.enabled: true
- layer.effect: OpacityMask {
- maskSource: mask
- }
-
- Item {
- id: mask
-
- anchors.fill: parent
- layer.enabled: true
- visible: false
-
- Rectangle {
- anchors.fill: parent
- radius: Appearance.rounding.full
-
- gradient: Gradient {
- orientation: Gradient.Vertical
-
- GradientStop {
- position: 0
- color: Qt.rgba(0, 0, 0, 0)
- }
- GradientStop {
- position: 0.3
- color: Qt.rgba(0, 0, 0, 1)
- }
- GradientStop {
- position: 0.7
- color: Qt.rgba(0, 0, 0, 1)
- }
- GradientStop {
- position: 1
- color: Qt.rgba(0, 0, 0, 0)
- }
- }
- }
-
- Rectangle {
- anchors.top: parent.top
- anchors.left: parent.left
- anchors.right: parent.right
-
- radius: Appearance.rounding.full
- implicitHeight: parent.height / 2
- opacity: view.contentY > 0 ? 0 : 1
-
- Behavior on opacity {
- Anim {}
- }
- }
-
- Rectangle {
- anchors.bottom: parent.bottom
- anchors.left: parent.left
- anchors.right: parent.right
-
- radius: Appearance.rounding.full
- implicitHeight: parent.height / 2
- opacity: view.contentY < view.contentHeight - parent.height + Appearance.padding.small ? 0 : 1
-
- Behavior on opacity {
- Anim {}
- }
- }
- }
-
- ListView {
- id: view
-
- anchors.fill: parent
- spacing: Appearance.spacing.normal
- interactive: false
-
- currentIndex: model.values.findIndex(w => w.name === root.activeSpecial)
- onCurrentIndexChanged: currentIndex = Qt.binding(() => model.values.findIndex(w => w.name === root.activeSpecial))
-
- model: ScriptModel {
- values: Hypr.workspaces.values.filter(w => w.name.startsWith("special:") && (!Config.bar.workspaces.perMonitorWorkspaces || w.monitor === root.monitor))
- }
-
- preferredHighlightBegin: 0
- preferredHighlightEnd: height
- highlightRangeMode: ListView.StrictlyEnforceRange
-
- highlightFollowsCurrentItem: false
- highlight: Item {
- y: view.currentItem?.y ?? 0
- implicitHeight: view.currentItem?.size ?? 0
-
- Behavior on y {
- Anim {}
- }
- }
-
- delegate: ColumnLayout {
- id: ws
-
- required property HyprlandWorkspace modelData
- readonly property int size: label.Layout.preferredHeight + (hasWindows ? windows.implicitHeight + Appearance.padding.small : 0)
- property int wsId
- property string icon
- property bool hasWindows
-
- anchors.left: view.contentItem.left
- anchors.right: view.contentItem.right
-
- spacing: 0
-
- Component.onCompleted: {
- wsId = modelData.id;
- icon = Icons.getSpecialWsIcon(modelData.name);
- hasWindows = Config.bar.workspaces.showWindowsOnSpecialWorkspaces && modelData.lastIpcObject.windows > 0;
- }
-
- // Hacky thing cause modelData gets destroyed before the remove anim finishes
- Connections {
- target: ws.modelData
-
- function onIdChanged(): void {
- if (ws.modelData)
- ws.wsId = ws.modelData.id;
- }
-
- function onNameChanged(): void {
- if (ws.modelData)
- ws.icon = Icons.getSpecialWsIcon(ws.modelData.name);
- }
-
- function onLastIpcObjectChanged(): void {
- if (ws.modelData)
- ws.hasWindows = Config.bar.workspaces.showWindowsOnSpecialWorkspaces && ws.modelData.lastIpcObject.windows > 0;
- }
- }
-
- Connections {
- target: Config.bar.workspaces
-
- function onShowWindowsOnSpecialWorkspacesChanged(): void {
- if (ws.modelData)
- ws.hasWindows = Config.bar.workspaces.showWindowsOnSpecialWorkspaces && ws.modelData.lastIpcObject.windows > 0;
- }
- }
-
- Loader {
- id: label
-
- Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
- Layout.preferredHeight: Config.bar.sizes.innerWidth - Appearance.padding.small * 2
-
- sourceComponent: ws.icon.length === 1 ? letterComp : iconComp
-
- Component {
- id: iconComp
-
- MaterialIcon {
- fill: 1
- text: ws.icon
- verticalAlignment: Qt.AlignVCenter
- }
- }
-
- Component {
- id: letterComp
-
- StyledText {
- text: ws.icon
- verticalAlignment: Qt.AlignVCenter
- }
- }
- }
-
- Loader {
- id: windows
-
- Layout.alignment: Qt.AlignHCenter
- Layout.fillHeight: true
- Layout.preferredHeight: implicitHeight
-
- visible: active
- active: ws.hasWindows
-
- sourceComponent: Column {
- spacing: 0
-
- add: Transition {
- Anim {
- properties: "scale"
- from: 0
- to: 1
- easing.bezierCurve: Appearance.anim.curves.standardDecel
- }
- }
-
- move: Transition {
- Anim {
- properties: "scale"
- to: 1
- easing.bezierCurve: Appearance.anim.curves.standardDecel
- }
- Anim {
- properties: "x,y"
- }
- }
-
- Repeater {
- model: ScriptModel {
- values: Hypr.toplevels.values.filter(c => c.workspace?.id === ws.wsId)
- }
-
- MaterialIcon {
- required property var modelData
-
- grade: 0
- text: Icons.getAppCategoryIcon(modelData.lastIpcObject.class, "terminal")
- color: Colours.palette.m3onSurfaceVariant
- }
- }
- }
-
- Behavior on Layout.preferredHeight {
- Anim {}
- }
- }
- }
-
- add: Transition {
- Anim {
- properties: "scale"
- from: 0
- to: 1
- easing.bezierCurve: Appearance.anim.curves.standardDecel
- }
- }
-
- remove: Transition {
- Anim {
- property: "scale"
- to: 0.5
- duration: Appearance.anim.durations.small
- }
- Anim {
- property: "opacity"
- to: 0
- duration: Appearance.anim.durations.small
- }
- }
-
- move: Transition {
- Anim {
- properties: "scale"
- to: 1
- easing.bezierCurve: Appearance.anim.curves.standardDecel
- }
- Anim {
- properties: "x,y"
- }
- }
-
- displaced: Transition {
- Anim {
- properties: "scale"
- to: 1
- easing.bezierCurve: Appearance.anim.curves.standardDecel
- }
- Anim {
- properties: "x,y"
- }
- }
- }
-
- Loader {
- active: Config.bar.workspaces.activeIndicator
- anchors.fill: parent
-
- sourceComponent: Item {
- StyledClippingRect {
- id: indicator
-
- anchors.left: parent.left
- anchors.right: parent.right
-
- y: (view.currentItem?.y ?? 0) - view.contentY
- implicitHeight: view.currentItem?.size ?? 0
-
- color: Colours.palette.m3tertiary
- radius: Appearance.rounding.full
-
- Colouriser {
- source: view
- sourceColor: Colours.palette.m3onSurface
- colorizationColor: Colours.palette.m3onTertiary
-
- anchors.horizontalCenter: parent.horizontalCenter
-
- x: 0
- y: -indicator.y
- implicitWidth: view.width
- implicitHeight: view.height
- }
-
- Behavior on y {
- Anim {
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
-
- Behavior on implicitHeight {
- Anim {
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
- }
- }
- }
-
- MouseArea {
- property real startY
-
- anchors.fill: view
-
- drag.target: view.contentItem
- drag.axis: Drag.YAxis
- drag.maximumY: 0
- drag.minimumY: Math.min(0, view.height - view.contentHeight - Appearance.padding.small)
-
- onPressed: event => startY = event.y
-
- onClicked: event => {
- if (Math.abs(event.y - startY) > drag.threshold)
- return;
-
- const ws = view.itemAt(event.x, event.y);
- if (ws?.modelData)
- Hypr.dispatch(`togglespecialworkspace ${ws.modelData.name.slice(8)}`);
- else
- Hypr.dispatch("togglespecialworkspace special");
- }
- }
-}
diff --git a/modules/controlcenter/appearance/AppearancePane.qml b/modules/controlcenter/appearance/AppearancePane.qml
deleted file mode 100644
index 822edad..0000000
--- a/modules/controlcenter/appearance/AppearancePane.qml
+++ /dev/null
@@ -1,259 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import "../components"
-import "./sections"
-import "../../launcher/services"
-import qs.components
-import qs.components.controls
-import qs.components.effects
-import qs.components.containers
-import qs.components.images
-import qs.services
-import qs.config
-import qs.utils
-import Caelestia.Models
-import Quickshell
-import Quickshell.Widgets
-import QtQuick
-import QtQuick.Layouts
-
-Item {
- id: root
-
- required property Session session
-
- property real animDurationsScale: Config.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: Config.appearance.transparency.enabled ?? false
- property real transparencyBase: Config.appearance.transparency.base ?? 0.85
- property real transparencyLayers: Config.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 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
-
- anchors.fill: parent
-
- function saveConfig() {
- Config.appearance.anim.durations.scale = root.animDurationsScale;
-
- Config.appearance.font.family.material = root.fontFamilyMaterial;
- Config.appearance.font.family.mono = root.fontFamilyMono;
- Config.appearance.font.family.sans = root.fontFamilySans;
- Config.appearance.font.size.scale = root.fontSizeScale;
-
- Config.appearance.padding.scale = root.paddingScale;
- Config.appearance.rounding.scale = root.roundingScale;
- Config.appearance.spacing.scale = root.spacingScale;
-
- Config.appearance.transparency.enabled = root.transparencyEnabled;
- Config.appearance.transparency.base = root.transparencyBase;
- Config.appearance.transparency.layers = root.transparencyLayers;
-
- Config.background.desktopClock.enabled = root.desktopClockEnabled;
- Config.background.enabled = root.backgroundEnabled;
- Config.background.desktopClock.scale = root.desktopClockScale
- Config.background.desktopClock.position = root.desktopClockPosition
- Config.background.desktopClock.shadow.enabled = root.desktopClockShadowEnabled
- Config.background.desktopClock.shadow.opacity = root.desktopClockShadowOpacity
- Config.background.desktopClock.shadow.blur = root.desktopClockShadowBlur
- Config.background.desktopClock.background.enabled = root.desktopClockBackgroundEnabled
- Config.background.desktopClock.background.opacity = root.desktopClockBackgroundOpacity
- Config.background.desktopClock.background.blur = root.desktopClockBackgroundBlur
- Config.background.desktopClock.invertColors = root.desktopClockInvertColors
-
- Config.background.visualiser.enabled = root.visualiserEnabled;
- Config.background.visualiser.autoHide = root.visualiserAutoHide;
- Config.background.visualiser.rounding = root.visualiserRounding;
- Config.background.visualiser.spacing = root.visualiserSpacing;
-
- Config.border.rounding = root.borderRounding;
- Config.border.thickness = root.borderThickness;
-
- Config.save();
- }
-
- Component {
- id: appearanceRightContentComponent
-
- Item {
- id: rightAppearanceFlickable
-
- ColumnLayout {
- id: contentLayout
-
- anchors.fill: parent
- spacing: 0
-
- StyledText {
- Layout.alignment: Qt.AlignHCenter
- Layout.bottomMargin: Appearance.spacing.normal
- text: qsTr("Wallpaper")
- font.pointSize: Appearance.font.size.extraLarge
- font.weight: 600
- }
-
- Loader {
- id: wallpaperLoader
-
- Layout.fillWidth: true
- Layout.fillHeight: true
- Layout.bottomMargin: -Appearance.padding.large * 2
-
- 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("[AppearancePane] 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
- anchors.left: parent.left
- anchors.right: parent.right
- spacing: Appearance.spacing.small
-
- 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
-
- RowLayout {
- spacing: Appearance.spacing.smaller
-
- StyledText {
- text: qsTr("Appearance")
- font.pointSize: Appearance.font.size.large
- font.weight: 500
- }
-
- 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
- }
- }
- }
- }
- }
-}
diff --git a/modules/controlcenter/appearance/sections/BackgroundSection.qml b/modules/controlcenter/appearance/sections/BackgroundSection.qml
deleted file mode 100644
index d5c16d4..0000000
--- a/modules/controlcenter/appearance/sections/BackgroundSection.qml
+++ /dev/null
@@ -1,297 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import "../../components"
-import qs.components
-import qs.components.controls
-import qs.components.containers
-import qs.services
-import qs.config
-import QtQuick
-import QtQuick.Layouts
-
-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();
- }
- }
-
- StyledText {
- Layout.topMargin: Appearance.spacing.normal
- text: qsTr("Desktop Clock")
- font.pointSize: Appearance.font.size.larger
- font.weight: 500
- }
-
- SwitchRow {
- label: qsTr("Desktop Clock enabled")
- checked: rootPane.desktopClockEnabled
- onToggled: checked => {
- rootPane.desktopClockEnabled = checked;
- rootPane.saveConfig();
- }
- }
-
- SectionContainer {
- id: posContainer
-
- contentSpacing: Appearance.spacing.small
- z: 1
-
- 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();
- }
-
- StyledText {
- text: qsTr("Positioning")
- font.pointSize: Appearance.font.size.larger
- font.weight: 500
- }
-
- SplitButtonRow {
- label: qsTr("Vertical Position")
- enabled: rootPane.desktopClockEnabled
-
- menuItems: [
- MenuItem { text: qsTr("Top"); icon: "vertical_align_top"; property string val: "top" },
- MenuItem { text: qsTr("Middle"); icon: "vertical_align_center"; property string val: "middle" },
- MenuItem { text: qsTr("Bottom"); icon: "vertical_align_bottom"; property string val: "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 { text: qsTr("Left"); icon: "align_horizontal_left"; property string val: "left" },
- MenuItem { text: qsTr("Center"); icon: "align_horizontal_center"; property string val: "center" },
- MenuItem { text: qsTr("Right"); icon: "align_horizontal_right"; property string val: "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: Appearance.spacing.small
-
- StyledText {
- text: qsTr("Shadow")
- font.pointSize: Appearance.font.size.larger
- font.weight: 500
- }
-
- SwitchRow {
- label: qsTr("Enabled")
- checked: rootPane.desktopClockShadowEnabled
- onToggled: checked => {
- rootPane.desktopClockShadowEnabled = checked;
- rootPane.saveConfig();
- }
- }
-
- SectionContainer {
- contentSpacing: Appearance.spacing.normal
-
- 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: Appearance.spacing.normal
-
- 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: Appearance.spacing.small
-
- StyledText {
- text: qsTr("Background")
- font.pointSize: Appearance.font.size.larger
- font.weight: 500
- }
-
- 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: Appearance.spacing.normal
-
- 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: Appearance.spacing.normal
- text: qsTr("Visualiser")
- font.pointSize: Appearance.font.size.larger
- font.weight: 500
- }
-
- 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: Appearance.spacing.normal
-
- 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: Appearance.spacing.normal
-
- 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/ColorSchemeSection.qml b/modules/controlcenter/appearance/sections/ColorSchemeSection.qml
deleted file mode 100644
index 691d908..0000000
--- a/modules/controlcenter/appearance/sections/ColorSchemeSection.qml
+++ /dev/null
@@ -1,146 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import "../../../launcher/services"
-import qs.components
-import qs.components.controls
-import qs.components.containers
-import qs.services
-import qs.config
-import Quickshell
-import QtQuick
-import QtQuick.Layouts
-
-CollapsibleSection {
- title: qsTr("Color scheme")
- description: qsTr("Available color schemes")
- showBackground: true
-
- ColumnLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.small / 2
-
- 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: Appearance.rounding.normal
- border.width: isCurrent ? 1 : 0
- border.color: Colours.palette.m3primary
-
- StateLayer {
- function onClicked(): void {
- 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: Appearance.padding.normal
-
- spacing: Appearance.spacing.normal
-
- StyledRect {
- id: preview
-
- Layout.alignment: Qt.AlignVCenter
-
- border.width: 1
- border.color: Qt.alpha(`#${modelData.colours?.outline}`, 0.5)
-
- color: `#${modelData.colours?.surface}`
- radius: Appearance.rounding.full
- implicitWidth: iconPlaceholder.implicitWidth
- implicitHeight: iconPlaceholder.implicitWidth
-
- MaterialIcon {
- id: iconPlaceholder
- visible: false
- text: "circle"
- font.pointSize: Appearance.font.size.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: Appearance.rounding.full
- }
- }
- }
-
- Column {
- Layout.fillWidth: true
- spacing: 0
-
- StyledText {
- text: modelData.flavour ?? ""
- font.pointSize: Appearance.font.size.normal
- }
-
- StyledText {
- text: modelData.name ?? ""
- font.pointSize: Appearance.font.size.small
- color: Colours.palette.m3outline
-
- elide: Text.ElideRight
- anchors.left: parent.left
- anchors.right: parent.right
- }
- }
-
- Loader {
- active: isCurrent
-
- sourceComponent: MaterialIcon {
- text: "check"
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: Appearance.font.size.large
- }
- }
- }
-
- implicitHeight: schemeRow.implicitHeight + Appearance.padding.normal * 2
- }
- }
- }
-}
-
diff --git a/modules/controlcenter/appearance/sections/FontsSection.qml b/modules/controlcenter/appearance/sections/FontsSection.qml
deleted file mode 100644
index ef807b1..0000000
--- a/modules/controlcenter/appearance/sections/FontsSection.qml
+++ /dev/null
@@ -1,280 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import "../../components"
-import qs.components
-import qs.components.controls
-import qs.components.containers
-import qs.services
-import qs.config
-import QtQuick
-import QtQuick.Layouts
-
-CollapsibleSection {
- id: root
-
- required property var rootPane
-
- title: qsTr("Fonts")
- showBackground: true
-
- CollapsibleSection {
- id: materialFontSection
- title: qsTr("Material font family")
- expanded: true
- showBackground: true
- nested: true
-
- Loader {
- id: materialFontLoader
- Layout.fillWidth: true
- Layout.preferredHeight: item ? Math.min(item.contentHeight, 300) : 0
- active: materialFontSection.expanded
-
- sourceComponent: StyledListView {
- id: materialFontList
- property alias contentHeight: materialFontList.contentHeight
-
- clip: true
- spacing: Appearance.spacing.small / 2
- model: Qt.fontFamilies()
-
- StyledScrollBar.vertical: StyledScrollBar {
- flickable: materialFontList
- }
-
- delegate: StyledRect {
- required property string modelData
- required property int index
-
- width: ListView.view.width
-
- readonly property bool isCurrent: modelData === rootPane.fontFamilyMaterial
- color: Qt.alpha(Colours.tPalette.m3surfaceContainer, isCurrent ? Colours.tPalette.m3surfaceContainer.a : 0)
- radius: Appearance.rounding.normal
- border.width: isCurrent ? 1 : 0
- border.color: Colours.palette.m3primary
-
- StateLayer {
- function onClicked(): void {
- rootPane.fontFamilyMaterial = modelData;
- rootPane.saveConfig();
- }
- }
-
- RowLayout {
- id: fontFamilyMaterialRow
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- anchors.margins: Appearance.padding.normal
-
- spacing: Appearance.spacing.normal
-
- StyledText {
- text: modelData
- font.pointSize: Appearance.font.size.normal
- }
-
- Item {
- Layout.fillWidth: true
- }
-
- Loader {
- active: isCurrent
-
- sourceComponent: MaterialIcon {
- text: "check"
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: Appearance.font.size.large
- }
- }
- }
-
- implicitHeight: fontFamilyMaterialRow.implicitHeight + Appearance.padding.normal * 2
- }
- }
- }
- }
-
- 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
- active: monoFontSection.expanded
-
- sourceComponent: StyledListView {
- id: monoFontList
- property alias contentHeight: monoFontList.contentHeight
-
- clip: true
- spacing: Appearance.spacing.small / 2
- model: Qt.fontFamilies()
-
- StyledScrollBar.vertical: StyledScrollBar {
- flickable: monoFontList
- }
-
- delegate: StyledRect {
- required property string modelData
- required property int index
-
- width: ListView.view.width
-
- readonly property bool isCurrent: modelData === rootPane.fontFamilyMono
- color: Qt.alpha(Colours.tPalette.m3surfaceContainer, isCurrent ? Colours.tPalette.m3surfaceContainer.a : 0)
- radius: Appearance.rounding.normal
- border.width: isCurrent ? 1 : 0
- border.color: Colours.palette.m3primary
-
- StateLayer {
- function onClicked(): void {
- rootPane.fontFamilyMono = modelData;
- rootPane.saveConfig();
- }
- }
-
- RowLayout {
- id: fontFamilyMonoRow
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- anchors.margins: Appearance.padding.normal
-
- spacing: Appearance.spacing.normal
-
- StyledText {
- text: modelData
- font.pointSize: Appearance.font.size.normal
- }
-
- Item {
- Layout.fillWidth: true
- }
-
- Loader {
- active: isCurrent
-
- sourceComponent: MaterialIcon {
- text: "check"
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: Appearance.font.size.large
- }
- }
- }
-
- implicitHeight: fontFamilyMonoRow.implicitHeight + Appearance.padding.normal * 2
- }
- }
- }
- }
-
- CollapsibleSection {
- id: sansFontSection
- title: qsTr("Sans-serif font family")
- expanded: false
- showBackground: true
- nested: true
-
- Loader {
- Layout.fillWidth: true
- Layout.preferredHeight: item ? Math.min(item.contentHeight, 300) : 0
- active: sansFontSection.expanded
-
- sourceComponent: StyledListView {
- id: sansFontList
- property alias contentHeight: sansFontList.contentHeight
-
- clip: true
- spacing: Appearance.spacing.small / 2
- model: Qt.fontFamilies()
-
- StyledScrollBar.vertical: StyledScrollBar {
- flickable: sansFontList
- }
-
- delegate: StyledRect {
- required property string modelData
- required property int index
-
- width: ListView.view.width
-
- readonly property bool isCurrent: modelData === rootPane.fontFamilySans
- color: Qt.alpha(Colours.tPalette.m3surfaceContainer, isCurrent ? Colours.tPalette.m3surfaceContainer.a : 0)
- radius: Appearance.rounding.normal
- border.width: isCurrent ? 1 : 0
- border.color: Colours.palette.m3primary
-
- StateLayer {
- function onClicked(): void {
- rootPane.fontFamilySans = modelData;
- rootPane.saveConfig();
- }
- }
-
- RowLayout {
- id: fontFamilySansRow
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- anchors.margins: Appearance.padding.normal
-
- spacing: Appearance.spacing.normal
-
- StyledText {
- text: modelData
- font.pointSize: Appearance.font.size.normal
- }
-
- Item {
- Layout.fillWidth: true
- }
-
- Loader {
- active: isCurrent
-
- sourceComponent: MaterialIcon {
- text: "check"
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: Appearance.font.size.large
- }
- }
- }
-
- implicitHeight: fontFamilySansRow.implicitHeight + Appearance.padding.normal * 2
- }
- }
- }
- }
-
- SectionContainer {
- contentSpacing: Appearance.spacing.normal
-
- 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/launcher/LauncherPane.qml b/modules/controlcenter/launcher/LauncherPane.qml
deleted file mode 100644
index fabe75e..0000000
--- a/modules/controlcenter/launcher/LauncherPane.qml
+++ /dev/null
@@ -1,597 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import "../components"
-import "../../launcher/services"
-import qs.components
-import qs.components.controls
-import qs.components.effects
-import qs.components.containers
-import qs.services
-import qs.config
-import qs.utils
-import Caelestia
-import Quickshell
-import Quickshell.Widgets
-import QtQuick
-import QtQuick.Layouts
-import "../../../utils/scripts/fuzzysort.js" as Fuzzy
-
-Item {
- id: root
-
- required property Session session
-
- property var selectedApp: root.session.launcher.active
- property bool hideFromLauncherChecked: false
-
- anchors.fill: parent
-
- onSelectedAppChanged: {
- root.session.launcher.active = root.selectedApp;
- updateToggleState();
- }
-
- Connections {
- target: root.session.launcher
- function onActiveChanged() {
- root.selectedApp = root.session.launcher.active;
- updateToggleState();
- }
- }
-
- function updateToggleState() {
- if (!root.selectedApp) {
- root.hideFromLauncherChecked = false;
- return;
- }
-
- const appId = root.selectedApp.id || root.selectedApp.entry?.id;
-
- if (Config.launcher.hiddenApps && Config.launcher.hiddenApps.length > 0) {
- root.hideFromLauncherChecked = Config.launcher.hiddenApps.includes(appId);
- } else {
- root.hideFromLauncherChecked = false;
- }
- }
-
- function saveHiddenApps(isHidden) {
- if (!root.selectedApp) {
- return;
- }
-
- const appId = root.selectedApp.id || root.selectedApp.entry?.id;
-
- const hiddenApps = Config.launcher.hiddenApps ? [...Config.launcher.hiddenApps] : [];
-
- if (isHidden) {
- if (!hiddenApps.includes(appId)) {
- hiddenApps.push(appId);
- }
- } else {
- const index = hiddenApps.indexOf(appId);
- if (index !== -1) {
- hiddenApps.splice(index, 1);
- }
- }
-
- Config.launcher.hiddenApps = hiddenApps;
- Config.save();
- }
-
-
- AppDb {
- id: allAppsDb
-
- path: `${Paths.state}/apps.sqlite`
- entries: DesktopEntries.applications.values
- }
-
- property string searchText: ""
-
- function filterApps(search: string): list<var> {
- 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);
- }
-
- property list<var> filteredApps: []
-
- function updateFilteredApps() {
- filteredApps = filterApps(searchText);
- }
-
- onSearchTextChanged: {
- updateFilteredApps();
- }
-
- Component.onCompleted: {
- updateFilteredApps();
- }
-
- Connections {
- target: allAppsDb
- function onAppsChanged() {
- updateFilteredApps();
- }
- }
-
- SplitPaneLayout {
- anchors.fill: parent
-
- leftContent: Component {
-
- ColumnLayout {
- id: leftLauncherLayout
- anchors.fill: parent
-
- spacing: Appearance.spacing.small
-
- RowLayout {
- spacing: Appearance.spacing.smaller
-
- StyledText {
- text: qsTr("Launcher")
- font.pointSize: Appearance.font.size.large
- font.weight: 500
- }
-
- Item {
- Layout.fillWidth: true
- }
-
- ToggleButton {
- toggled: !root.session.launcher.active
- icon: "settings"
- accent: "Primary"
- iconSize: Appearance.font.size.normal
- horizontalPadding: Appearance.padding.normal
- verticalPadding: Appearance.padding.smaller
- 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: Appearance.spacing.large
- text: qsTr("Applications (%1)").arg(root.searchText ? root.filteredApps.length : allAppsDb.apps.length)
- font.pointSize: Appearance.font.size.normal
- font.weight: 500
- }
-
- StyledText {
- text: qsTr("All applications available in the launcher")
- color: Colours.palette.m3outline
- }
-
- StyledRect {
- Layout.fillWidth: true
- Layout.topMargin: Appearance.spacing.normal
- Layout.bottomMargin: Appearance.spacing.small
-
- color: Colours.layer(Colours.palette.m3surfaceContainer, 2)
- radius: Appearance.rounding.full
-
- implicitHeight: Math.max(searchIcon.implicitHeight, searchField.implicitHeight, clearIcon.implicitHeight)
-
- MaterialIcon {
- id: searchIcon
-
- anchors.verticalCenter: parent.verticalCenter
- anchors.left: parent.left
- anchors.leftMargin: Appearance.padding.normal
-
- text: "search"
- color: Colours.palette.m3onSurfaceVariant
- }
-
- StyledTextField {
- id: searchField
-
- anchors.left: searchIcon.right
- anchors.right: clearIcon.left
- anchors.leftMargin: Appearance.spacing.small
- anchors.rightMargin: Appearance.spacing.small
-
- topPadding: Appearance.padding.normal
- bottomPadding: Appearance.padding.normal
-
- placeholderText: qsTr("Search applications...")
-
- onTextChanged: {
- root.searchText = text;
- }
- }
-
- MaterialIcon {
- id: clearIcon
-
- anchors.verticalCenter: parent.verticalCenter
- anchors.right: parent.right
- anchors.rightMargin: Appearance.padding.normal
-
- 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 {
- duration: Appearance.anim.durations.small
- }
- }
-
- Behavior on opacity {
- Anim {
- duration: Appearance.anim.durations.small
- }
- }
- }
- }
-
- Loader {
- id: appsListLoader
- Layout.fillWidth: true
- Layout.fillHeight: true
- active: true
-
- sourceComponent: StyledListView {
- id: appsListView
-
- Layout.fillWidth: true
- Layout.fillHeight: true
-
- model: root.filteredApps
- spacing: Appearance.spacing.small / 2
- clip: true
-
- StyledScrollBar.vertical: StyledScrollBar {
- flickable: parent
- }
-
- delegate: StyledRect {
- required property var modelData
-
- width: parent ? parent.width : 0
-
- readonly property bool isSelected: root.selectedApp === modelData
-
- color: isSelected ? Colours.layer(Colours.palette.m3surfaceContainer, 2) : "transparent"
- radius: Appearance.rounding.normal
-
- opacity: 0
-
- Behavior on opacity {
- NumberAnimation {
- duration: 1000
- easing.type: Easing.OutCubic
- }
- }
-
- Component.onCompleted: {
- opacity = 1;
- }
-
- StateLayer {
- function onClicked(): void {
- root.session.launcher.active = modelData;
- }
- }
-
- RowLayout {
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- anchors.margins: Appearance.padding.normal
-
- spacing: Appearance.spacing.normal
-
- IconImage {
- 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.pointSize: Appearance.font.size.normal
- }
- }
-
- implicitHeight: 40
- }
- }
- }
- }
- }
-
- 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;
- }
-
- Loader {
- id: rightLauncherLoader
-
- anchors.fill: parent
-
- opacity: 1
- scale: 1
- transformOrigin: Item.Center
- clip: false
-
- sourceComponent: rightLauncherPane.targetComponent
- active: true
-
- property var displayedApp: rightLauncherPane.displayedApp
-
- 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
- }
- ]
- }
- }
-
- onPaneChanged: {
- nextComponent = getComponentForPane();
- paneId = pane ? (pane.id || pane.entry?.id || "") : "";
- }
-
- onDisplayedAppChanged: {
- if (displayedApp) {
- const appId = displayedApp.id || displayedApp.entry?.id;
- if (Config.launcher.hiddenApps && Config.launcher.hiddenApps.length > 0) {
- root.hideFromLauncherChecked = Config.launcher.hiddenApps.includes(appId);
- } else {
- root.hideFromLauncherChecked = false;
- }
- } else {
- root.hideFromLauncherChecked = false;
- }
- }
- }
- }
- }
-
- 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
- anchors.fill: parent
-
- readonly property var displayedApp: parent && parent.displayedApp !== undefined ? parent.displayedApp : null
-
- spacing: Appearance.spacing.normal
-
- SettingsHeader {
- Layout.leftMargin: Appearance.padding.large * 2
- Layout.rightMargin: Appearance.padding.large * 2
- Layout.topMargin: Appearance.padding.large * 2
- visible: displayedApp === null
- icon: "apps"
- title: qsTr("Launcher Applications")
- }
-
- Item {
- Layout.alignment: Qt.AlignHCenter
- Layout.leftMargin: Appearance.padding.large * 2
- Layout.rightMargin: Appearance.padding.large * 2
- Layout.topMargin: Appearance.padding.large * 2
- visible: displayedApp !== null
- implicitWidth: Math.max(appIconImage.implicitWidth, appTitleText.implicitWidth)
- implicitHeight: appIconImage.implicitHeight + Appearance.spacing.normal + appTitleText.implicitHeight
-
- ColumnLayout {
- anchors.centerIn: parent
- spacing: Appearance.spacing.normal
-
- IconImage {
- id: appIconImage
- Layout.alignment: Qt.AlignHCenter
- implicitSize: Appearance.font.size.extraLarge * 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.pointSize: Appearance.font.size.large
- font.bold: true
- }
- }
- }
-
- Item {
- Layout.fillWidth: true
- Layout.fillHeight: true
- Layout.topMargin: Appearance.spacing.large
- Layout.leftMargin: Appearance.padding.large * 2
- Layout.rightMargin: Appearance.padding.large * 2
-
- 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: Appearance.spacing.normal
-
- SwitchRow {
- Layout.topMargin: Appearance.spacing.normal
- visible: appDetailsLayout.displayedApp !== null
- label: qsTr("Hide from launcher")
- checked: root.hideFromLauncherChecked
- enabled: appDetailsLayout.displayedApp !== null
- onToggled: checked => {
- root.hideFromLauncherChecked = checked;
- const app = appDetailsLayout.displayedApp;
- if (app) {
- const appId = app.id || app.entry?.id;
- const hiddenApps = Config.launcher.hiddenApps ? [...Config.launcher.hiddenApps] : [];
- if (checked) {
- if (!hiddenApps.includes(appId)) {
- hiddenApps.push(appId);
- }
- } else {
- const index = hiddenApps.indexOf(appId);
- if (index !== -1) {
- hiddenApps.splice(index, 1);
- }
- }
- Config.launcher.hiddenApps = hiddenApps;
- Config.save();
- }
- }
- }
-
- }
- }
- }
- }
- }
-}
diff --git a/modules/controlcenter/network/NetworkSettings.qml b/modules/controlcenter/network/NetworkSettings.qml
index 04746af..81175fb 100644
--- a/modules/controlcenter/network/NetworkSettings.qml
+++ b/modules/controlcenter/network/NetworkSettings.qml
@@ -63,45 +63,6 @@ ColumnLayout {
SectionHeader {
Layout.topMargin: Appearance.spacing.large
- title: qsTr("VPN")
- description: qsTr("VPN provider settings")
- visible: Config.utilities.vpn.enabled || Config.utilities.vpn.provider.length > 0
- }
-
- SectionContainer {
- visible: Config.utilities.vpn.enabled || Config.utilities.vpn.provider.length > 0
-
- ToggleRow {
- label: qsTr("VPN enabled")
- checked: Config.utilities.vpn.enabled
- toggle.onToggled: {
- Config.utilities.vpn.enabled = checked;
- Config.save();
- }
- }
-
- PropertyRow {
- showTopMargin: true
- label: qsTr("Providers")
- value: qsTr("%1").arg(Config.utilities.vpn.provider.length)
- }
-
- TextButton {
- Layout.fillWidth: true
- Layout.topMargin: Appearance.spacing.normal
- Layout.minimumHeight: Appearance.font.size.normal + Appearance.padding.normal * 2
- text: qsTr("⚙ Manage VPN Providers")
- inactiveColour: Colours.palette.m3secondaryContainer
- inactiveOnColour: Colours.palette.m3onSecondaryContainer
-
- onClicked: {
- vpnSettingsDialog.open();
- }
- }
- }
-
- SectionHeader {
- Layout.topMargin: Appearance.spacing.large
title: qsTr("Current connection")
description: qsTr("Active network connection information")
}
@@ -135,38 +96,5 @@ ColumnLayout {
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 - Appearance.padding.large * 2)
- height: Math.min(700, parent.height - Appearance.padding.large * 2)
-
- modal: true
- closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
-
- background: StyledRect {
- color: Colours.palette.m3surface
- radius: Appearance.rounding.large
- }
-
- StyledFlickable {
- anchors.fill: parent
- anchors.margins: Appearance.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
index 23e795e..9047174 100644
--- a/modules/controlcenter/network/NetworkingPane.qml
+++ b/modules/controlcenter/network/NetworkingPane.qml
@@ -112,24 +112,6 @@ Item {
}
CollapsibleSection {
- id: vpnListSection
-
- Layout.fillWidth: true
- title: qsTr("VPN")
- expanded: true
-
- Loader {
- Layout.fillWidth: true
- sourceComponent: Component {
- VpnList {
- session: root.session
- showHeader: false
- }
- }
- }
- }
-
- CollapsibleSection {
id: ethernetListSection
Layout.fillWidth: true
@@ -171,17 +153,15 @@ Item {
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 var pane: ethernetPane || wirelessPane
+ property string paneId: 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;
@@ -193,27 +173,12 @@ Item {
}
Connections {
- target: root.session && root.session.vpn ? root.session.vpn : null
- enabled: target !== null
-
- 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();
- }
- }
-
- Connections {
target: root.session && root.session.ethernet ? root.session.ethernet : null
enabled: target !== null
-
+
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();
@@ -223,11 +188,10 @@ Item {
Connections {
target: root.session && root.session.network ? root.session.network : null
enabled: target !== null
-
+
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();
@@ -333,29 +297,6 @@ Item {
}
}
- 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
diff --git a/modules/controlcenter/network/VpnDetails.qml b/modules/controlcenter/network/VpnDetails.qml
deleted file mode 100644
index 76a9b17..0000000
--- a/modules/controlcenter/network/VpnDetails.qml
+++ /dev/null
@@ -1,367 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import "../components"
-import qs.components
-import qs.components.controls
-import qs.components.effects
-import qs.components.containers
-import qs.services
-import qs.config
-import qs.utils
-import QtQuick
-import QtQuick.Controls
-import QtQuick.Layouts
-import Qt5Compat.GraphicalEffects
-
-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 = Config.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: Appearance.spacing.normal
-
- 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 < Config.utilities.vpn.provider.length; i++) {
- const p = Config.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);
- }
-
- providers.push(newProvider);
- } else {
- providers.push(p);
- }
- }
-
- Config.utilities.vpn.provider = providers;
- Config.save();
- }
- }
-
- RowLayout {
- Layout.fillWidth: true
- Layout.topMargin: Appearance.spacing.normal
- spacing: Appearance.spacing.normal
-
- TextButton {
- Layout.fillWidth: true
- Layout.minimumHeight: Appearance.font.size.normal + Appearance.padding.normal * 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: {
- editVpnDialog.editIndex = root.vpnProvider.index;
- editVpnDialog.providerName = root.vpnProvider.name;
- editVpnDialog.displayName = root.vpnProvider.displayName;
- editVpnDialog.interfaceName = root.vpnProvider.interface;
- 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 < Config.utilities.vpn.provider.length; i++) {
- if (i !== root.vpnProvider.index) {
- providers.push(Config.utilities.vpn.provider[i]);
- }
- }
- Config.utilities.vpn.provider = providers;
- Config.save();
- root.session.vpn.active = null;
- }
- }
- }
- }
- }
- },
- Component {
- ColumnLayout {
- spacing: Appearance.spacing.normal
-
- SectionHeader {
- title: qsTr("Provider details")
- description: qsTr("VPN provider information")
- }
-
- SectionContainer {
- contentSpacing: Appearance.spacing.small / 2
-
- 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...");
- if (VPN.connected) return qsTr("Connected");
- return qsTr("Enabled (Not connected)");
- }
- }
-
- 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: ""
-
- parent: Overlay.overlay
- anchors.centerIn: parent
- width: Math.min(400, parent.width - Appearance.padding.large * 2)
- padding: Appearance.padding.large * 1.5
-
- modal: true
- closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
-
- opacity: 0
- scale: 0.7
-
- enter: Transition {
- ParallelAnimation {
- NumberAnimation { property: "opacity"; from: 0; to: 1; duration: Appearance.anim.durations.expressiveFastSpatial; easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial }
- NumberAnimation { property: "scale"; from: 0.7; to: 1; duration: Appearance.anim.durations.expressiveFastSpatial; easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial }
- }
- }
-
- exit: Transition {
- ParallelAnimation {
- NumberAnimation { property: "opacity"; from: 1; to: 0; duration: Appearance.anim.durations.expressiveFastSpatial; easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial }
- NumberAnimation { property: "scale"; from: 1; to: 0.7; duration: Appearance.anim.durations.expressiveFastSpatial; easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial }
- }
- }
-
- function closeWithAnimation(): void {
- close();
- }
-
- Overlay.modal: Rectangle {
- color: Qt.rgba(0, 0, 0, 0.4 * editVpnDialog.opacity)
- }
-
-
- background: StyledRect {
- color: Colours.palette.m3surfaceContainerHigh
- radius: Appearance.rounding.large
-
- layer.enabled: true
- layer.effect: DropShadow {
- color: Qt.rgba(0, 0, 0, 0.3)
- radius: 16
- samples: 33
- verticalOffset: 4
- }
- }
-
- contentItem: ColumnLayout {
- spacing: Appearance.spacing.normal
-
- StyledText {
- text: qsTr("Edit VPN Provider")
- font.pointSize: Appearance.font.size.large
- font.weight: 500
- }
-
- ColumnLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.smaller / 2
-
- StyledText {
- text: qsTr("Display Name")
- font.pointSize: Appearance.font.size.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: Appearance.rounding.small
- 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 - Appearance.padding.normal
- horizontalAlignment: TextInput.AlignLeft
- text: editVpnDialog.displayName
- onTextChanged: editVpnDialog.displayName = text
- }
- }
- }
-
- ColumnLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.smaller / 2
-
- StyledText {
- text: qsTr("Interface (e.g., wg0, torguard)")
- font.pointSize: Appearance.font.size.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: Appearance.rounding.small
- 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 - Appearance.padding.normal
- horizontalAlignment: TextInput.AlignLeft
- text: editVpnDialog.interfaceName
- onTextChanged: editVpnDialog.interfaceName = text
- }
- }
- }
-
- Item { Layout.preferredHeight: Appearance.spacing.normal }
-
- RowLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.normal
-
- 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 = Config.utilities.vpn.provider[editVpnDialog.editIndex];
- const wasEnabled = typeof oldProvider === "object" ? (oldProvider.enabled !== false) : true;
-
- for (let i = 0; i < Config.utilities.vpn.provider.length; i++) {
- if (i === editVpnDialog.editIndex) {
- providers.push({
- name: editVpnDialog.providerName,
- displayName: editVpnDialog.displayName || editVpnDialog.interfaceName,
- interface: editVpnDialog.interfaceName,
- enabled: wasEnabled
- });
- } else {
- providers.push(Config.utilities.vpn.provider[i]);
- }
- }
-
- Config.utilities.vpn.provider = providers;
- Config.save();
- editVpnDialog.closeWithAnimation();
- }
- }
- }
- }
- }
-}
diff --git a/modules/controlcenter/network/VpnList.qml b/modules/controlcenter/network/VpnList.qml
deleted file mode 100644
index 665f8cc..0000000
--- a/modules/controlcenter/network/VpnList.qml
+++ /dev/null
@@ -1,646 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import qs.components
-import qs.components.controls
-import qs.components.containers
-import qs.components.effects
-import qs.services
-import qs.config
-import qs.utils
-import Quickshell
-import QtQuick
-import QtQuick.Controls
-import QtQuick.Layouts
-import Qt5Compat.GraphicalEffects
-
-ColumnLayout {
- id: root
-
- required property Session session
- property bool showHeader: true
- property int pendingSwitchIndex: -1
-
- spacing: Appearance.spacing.normal
-
- Connections {
- target: VPN
- function onConnectedChanged() {
- if (!VPN.connected && root.pendingSwitchIndex >= 0) {
- const targetIndex = root.pendingSwitchIndex;
- root.pendingSwitchIndex = -1;
-
- const providers = [];
- for (let i = 0; i < Config.utilities.vpn.provider.length; i++) {
- const p = Config.utilities.vpn.provider[i];
- if (typeof p === "object") {
- const newProvider = {
- name: p.name,
- displayName: p.displayName,
- interface: p.interface,
- enabled: (i === targetIndex)
- };
- providers.push(newProvider);
- } else {
- providers.push(p);
- }
- }
- Config.utilities.vpn.provider = providers;
- Config.save();
-
- Qt.callLater(function() {
- VPN.toggle();
- });
- }
- }
- }
-
- 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: Appearance.spacing.smaller
-
- model: ScriptModel {
- values: Config.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
-
- color: Qt.alpha(Colours.tPalette.m3surfaceContainer, (root.session && root.session.vpn && root.session.vpn.active === modelData) ? Colours.tPalette.m3surfaceContainer.a : 0)
- radius: Appearance.rounding.normal
-
- StateLayer {
- function onClicked(): void {
- 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: Appearance.padding.normal
-
- spacing: Appearance.spacing.normal
-
- StyledRect {
- implicitWidth: implicitHeight
- implicitHeight: icon.implicitHeight + Appearance.padding.normal * 2
-
- radius: Appearance.rounding.normal
- 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"
- font.pointSize: Appearance.font.size.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: Appearance.spacing.smaller
-
- StyledText {
- Layout.fillWidth: true
- text: {
- if (modelData.enabled && VPN.connected) return qsTr("Connected");
- if (modelData.enabled && VPN.connecting) return qsTr("Connecting...");
- if (modelData.enabled) return qsTr("Enabled");
- return qsTr("Disabled");
- }
- color: modelData.enabled ? (VPN.connected ? Colours.palette.m3primary : Colours.palette.m3onSurface) : Colours.palette.m3outline
- font.pointSize: Appearance.font.size.small
- font.weight: modelData.enabled && VPN.connected ? 500 : 400
- elide: Text.ElideRight
- }
- }
- }
-
- StyledRect {
- implicitWidth: implicitHeight
- implicitHeight: connectIcon.implicitHeight + Appearance.padding.smaller * 2
-
- radius: Appearance.rounding.full
- color: Qt.alpha(Colours.palette.m3primaryContainer, VPN.connected && modelData.enabled ? 1 : 0)
-
- StateLayer {
- enabled: !VPN.connecting
- function onClicked(): void {
- 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 < Config.utilities.vpn.provider.length; i++) {
- const p = Config.utilities.vpn.provider[i];
- if (typeof p === "object") {
- const newProvider = {
- name: p.name,
- displayName: p.displayName,
- interface: p.interface,
- enabled: (i === clickedIndex)
- };
- providers.push(newProvider);
- } else {
- providers.push(p);
- }
- }
- Config.utilities.vpn.provider = providers;
- Config.save();
-
- Qt.callLater(function() {
- VPN.toggle();
- });
- }
- }
- }
- }
-
- 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 + Appearance.padding.smaller * 2
-
- radius: Appearance.rounding.full
- color: "transparent"
-
- StateLayer {
- function onClicked(): void {
- const providers = [];
- for (let i = 0; i < Config.utilities.vpn.provider.length; i++) {
- if (i !== modelData.index) {
- providers.push(Config.utilities.vpn.provider[i]);
- }
- }
- Config.utilities.vpn.provider = providers;
- Config.save();
- }
- }
-
- MaterialIcon {
- id: deleteIcon
-
- anchors.centerIn: parent
- text: "delete"
- color: Colours.palette.m3onSurface
- }
- }
- }
-
- implicitHeight: rowLayout.implicitHeight + Appearance.padding.normal * 2
- }
- }
- }
-
- Popup {
- id: vpnDialog
-
- property string currentState: "selection"
- property int editIndex: -1
- property string providerName: ""
- property string displayName: ""
- property string interfaceName: ""
-
- parent: Overlay.overlay
- x: Math.round((parent.width - width) / 2)
- y: Math.round((parent.height - height) / 2)
- implicitWidth: Math.min(400, parent.width - Appearance.padding.large * 2)
- padding: Appearance.padding.large * 1.5
-
- modal: true
- closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
-
- opacity: 0
- scale: 0.7
-
- enter: Transition {
- ParallelAnimation {
- NumberAnimation { property: "opacity"; from: 0; to: 1; duration: Appearance.anim.durations.normal; easing.bezierCurve: Appearance.anim.curves.emphasized }
- NumberAnimation { property: "scale"; from: 0.7; to: 1; duration: Appearance.anim.durations.normal; easing.bezierCurve: Appearance.anim.curves.emphasized }
- }
- }
-
- exit: Transition {
- ParallelAnimation {
- NumberAnimation { property: "opacity"; from: 1; to: 0; duration: Appearance.anim.durations.small; easing.bezierCurve: Appearance.anim.curves.emphasized }
- NumberAnimation { property: "scale"; from: 1; to: 0.7; duration: Appearance.anim.durations.small; easing.bezierCurve: Appearance.anim.curves.emphasized }
- }
- }
-
- function showProviderSelection(): void {
- currentState = "selection";
- open();
- }
-
- function closeWithAnimation(): void {
- close();
- }
-
- function showAddForm(providerType: string, defaultDisplayName: string): void {
- editIndex = -1;
- providerName = providerType;
- displayName = defaultDisplayName;
- interfaceName = "";
-
- if (currentState === "selection") {
- transitionToForm.start();
- } else {
- currentState = "form";
- isClosing = false;
- open();
- }
- }
-
- function showEditForm(index: int): void {
- const provider = Config.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 || "") : "";
-
- currentState = "form";
- open();
- }
-
- Overlay.modal: Rectangle {
- color: Qt.rgba(0, 0, 0, 0.4 * vpnDialog.opacity)
- }
-
- onClosed: {
- currentState = "selection";
- }
-
- SequentialAnimation {
- id: transitionToForm
-
- ParallelAnimation {
- NumberAnimation {
- target: selectionContent
- property: "opacity"
- to: 0
- duration: Appearance.anim.durations.small
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
-
- ScriptAction {
- script: {
- vpnDialog.currentState = "form";
- }
- }
-
- ParallelAnimation {
- NumberAnimation {
- target: formContent
- property: "opacity"
- to: 1
- duration: Appearance.anim.durations.small
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
- }
-
- background: StyledRect {
- color: Colours.palette.m3surfaceContainerHigh
- radius: Appearance.rounding.large
-
- layer.enabled: true
- layer.effect: DropShadow {
- color: Qt.rgba(0, 0, 0, 0.3)
- radius: 16
- samples: 33
- verticalOffset: 4
- }
-
- Behavior on implicitHeight {
- NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
- }
-
- contentItem: Item {
- implicitHeight: vpnDialog.currentState === "selection" ? selectionContent.implicitHeight : formContent.implicitHeight
-
- Behavior on implicitHeight {
- NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
-
- ColumnLayout {
- id: selectionContent
-
- anchors.fill: parent
- spacing: Appearance.spacing.normal
- visible: vpnDialog.currentState === "selection"
- opacity: vpnDialog.currentState === "selection" ? 1 : 0
-
- Behavior on opacity {
- NumberAnimation {
- duration: Appearance.anim.durations.small
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
-
- StyledText {
- text: qsTr("Add VPN Provider")
- font.pointSize: Appearance.font.size.large
- font.weight: 500
- }
-
- StyledText {
- Layout.fillWidth: true
- text: qsTr("Choose a provider to add")
- wrapMode: Text.WordWrap
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.small
- }
-
- Item { Layout.preferredHeight: Appearance.spacing.small }
-
- TextButton {
- Layout.fillWidth: true
- text: qsTr("NetBird")
- inactiveColour: Colours.tPalette.m3surfaceContainerHigh
- inactiveOnColour: Colours.palette.m3onSurface
- onClicked: {
- const providers = [];
- for (let i = 0; i < Config.utilities.vpn.provider.length; i++) {
- providers.push(Config.utilities.vpn.provider[i]);
- }
- providers.push({ name: "netbird", displayName: "NetBird", interface: "wt0" });
- Config.utilities.vpn.provider = providers;
- Config.save();
- 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 < Config.utilities.vpn.provider.length; i++) {
- providers.push(Config.utilities.vpn.provider[i]);
- }
- providers.push({ name: "tailscale", displayName: "Tailscale", interface: "tailscale0" });
- Config.utilities.vpn.provider = providers;
- Config.save();
- 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 < Config.utilities.vpn.provider.length; i++) {
- providers.push(Config.utilities.vpn.provider[i]);
- }
- providers.push({ name: "warp", displayName: "Cloudflare WARP", interface: "CloudflareWARP" });
- Config.utilities.vpn.provider = providers;
- Config.save();
- vpnDialog.closeWithAnimation();
- }
- }
-
- TextButton {
- Layout.fillWidth: true
- text: qsTr("WireGuard (Custom)")
- inactiveColour: Colours.tPalette.m3surfaceContainerHigh
- inactiveOnColour: Colours.palette.m3onSurface
- onClicked: {
- vpnDialog.showAddForm("wireguard", "WireGuard");
- }
- }
-
- Item { Layout.preferredHeight: Appearance.spacing.small }
-
- TextButton {
- Layout.fillWidth: true
- text: qsTr("Cancel")
- inactiveColour: Colours.palette.m3secondaryContainer
- inactiveOnColour: Colours.palette.m3onSecondaryContainer
- onClicked: vpnDialog.closeWithAnimation()
- }
- }
-
- ColumnLayout {
- id: formContent
-
- anchors.fill: parent
- spacing: Appearance.spacing.normal
- visible: vpnDialog.currentState === "form"
- opacity: vpnDialog.currentState === "form" ? 1 : 0
-
- Behavior on opacity {
- NumberAnimation {
- duration: Appearance.anim.durations.small
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
-
- StyledText {
- text: vpnDialog.editIndex >= 0 ? qsTr("Edit VPN Provider") : qsTr("Add %1 VPN").arg(vpnDialog.displayName)
- font.pointSize: Appearance.font.size.large
- font.weight: 500
- }
-
- ColumnLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.smaller / 2
-
- StyledText {
- text: qsTr("Display Name")
- font.pointSize: Appearance.font.size.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: Appearance.rounding.small
- 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 - Appearance.padding.normal
- horizontalAlignment: TextInput.AlignLeft
- text: vpnDialog.displayName
- onTextChanged: vpnDialog.displayName = text
- }
- }
- }
-
- ColumnLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.smaller / 2
-
- StyledText {
- text: qsTr("Interface (e.g., wg0, torguard)")
- font.pointSize: Appearance.font.size.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: Appearance.rounding.small
- 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 - Appearance.padding.normal
- horizontalAlignment: TextInput.AlignLeft
- text: vpnDialog.interfaceName
- onTextChanged: vpnDialog.interfaceName = text
- }
- }
- }
-
- Item { Layout.preferredHeight: Appearance.spacing.normal }
-
- RowLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.normal
-
- 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: vpnDialog.interfaceName.length > 0
- inactiveColour: Colours.palette.m3primaryContainer
- inactiveOnColour: Colours.palette.m3onPrimaryContainer
-
- onClicked: {
- const providers = [];
- const newProvider = {
- name: vpnDialog.providerName,
- displayName: vpnDialog.displayName || vpnDialog.interfaceName,
- interface: vpnDialog.interfaceName
- };
-
- if (vpnDialog.editIndex >= 0) {
- for (let i = 0; i < Config.utilities.vpn.provider.length; i++) {
- if (i === vpnDialog.editIndex) {
- providers.push(newProvider);
- } else {
- providers.push(Config.utilities.vpn.provider[i]);
- }
- }
- } else {
- for (let i = 0; i < Config.utilities.vpn.provider.length; i++) {
- providers.push(Config.utilities.vpn.provider[i]);
- }
- providers.push(newProvider);
- }
-
- Config.utilities.vpn.provider = providers;
- Config.save();
- vpnDialog.closeWithAnimation();
- }
- }
- }
- }
- }
- }
-}
diff --git a/modules/controlcenter/network/VpnSettings.qml b/modules/controlcenter/network/VpnSettings.qml
deleted file mode 100644
index 7387ddc..0000000
--- a/modules/controlcenter/network/VpnSettings.qml
+++ /dev/null
@@ -1,232 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import "../components"
-import qs.components
-import qs.components.controls
-import qs.components.containers
-import qs.components.effects
-import qs.services
-import qs.config
-import Quickshell
-import QtQuick
-import QtQuick.Controls
-import QtQuick.Layouts
-
-ColumnLayout {
- id: root
-
- required property Session session
-
- spacing: Appearance.spacing.normal
-
- SettingsHeader {
- icon: "vpn_key"
- title: qsTr("VPN Settings")
- }
-
- SectionHeader {
- Layout.topMargin: Appearance.spacing.large
- title: qsTr("General")
- description: qsTr("VPN configuration")
- }
-
- SectionContainer {
- ToggleRow {
- label: qsTr("VPN enabled")
- checked: Config.utilities.vpn.enabled
- toggle.onToggled: {
- Config.utilities.vpn.enabled = checked;
- Config.save();
- }
- }
- }
-
- SectionHeader {
- Layout.topMargin: Appearance.spacing.large
- title: qsTr("Providers")
- description: qsTr("Manage VPN providers")
- }
-
- SectionContainer {
- contentSpacing: Appearance.spacing.normal
-
- ListView {
- Layout.fillWidth: true
- Layout.preferredHeight: contentHeight
-
- interactive: false
- spacing: Appearance.spacing.smaller
-
- model: ScriptModel {
- values: Config.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
- color: Colours.tPalette.m3surfaceContainerHigh
- radius: Appearance.rounding.normal
-
- RowLayout {
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- anchors.margins: Appearance.padding.normal
- spacing: Appearance.spacing.normal
-
- MaterialIcon {
- text: modelData.isActive ? "vpn_key" : "vpn_key_off"
- font.pointSize: Appearance.font.size.large
- color: modelData.isActive ? Colours.palette.m3primary : Colours.palette.m3outline
- }
-
- ColumnLayout {
- Layout.fillWidth: true
- spacing: 0
-
- StyledText {
- text: modelData.displayName
- font.weight: modelData.isActive ? 500 : 400
- }
-
- StyledText {
- text: qsTr("%1 • %2").arg(modelData.name).arg(modelData.interface || qsTr("No interface"))
- font.pointSize: Appearance.font.size.small
- color: Colours.palette.m3outline
- }
- }
-
- IconButton {
- icon: modelData.isActive ? "arrow_downward" : "arrow_upward"
- visible: !modelData.isActive || Config.utilities.vpn.provider.length > 1
- onClicked: {
- if (modelData.isActive && index < Config.utilities.vpn.provider.length - 1) {
- // Move down
- const providers = [...Config.utilities.vpn.provider];
- const temp = providers[index];
- providers[index] = providers[index + 1];
- providers[index + 1] = temp;
- Config.utilities.vpn.provider = providers;
- Config.save();
- } else if (!modelData.isActive) {
- // Make active (move to top)
- const providers = [...Config.utilities.vpn.provider];
- const provider = providers.splice(index, 1)[0];
- providers.unshift(provider);
- Config.utilities.vpn.provider = providers;
- Config.save();
- }
- }
- }
-
- IconButton {
- icon: "delete"
- onClicked: {
- const providers = [...Config.utilities.vpn.provider];
- providers.splice(index, 1);
- Config.utilities.vpn.provider = providers;
- Config.save();
- }
- }
- }
-
- implicitHeight: 60
- }
- }
- }
-
- TextButton {
- Layout.fillWidth: true
- Layout.topMargin: Appearance.spacing.normal
- text: qsTr("+ Add Provider")
- inactiveColour: Colours.palette.m3primaryContainer
- inactiveOnColour: Colours.palette.m3onPrimaryContainer
-
- onClicked: {
- addProviderDialog.open();
- }
- }
- }
-
- SectionHeader {
- Layout.topMargin: Appearance.spacing.large
- title: qsTr("Quick Add")
- description: qsTr("Add common VPN providers")
- }
-
- SectionContainer {
- contentSpacing: Appearance.spacing.smaller
-
- TextButton {
- Layout.fillWidth: true
- text: qsTr("+ Add NetBird")
- inactiveColour: Colours.tPalette.m3surfaceContainerHigh
- inactiveOnColour: Colours.palette.m3onSurface
-
- onClicked: {
- const providers = [...Config.utilities.vpn.provider];
- providers.push({
- name: "netbird",
- displayName: "NetBird",
- interface: "wt0"
- });
- Config.utilities.vpn.provider = providers;
- Config.save();
- }
- }
-
- TextButton {
- Layout.fillWidth: true
- text: qsTr("+ Add Tailscale")
- inactiveColour: Colours.tPalette.m3surfaceContainerHigh
- inactiveOnColour: Colours.palette.m3onSurface
-
- onClicked: {
- const providers = [...Config.utilities.vpn.provider];
- providers.push({
- name: "tailscale",
- displayName: "Tailscale",
- interface: "tailscale0"
- });
- Config.utilities.vpn.provider = providers;
- Config.save();
- }
- }
-
- TextButton {
- Layout.fillWidth: true
- text: qsTr("+ Add Cloudflare WARP")
- inactiveColour: Colours.tPalette.m3surfaceContainerHigh
- inactiveOnColour: Colours.palette.m3onSurface
-
- onClicked: {
- const providers = [...Config.utilities.vpn.provider];
- providers.push({
- name: "warp",
- displayName: "Cloudflare WARP",
- interface: "CloudflareWARP"
- });
- Config.utilities.vpn.provider = providers;
- Config.save();
- }
- }
- }
-}
diff --git a/modules/controlcenter/state/VpnState.qml b/modules/controlcenter/state/VpnState.qml
deleted file mode 100644
index aa911f1..0000000
--- 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 917b73a..0000000
--- a/modules/controlcenter/taskbar/TaskbarPane.qml
+++ /dev/null
@@ -1,646 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import "../components"
-import qs.components
-import qs.components.controls
-import qs.components.effects
-import qs.components.containers
-import qs.services
-import qs.config
-import qs.utils
-import Quickshell
-import Quickshell.Widgets
-import QtQuick
-import QtQuick.Layouts
-
-Item {
- id: root
-
- required property Session session
-
- property bool clockShowIcon: Config.bar.clock.showIcon ?? true
- 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 bool workspacesPerMonitor: Config.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
-
- 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
- });
- }
- }
- }
-
- function saveConfig(entryIndex, entryEnabled) {
- Config.bar.clock.showIcon = root.clockShowIcon;
- Config.bar.persistent = root.persistent;
- Config.bar.showOnHover = root.showOnHover;
- Config.bar.dragThreshold = root.dragThreshold;
- Config.bar.status.showAudio = root.showAudio;
- Config.bar.status.showMicrophone = root.showMicrophone;
- Config.bar.status.showKbLayout = root.showKbLayout;
- Config.bar.status.showNetwork = root.showNetwork;
- Config.bar.status.showWifi = root.showWifi;
- Config.bar.status.showBluetooth = root.showBluetooth;
- Config.bar.status.showBattery = root.showBattery;
- Config.bar.status.showLockStatus = root.showLockStatus;
- Config.bar.tray.background = root.trayBackground;
- Config.bar.tray.compact = root.trayCompact;
- Config.bar.tray.recolour = root.trayRecolour;
- Config.bar.workspaces.shown = root.workspacesShown;
- Config.bar.workspaces.activeIndicator = root.workspacesActiveIndicator;
- Config.bar.workspaces.occupiedBg = root.workspacesOccupiedBg;
- Config.bar.workspaces.showWindows = root.workspacesShowWindows;
- Config.bar.workspaces.perMonitorWorkspaces = root.workspacesPerMonitor;
- Config.bar.scrollActions.workspaces = root.scrollWorkspaces;
- Config.bar.scrollActions.volume = root.scrollVolume;
- Config.bar.scrollActions.brightness = root.scrollBrightness;
- Config.bar.popouts.activeWindow = root.popoutActiveWindow;
- Config.bar.popouts.tray = root.popoutTray;
- Config.bar.popouts.statusIcons = root.popoutStatusIcons;
-
- 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
- });
- }
- Config.bar.entries = entries;
- Config.save();
- }
-
- ListModel {
- id: entriesModel
- }
-
- ClippingRectangle {
- id: taskbarClippingRect
- anchors.fill: parent
- anchors.margins: Appearance.padding.normal
- anchors.leftMargin: 0
- anchors.rightMargin: Appearance.padding.normal
-
- radius: taskbarBorder.innerRadius
- color: "transparent"
-
- Loader {
- id: taskbarLoader
-
- anchors.fill: parent
- anchors.margins: Appearance.padding.large + Appearance.padding.normal
- anchors.leftMargin: Appearance.padding.large
- anchors.rightMargin: Appearance.padding.large
-
- sourceComponent: taskbarContentComponent
- }
- }
-
- InnerBorder {
- id: taskbarBorder
- leftThickness: 0
- rightThickness: Appearance.padding.normal
- }
-
- 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: Appearance.spacing.normal
-
- RowLayout {
- spacing: Appearance.spacing.smaller
-
- StyledText {
- text: qsTr("Taskbar")
- font.pointSize: Appearance.font.size.large
- font.weight: 500
- }
- }
-
- SectionContainer {
- Layout.fillWidth: true
- alignTop: true
-
- StyledText {
- text: qsTr("Status Icons")
- font.pointSize: Appearance.font.size.normal
- }
-
- 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: Appearance.spacing.normal
-
- ColumnLayout {
- id: leftColumnLayout
- Layout.fillWidth: true
- Layout.alignment: Qt.AlignTop
- spacing: Appearance.spacing.normal
-
- SectionContainer {
- Layout.fillWidth: true
- alignTop: true
-
- StyledText {
- text: qsTr("Workspaces")
- font.pointSize: Appearance.font.size.normal
- }
-
- StyledRect {
- Layout.fillWidth: true
- implicitHeight: workspacesShownRow.implicitHeight + Appearance.padding.large * 2
- radius: Appearance.rounding.normal
- 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: Appearance.padding.large
- spacing: Appearance.spacing.normal
-
- 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 + Appearance.padding.large * 2
- radius: Appearance.rounding.normal
- 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: Appearance.padding.large
- spacing: Appearance.spacing.normal
-
- 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 + Appearance.padding.large * 2
- radius: Appearance.rounding.normal
- 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: Appearance.padding.large
- spacing: Appearance.spacing.normal
-
- 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 + Appearance.padding.large * 2
- radius: Appearance.rounding.normal
- 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: Appearance.padding.large
- spacing: Appearance.spacing.normal
-
- StyledText {
- Layout.fillWidth: true
- text: qsTr("Show windows")
- }
-
- StyledSwitch {
- checked: root.workspacesShowWindows
- onToggled: {
- root.workspacesShowWindows = checked;
- root.saveConfig();
- }
- }
- }
- }
-
- StyledRect {
- Layout.fillWidth: true
- implicitHeight: workspacesPerMonitorRow.implicitHeight + Appearance.padding.large * 2
- radius: Appearance.rounding.normal
- 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: Appearance.padding.large
- spacing: Appearance.spacing.normal
-
- 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.pointSize: Appearance.font.size.normal
- }
-
- 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: Appearance.spacing.normal
-
- SectionContainer {
- Layout.fillWidth: true
- alignTop: true
-
- StyledText {
- text: qsTr("Clock")
- font.pointSize: Appearance.font.size.normal
- }
-
- 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.pointSize: Appearance.font.size.normal
- }
-
- 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: Appearance.spacing.normal
-
- 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();
- }
- }
- }
- }
- }
-
- ColumnLayout {
- id: rightColumnLayout
- Layout.fillWidth: true
- Layout.alignment: Qt.AlignTop
- spacing: Appearance.spacing.normal
-
- SectionContainer {
- Layout.fillWidth: true
- alignTop: true
-
- StyledText {
- text: qsTr("Popouts")
- font.pointSize: Appearance.font.size.normal
- }
-
- 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.pointSize: Appearance.font.size.normal
- }
-
- 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();
- }
- }
- ]
- }
- }
- }
- }
-
- }
- }
- }
-}
diff --git a/modules/launcher/items/SchemeItem.qml b/modules/launcher/items/SchemeItem.qml
deleted file mode 100644
index 3ff1846..0000000
--- a/modules/launcher/items/SchemeItem.qml
+++ /dev/null
@@ -1,104 +0,0 @@
-import "../services"
-import qs.components
-import qs.services
-import qs.config
-import QtQuick
-
-Item {
- id: root
-
- required property Schemes.Scheme modelData
- required property var list
-
- implicitHeight: Config.launcher.sizes.itemHeight
-
- anchors.left: parent?.left
- anchors.right: parent?.right
-
- StateLayer {
- radius: Appearance.rounding.normal
-
- function onClicked(): void {
- root.modelData?.onClicked(root.list);
- }
- }
-
- Item {
- anchors.fill: parent
- anchors.leftMargin: Appearance.padding.larger
- anchors.rightMargin: Appearance.padding.larger
- anchors.margins: Appearance.padding.smaller
-
- StyledRect {
- id: preview
-
- anchors.verticalCenter: parent.verticalCenter
-
- border.width: 1
- border.color: Qt.alpha(`#${root.modelData?.colours?.outline}`, 0.5)
-
- color: `#${root.modelData?.colours?.surface}`
- radius: Appearance.rounding.full
- implicitWidth: parent.height * 0.8
- implicitHeight: parent.height * 0.8
-
- 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: `#${root.modelData?.colours?.primary}`
- radius: Appearance.rounding.full
- }
- }
- }
-
- Column {
- anchors.left: preview.right
- anchors.leftMargin: Appearance.spacing.normal
- anchors.verticalCenter: parent.verticalCenter
-
- width: parent.width - preview.width - anchors.leftMargin - (current.active ? current.width + Appearance.spacing.normal : 0)
- spacing: 0
-
- StyledText {
- text: root.modelData?.flavour ?? ""
- font.pointSize: Appearance.font.size.normal
- }
-
- StyledText {
- text: root.modelData?.name ?? ""
- font.pointSize: Appearance.font.size.small
- color: Colours.palette.m3outline
-
- elide: Text.ElideRight
- anchors.left: parent.left
- anchors.right: parent.right
- }
- }
-
- Loader {
- id: current
-
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
-
- active: `${root.modelData?.name} ${root.modelData?.flavour}` === Schemes.currentScheme
-
- sourceComponent: MaterialIcon {
- text: "check"
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: Appearance.font.size.large
- }
- }
- }
-}
diff --git a/modules/launcher/items/VariantItem.qml b/modules/launcher/items/VariantItem.qml
deleted file mode 100644
index 5c34fa8..0000000
--- a/modules/launcher/items/VariantItem.qml
+++ /dev/null
@@ -1,80 +0,0 @@
-import "../services"
-import qs.components
-import qs.services
-import qs.config
-import QtQuick
-
-Item {
- id: root
-
- required property M3Variants.Variant modelData
- required property var list
-
- implicitHeight: Config.launcher.sizes.itemHeight
-
- anchors.left: parent?.left
- anchors.right: parent?.right
-
- StateLayer {
- radius: Appearance.rounding.normal
-
- function onClicked(): void {
- root.modelData?.onClicked(root.list);
- }
- }
-
- Item {
- anchors.fill: parent
- anchors.leftMargin: Appearance.padding.larger
- anchors.rightMargin: Appearance.padding.larger
- anchors.margins: Appearance.padding.smaller
-
- MaterialIcon {
- id: icon
-
- text: root.modelData?.icon ?? ""
- font.pointSize: Appearance.font.size.extraLarge
-
- anchors.verticalCenter: parent.verticalCenter
- }
-
- Column {
- anchors.left: icon.right
- anchors.leftMargin: Appearance.spacing.larger
- anchors.verticalCenter: icon.verticalCenter
-
- width: parent.width - icon.width - anchors.leftMargin - (current.active ? current.width + Appearance.spacing.normal : 0)
- spacing: 0
-
- StyledText {
- text: root.modelData?.name ?? ""
- font.pointSize: Appearance.font.size.normal
- }
-
- StyledText {
- text: root.modelData?.description ?? ""
- font.pointSize: Appearance.font.size.small
- color: Colours.palette.m3outline
-
- elide: Text.ElideRight
- anchors.left: parent.left
- anchors.right: parent.right
- }
- }
-
- Loader {
- id: current
-
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
-
- active: root.modelData?.variant === Schemes.currentVariant
-
- sourceComponent: MaterialIcon {
- text: "check"
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: Appearance.font.size.large
- }
- }
- }
-}
diff --git a/modules/launcher/services/Apps.qml b/modules/launcher/services/Apps.qml
index 79f3754..cb334fb 100644
--- a/modules/launcher/services/Apps.qml
+++ b/modules/launcher/services/Apps.qml
@@ -66,7 +66,7 @@ Searcher {
}
list: appDb.apps
- useFuzzy: Config.launcher.useFuzzy.apps
+ useFuzzy: Config.launcher.useFuzzy
AppDb {
id: appDb
diff --git a/modules/lock/Center.qml b/modules/lock/Center.qml
deleted file mode 100644
index a120f5b..0000000
--- a/modules/lock/Center.qml
+++ /dev/null
@@ -1,415 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.components
-import qs.components.controls
-import qs.services
-import qs.config
-import qs.utils
-import QtQuick
-import QtQuick.Layouts
-
-ColumnLayout {
- id: root
-
- required property var lock
- readonly property real centerScale: Math.min(1, (lock.screen?.height ?? 1440) / 1440)
- readonly property int centerWidth: Config.lock.sizes.centerWidth * centerScale
-
- Layout.preferredWidth: centerWidth
- Layout.fillWidth: false
- Layout.fillHeight: true
-
- spacing: Appearance.spacing.large * 2
-
- RowLayout {
- Layout.alignment: Qt.AlignHCenter
- spacing: Appearance.spacing.small
-
- StyledText {
- Layout.alignment: Qt.AlignVCenter
- text: Time.hourStr
- color: Colours.palette.m3secondary
- font.pointSize: Math.floor(Appearance.font.size.extraLarge * 3 * root.centerScale)
- font.family: Appearance.font.family.clock
- font.bold: true
- }
-
- StyledText {
- Layout.alignment: Qt.AlignVCenter
- text: ":"
- color: Colours.palette.m3primary
- font.pointSize: Math.floor(Appearance.font.size.extraLarge * 3 * root.centerScale)
- font.family: Appearance.font.family.clock
- font.bold: true
- }
-
- StyledText {
- Layout.alignment: Qt.AlignVCenter
- text: Time.minuteStr
- color: Colours.palette.m3secondary
- font.pointSize: Math.floor(Appearance.font.size.extraLarge * 3 * root.centerScale)
- font.family: Appearance.font.family.clock
- font.bold: true
- }
-
- Loader {
- Layout.leftMargin: Appearance.spacing.small
- Layout.alignment: Qt.AlignVCenter
-
- active: Config.services.useTwelveHourClock
- visible: active
-
- sourceComponent: StyledText {
- text: Time.amPmStr
- color: Colours.palette.m3primary
- font.pointSize: Math.floor(Appearance.font.size.extraLarge * 2 * root.centerScale)
- font.family: Appearance.font.family.clock
- font.bold: true
- }
- }
- }
-
- StyledText {
- Layout.alignment: Qt.AlignHCenter
- Layout.topMargin: -Appearance.padding.large * 2
-
- text: Time.format("dddd, d MMMM yyyy")
- color: Colours.palette.m3tertiary
- font.pointSize: Math.floor(Appearance.font.size.extraLarge * root.centerScale)
- font.family: Appearance.font.family.mono
- font.bold: true
- }
-
- StyledClippingRect {
- Layout.topMargin: Appearance.spacing.large * 2
- Layout.alignment: Qt.AlignHCenter
-
- implicitWidth: root.centerWidth / 2
- implicitHeight: root.centerWidth / 2
-
- color: Colours.tPalette.m3surfaceContainer
- radius: Appearance.rounding.full
-
- MaterialIcon {
- anchors.centerIn: parent
-
- text: "person"
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: Math.floor(root.centerWidth / 4)
- }
-
- Image {
- id: pfp
-
- anchors.fill: parent
- source: Paths.face
- }
- }
-
- StyledRect {
- Layout.alignment: Qt.AlignHCenter
-
- implicitWidth: root.centerWidth * 0.8
- implicitHeight: input.implicitHeight + Appearance.padding.small * 2
-
- color: Colours.tPalette.m3surfaceContainer
- radius: Appearance.rounding.full
-
- focus: true
- onActiveFocusChanged: {
- if (!activeFocus)
- forceActiveFocus();
- }
-
- Keys.onPressed: event => {
- if (root.lock.unlocking)
- return;
-
- if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return)
- inputField.placeholder.animate = false;
-
- root.lock.pam.handleKey(event);
- }
-
- StateLayer {
- hoverEnabled: false
- cursorShape: Qt.IBeamCursor
-
- function onClicked(): void {
- parent.forceActiveFocus();
- }
- }
-
- RowLayout {
- id: input
-
- anchors.fill: parent
- anchors.margins: Appearance.padding.small
- spacing: Appearance.spacing.normal
-
- Item {
- implicitWidth: implicitHeight
- implicitHeight: fprintIcon.implicitHeight + Appearance.padding.small * 2
-
- MaterialIcon {
- id: fprintIcon
-
- anchors.centerIn: parent
- animate: true
- text: {
- if (root.lock.pam.fprint.tries >= Config.lock.maxFprintTries)
- return "fingerprint_off";
- if (root.lock.pam.fprint.active)
- return "fingerprint";
- return "lock";
- }
- color: root.lock.pam.fprint.tries >= Config.lock.maxFprintTries ? Colours.palette.m3error : Colours.palette.m3onSurface
- opacity: root.lock.pam.passwd.active ? 0 : 1
-
- Behavior on opacity {
- Anim {}
- }
- }
-
- CircularIndicator {
- anchors.fill: parent
- running: root.lock.pam.passwd.active
- }
- }
-
- InputField {
- id: inputField
-
- pam: root.lock.pam
- }
-
- StyledRect {
- implicitWidth: implicitHeight
- implicitHeight: enterIcon.implicitHeight + Appearance.padding.small * 2
-
- color: root.lock.pam.buffer ? Colours.palette.m3primary : Colours.layer(Colours.palette.m3surfaceContainerHigh, 2)
- radius: Appearance.rounding.full
-
- StateLayer {
- color: root.lock.pam.buffer ? Colours.palette.m3onPrimary : Colours.palette.m3onSurface
-
- function onClicked(): void {
- root.lock.pam.passwd.start();
- }
- }
-
- MaterialIcon {
- id: enterIcon
-
- anchors.centerIn: parent
- text: "arrow_forward"
- color: root.lock.pam.buffer ? Colours.palette.m3onPrimary : Colours.palette.m3onSurface
- font.weight: 500
- }
- }
- }
- }
-
- Item {
- Layout.fillWidth: true
- Layout.topMargin: -Appearance.spacing.large
-
- implicitHeight: Math.max(message.implicitHeight, stateMessage.implicitHeight)
-
- Behavior on implicitHeight {
- Anim {}
- }
-
- StyledText {
- id: stateMessage
-
- readonly property string msg: {
- if (Hypr.kbLayout !== Hypr.defaultKbLayout) {
- if (Hypr.capsLock && Hypr.numLock)
- return qsTr("Caps lock and Num lock are ON.\nKeyboard layout: %1").arg(Hypr.kbLayoutFull);
- if (Hypr.capsLock)
- return qsTr("Caps lock is ON. Kb layout: %1").arg(Hypr.kbLayoutFull);
- if (Hypr.numLock)
- return qsTr("Num lock is ON. Kb layout: %1").arg(Hypr.kbLayoutFull);
- return qsTr("Keyboard layout: %1").arg(Hypr.kbLayoutFull);
- }
-
- if (Hypr.capsLock && Hypr.numLock)
- return qsTr("Caps lock and Num lock are ON.");
- if (Hypr.capsLock)
- return qsTr("Caps lock is ON.");
- if (Hypr.numLock)
- return qsTr("Num lock is ON.");
-
- return "";
- }
-
- property bool shouldBeVisible
-
- onMsgChanged: {
- if (msg) {
- if (opacity > 0) {
- animate = true;
- text = msg;
- animate = false;
- } else {
- text = msg;
- }
- shouldBeVisible = true;
- } else {
- shouldBeVisible = false;
- }
- }
-
- anchors.left: parent.left
- anchors.right: parent.right
-
- scale: shouldBeVisible && !message.msg ? 1 : 0.7
- opacity: shouldBeVisible && !message.msg ? 1 : 0
- color: Colours.palette.m3onSurfaceVariant
- animateProp: "opacity"
-
- font.family: Appearance.font.family.mono
- horizontalAlignment: Qt.AlignHCenter
- wrapMode: Text.WrapAtWordBoundaryOrAnywhere
- lineHeight: 1.2
-
- Behavior on scale {
- Anim {}
- }
-
- Behavior on opacity {
- Anim {}
- }
- }
-
- StyledText {
- id: message
-
- readonly property Pam pam: root.lock.pam
- readonly property string msg: {
- if (pam.fprintState === "error")
- return qsTr("FP ERROR: %1").arg(pam.fprint.message);
- if (pam.state === "error")
- return qsTr("PW ERROR: %1").arg(pam.passwd.message);
-
- if (pam.lockMessage)
- return pam.lockMessage;
-
- if (pam.state === "max" && pam.fprintState === "max")
- return qsTr("Maximum password and fingerprint attempts reached.");
- if (pam.state === "max") {
- if (pam.fprint.available)
- return qsTr("Maximum password attempts reached. Please use fingerprint.");
- return qsTr("Maximum password attempts reached.");
- }
- if (pam.fprintState === "max")
- return qsTr("Maximum fingerprint attempts reached. Please use password.");
-
- if (pam.state === "fail") {
- if (pam.fprint.available)
- return qsTr("Incorrect password. Please try again or use fingerprint.");
- return qsTr("Incorrect password. Please try again.");
- }
- if (pam.fprintState === "fail")
- return qsTr("Fingerprint not recognized (%1/%2). Please try again or use password.").arg(pam.fprint.tries).arg(Config.lock.maxFprintTries);
-
- return "";
- }
-
- anchors.left: parent.left
- anchors.right: parent.right
-
- scale: 0.7
- opacity: 0
- color: Colours.palette.m3error
-
- font.pointSize: Appearance.font.size.small
- font.family: Appearance.font.family.mono
- horizontalAlignment: Qt.AlignHCenter
- wrapMode: Text.WrapAtWordBoundaryOrAnywhere
-
- onMsgChanged: {
- if (msg) {
- if (opacity > 0) {
- animate = true;
- text = msg;
- animate = false;
-
- exitAnim.stop();
- if (scale < 1)
- appearAnim.restart();
- else
- flashAnim.restart();
- } else {
- text = msg;
- exitAnim.stop();
- appearAnim.restart();
- }
- } else {
- appearAnim.stop();
- flashAnim.stop();
- exitAnim.start();
- }
- }
-
- Connections {
- target: root.lock.pam
-
- function onFlashMsg(): void {
- exitAnim.stop();
- if (message.scale < 1)
- appearAnim.restart();
- else
- flashAnim.restart();
- }
- }
-
- Anim {
- id: appearAnim
-
- target: message
- properties: "scale,opacity"
- to: 1
- onFinished: flashAnim.restart()
- }
-
- SequentialAnimation {
- id: flashAnim
-
- loops: 2
-
- FlashAnim {
- to: 0.3
- }
- FlashAnim {
- to: 1
- }
- }
-
- ParallelAnimation {
- id: exitAnim
-
- Anim {
- target: message
- property: "scale"
- to: 0.7
- duration: Appearance.anim.durations.large
- }
- Anim {
- target: message
- property: "opacity"
- to: 0
- duration: Appearance.anim.durations.large
- }
- }
- }
- }
-
- component FlashAnim: NumberAnimation {
- target: message
- property: "opacity"
- duration: Appearance.anim.durations.small
- easing.type: Easing.Linear
- }
-}
diff --git a/modules/lock/Fetch.qml b/modules/lock/Fetch.qml
deleted file mode 100644
index ded5608..0000000
--- a/modules/lock/Fetch.qml
+++ /dev/null
@@ -1,165 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.components
-import qs.components.effects
-import qs.services
-import qs.config
-import qs.utils
-import Quickshell.Services.UPower
-import QtQuick
-import QtQuick.Layouts
-
-ColumnLayout {
- id: root
-
- anchors.fill: parent
- anchors.margins: Appearance.padding.large * 2
- anchors.topMargin: Appearance.padding.large
-
- spacing: Appearance.spacing.small
-
- RowLayout {
- Layout.fillWidth: true
- Layout.fillHeight: false
- spacing: Appearance.spacing.normal
-
- StyledRect {
- implicitWidth: prompt.implicitWidth + Appearance.padding.normal * 2
- implicitHeight: prompt.implicitHeight + Appearance.padding.normal * 2
-
- color: Colours.palette.m3primary
- radius: Appearance.rounding.small
-
- MonoText {
- id: prompt
-
- anchors.centerIn: parent
- text: ">"
- font.pointSize: root.width > 400 ? Appearance.font.size.larger : Appearance.font.size.normal
- color: Colours.palette.m3onPrimary
- }
- }
-
- MonoText {
- Layout.fillWidth: true
- text: "caelestiafetch.sh"
- font.pointSize: root.width > 400 ? Appearance.font.size.larger : Appearance.font.size.normal
- elide: Text.ElideRight
- }
-
- WrappedLoader {
- Layout.fillHeight: true
- active: !iconLoader.active
-
- sourceComponent: OsLogo {}
- }
- }
-
- RowLayout {
- Layout.fillWidth: true
- Layout.fillHeight: false
- spacing: height * 0.15
-
- WrappedLoader {
- id: iconLoader
-
- Layout.fillHeight: true
- active: root.width > 320
-
- sourceComponent: OsLogo {}
- }
-
- ColumnLayout {
- Layout.fillWidth: true
- Layout.topMargin: Appearance.padding.normal
- Layout.bottomMargin: Appearance.padding.normal
- Layout.leftMargin: iconLoader.active ? 0 : width * 0.1
- spacing: Appearance.spacing.normal
-
- WrappedLoader {
- Layout.fillWidth: true
- active: !batLoader.active && root.height > 200
-
- sourceComponent: FetchText {
- text: `OS : ${SysInfo.osPrettyName || SysInfo.osName}`
- }
- }
-
- WrappedLoader {
- Layout.fillWidth: true
- active: root.height > (batLoader.active ? 200 : 110)
-
- sourceComponent: FetchText {
- text: `WM : ${SysInfo.wm}`
- }
- }
-
- WrappedLoader {
- Layout.fillWidth: true
- active: !batLoader.active || root.height > 110
-
- sourceComponent: FetchText {
- text: `USER: ${SysInfo.user}`
- }
- }
-
- FetchText {
- text: `UP : ${SysInfo.uptime}`
- }
-
- WrappedLoader {
- id: batLoader
-
- Layout.fillWidth: true
- active: UPower.displayDevice.isLaptopBattery
-
- sourceComponent: FetchText {
- text: `BATT: ${[UPowerDeviceState.Charging, UPowerDeviceState.FullyCharged, UPowerDeviceState.PendingCharge].includes(UPower.displayDevice.state) ? "(+) " : ""}${Math.round(UPower.displayDevice.percentage * 100)}%`
- }
- }
- }
- }
-
- WrappedLoader {
- Layout.alignment: Qt.AlignHCenter
- active: root.height > 180
-
- sourceComponent: RowLayout {
- spacing: Appearance.spacing.large
-
- Repeater {
- model: Math.max(0, Math.min(8, root.width / (Appearance.font.size.larger * 2 + Appearance.spacing.large)))
-
- StyledRect {
- required property int index
-
- implicitWidth: implicitHeight
- implicitHeight: Appearance.font.size.larger * 2
- color: Colours.palette[`term${index}`]
- radius: Appearance.rounding.small
- }
- }
- }
- }
-
- component WrappedLoader: Loader {
- visible: active
- }
-
- component OsLogo: ColouredIcon {
- source: SysInfo.osLogo
- implicitSize: height
- colour: Colours.palette.m3primary
- layer.enabled: Config.lock.recolourLogo || SysInfo.isDefaultLogo
- }
-
- component FetchText: MonoText {
- Layout.fillWidth: true
- font.pointSize: root.width > 400 ? Appearance.font.size.larger : Appearance.font.size.normal
- elide: Text.ElideRight
- }
-
- component MonoText: StyledText {
- font.family: Appearance.font.family.mono
- }
-}
diff --git a/modules/lock/NotifDock.qml b/modules/lock/NotifDock.qml
deleted file mode 100644
index 01f7e4b..0000000
--- a/modules/lock/NotifDock.qml
+++ /dev/null
@@ -1,145 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.components
-import qs.components.containers
-import qs.components.effects
-import qs.services
-import qs.config
-import Quickshell
-import Quickshell.Widgets
-import QtQuick
-import QtQuick.Layouts
-
-ColumnLayout {
- id: root
-
- required property var lock
-
- anchors.fill: parent
- anchors.margins: Appearance.padding.large
-
- spacing: Appearance.spacing.smaller
-
- StyledText {
- Layout.fillWidth: true
- text: Notifs.list.length > 0 ? qsTr("%1 notification%2").arg(Notifs.list.length).arg(Notifs.list.length === 1 ? "" : "s") : qsTr("Notifications")
- color: Colours.palette.m3outline
- font.family: Appearance.font.family.mono
- font.weight: 500
- elide: Text.ElideRight
- }
-
- ClippingRectangle {
- id: clipRect
-
- Layout.fillWidth: true
- Layout.fillHeight: true
-
- radius: Appearance.rounding.small
- color: "transparent"
-
- Loader {
- anchors.centerIn: parent
- active: opacity > 0
- opacity: Notifs.list.length > 0 ? 0 : 1
-
- sourceComponent: ColumnLayout {
- spacing: Appearance.spacing.large
-
- Image {
- asynchronous: true
- source: Qt.resolvedUrl(`${Quickshell.shellDir}/assets/dino.png`)
- fillMode: Image.PreserveAspectFit
- sourceSize.width: clipRect.width * 0.8
-
- layer.enabled: true
- layer.effect: Colouriser {
- colorizationColor: Colours.palette.m3outlineVariant
- brightness: 1
- }
- }
-
- StyledText {
- Layout.alignment: Qt.AlignHCenter
- text: qsTr("No Notifications")
- color: Colours.palette.m3outlineVariant
- font.pointSize: Appearance.font.size.large
- font.family: Appearance.font.family.mono
- font.weight: 500
- }
- }
-
- Behavior on opacity {
- Anim {
- duration: Appearance.anim.durations.extraLarge
- }
- }
- }
-
- StyledListView {
- anchors.fill: parent
-
- spacing: Appearance.spacing.small
- clip: true
-
- model: ScriptModel {
- values: {
- const list = Notifs.notClosed.map(n => [n.appName, null]);
- return [...new Map(list).keys()];
- }
- }
-
- delegate: NotifGroup {}
-
- add: Transition {
- Anim {
- property: "opacity"
- from: 0
- to: 1
- }
- Anim {
- property: "scale"
- from: 0
- to: 1
- duration: Appearance.anim.durations.expressiveDefaultSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
- }
- }
-
- remove: Transition {
- Anim {
- property: "opacity"
- to: 0
- }
- Anim {
- property: "scale"
- to: 0.6
- }
- }
-
- move: Transition {
- Anim {
- properties: "opacity,scale"
- to: 1
- }
- Anim {
- property: "y"
- duration: Appearance.anim.durations.expressiveDefaultSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
- }
- }
-
- displaced: Transition {
- Anim {
- properties: "opacity,scale"
- to: 1
- }
- Anim {
- property: "y"
- duration: Appearance.anim.durations.expressiveDefaultSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
- }
- }
- }
- }
-}
diff --git a/modules/lock/NotifGroup.qml b/modules/lock/NotifGroup.qml
deleted file mode 100644
index 7796090..0000000
--- a/modules/lock/NotifGroup.qml
+++ /dev/null
@@ -1,316 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.components
-import qs.components.effects
-import qs.services
-import qs.config
-import qs.utils
-import Quickshell
-import Quickshell.Widgets
-import Quickshell.Services.Notifications
-import QtQuick
-import QtQuick.Layouts
-
-StyledRect {
- id: root
-
- required property string modelData
-
- readonly property list<var> notifs: Notifs.list.filter(notif => notif.appName === modelData)
- readonly property string image: notifs.find(n => n.image.length > 0)?.image ?? ""
- readonly property string appIcon: notifs.find(n => n.appIcon.length > 0)?.appIcon ?? ""
- readonly property string urgency: notifs.some(n => n.urgency === NotificationUrgency.Critical) ? "critical" : notifs.some(n => n.urgency === NotificationUrgency.Normal) ? "normal" : "low"
-
- property bool expanded
-
- anchors.left: parent?.left
- anchors.right: parent?.right
- implicitHeight: content.implicitHeight + Appearance.padding.normal * 2
-
- clip: true
- radius: Appearance.rounding.normal
- color: root.urgency === "critical" ? Colours.palette.m3secondaryContainer : Colours.layer(Colours.palette.m3surfaceContainerHigh, 2)
-
- RowLayout {
- id: content
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.top: parent.top
- anchors.margins: Appearance.padding.normal
-
- spacing: Appearance.spacing.normal
-
- Item {
- Layout.alignment: Qt.AlignLeft | Qt.AlignTop
- implicitWidth: Config.notifs.sizes.image
- implicitHeight: Config.notifs.sizes.image
-
- Component {
- id: imageComp
-
- Image {
- source: Qt.resolvedUrl(root.image)
- fillMode: Image.PreserveAspectCrop
- cache: false
- asynchronous: true
- width: Config.notifs.sizes.image
- height: Config.notifs.sizes.image
- }
- }
-
- Component {
- id: appIconComp
-
- ColouredIcon {
- implicitSize: Math.round(Config.notifs.sizes.image * 0.6)
- source: Quickshell.iconPath(root.appIcon)
- colour: root.urgency === "critical" ? Colours.palette.m3onError : root.urgency === "low" ? Colours.palette.m3onSurface : Colours.palette.m3onSecondaryContainer
- layer.enabled: root.appIcon.endsWith("symbolic")
- }
- }
-
- Component {
- id: materialIconComp
-
- MaterialIcon {
- text: Icons.getNotifIcon(root.notifs[0]?.summary, root.urgency)
- color: root.urgency === "critical" ? Colours.palette.m3onError : root.urgency === "low" ? Colours.palette.m3onSurface : Colours.palette.m3onSecondaryContainer
- font.pointSize: Appearance.font.size.large
- }
- }
-
- ClippingRectangle {
- anchors.fill: parent
- color: root.urgency === "critical" ? Colours.palette.m3error : root.urgency === "low" ? Colours.layer(Colours.palette.m3surfaceContainerHighest, 3) : Colours.palette.m3secondaryContainer
- radius: Appearance.rounding.full
-
- Loader {
- anchors.centerIn: parent
- sourceComponent: root.image ? imageComp : root.appIcon ? appIconComp : materialIconComp
- }
- }
-
- Loader {
- anchors.right: parent.right
- anchors.bottom: parent.bottom
- active: root.appIcon && root.image
-
- sourceComponent: StyledRect {
- implicitWidth: Config.notifs.sizes.badge
- implicitHeight: Config.notifs.sizes.badge
-
- color: root.urgency === "critical" ? Colours.palette.m3error : root.urgency === "low" ? Colours.palette.m3surfaceContainerHighest : Colours.palette.m3secondaryContainer
- radius: Appearance.rounding.full
-
- ColouredIcon {
- anchors.centerIn: parent
- implicitSize: Math.round(Config.notifs.sizes.badge * 0.6)
- source: Quickshell.iconPath(root.appIcon)
- colour: root.urgency === "critical" ? Colours.palette.m3onError : root.urgency === "low" ? Colours.palette.m3onSurface : Colours.palette.m3onSecondaryContainer
- layer.enabled: root.appIcon.endsWith("symbolic")
- }
- }
- }
- }
-
- ColumnLayout {
- Layout.topMargin: -Appearance.padding.small
- Layout.bottomMargin: -Appearance.padding.small / 2 - (root.expanded ? 0 : spacing)
- Layout.fillWidth: true
- spacing: Math.round(Appearance.spacing.small / 2)
-
- RowLayout {
- Layout.bottomMargin: -parent.spacing
- Layout.fillWidth: true
- spacing: Appearance.spacing.smaller
-
- StyledText {
- Layout.fillWidth: true
- text: root.modelData
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: Appearance.font.size.small
- elide: Text.ElideRight
- }
-
- StyledText {
- animate: true
- text: root.notifs[0]?.timeStr ?? ""
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.small
- }
-
- StyledRect {
- implicitWidth: expandBtn.implicitWidth + Appearance.padding.smaller * 2
- implicitHeight: groupCount.implicitHeight + Appearance.padding.small
-
- color: root.urgency === "critical" ? Colours.palette.m3error : Colours.layer(Colours.palette.m3surfaceContainerHighest, 2)
- radius: Appearance.rounding.full
-
- opacity: root.notifs.length > Config.notifs.groupPreviewNum ? 1 : 0
- Layout.preferredWidth: root.notifs.length > Config.notifs.groupPreviewNum ? implicitWidth : 0
-
- StateLayer {
- color: root.urgency === "critical" ? Colours.palette.m3onError : Colours.palette.m3onSurface
-
- function onClicked(): void {
- root.expanded = !root.expanded;
- }
- }
-
- RowLayout {
- id: expandBtn
-
- anchors.centerIn: parent
- spacing: Appearance.spacing.small / 2
-
- StyledText {
- id: groupCount
-
- Layout.leftMargin: Appearance.padding.small / 2
- animate: true
- text: root.notifs.length
- color: root.urgency === "critical" ? Colours.palette.m3onError : Colours.palette.m3onSurface
- font.pointSize: Appearance.font.size.small
- }
-
- MaterialIcon {
- Layout.rightMargin: -Appearance.padding.small / 2
- animate: true
- text: root.expanded ? "expand_less" : "expand_more"
- color: root.urgency === "critical" ? Colours.palette.m3onError : Colours.palette.m3onSurface
- }
- }
-
- Behavior on opacity {
- Anim {}
- }
-
- Behavior on Layout.preferredWidth {
- Anim {}
- }
- }
- }
-
- Repeater {
- model: ScriptModel {
- values: root.notifs.slice(0, Config.notifs.groupPreviewNum)
- }
-
- NotifLine {
- id: notif
-
- ParallelAnimation {
- running: true
-
- Anim {
- target: notif
- property: "opacity"
- from: 0
- to: 1
- }
- Anim {
- target: notif
- property: "scale"
- from: 0.7
- to: 1
- }
- Anim {
- target: notif.Layout
- property: "preferredHeight"
- from: 0
- to: notif.implicitHeight
- }
- }
-
- ParallelAnimation {
- running: notif.modelData.closed
- onFinished: notif.modelData.unlock(notif)
-
- Anim {
- target: notif
- property: "opacity"
- to: 0
- }
- Anim {
- target: notif
- property: "scale"
- to: 0.7
- }
- Anim {
- target: notif.Layout
- property: "preferredHeight"
- to: 0
- }
- }
- }
- }
-
- Loader {
- Layout.fillWidth: true
-
- opacity: root.expanded ? 1 : 0
- Layout.preferredHeight: root.expanded ? implicitHeight : 0
- active: opacity > 0
-
- sourceComponent: ColumnLayout {
- Repeater {
- model: ScriptModel {
- values: root.notifs.slice(Config.notifs.groupPreviewNum)
- }
-
- NotifLine {}
- }
- }
-
- Behavior on opacity {
- Anim {}
- }
- }
- }
- }
-
- Behavior on implicitHeight {
- Anim {
- duration: Appearance.anim.durations.expressiveDefaultSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
- }
- }
-
- component NotifLine: StyledText {
- id: notifLine
-
- required property Notifs.Notif modelData
-
- Layout.fillWidth: true
- textFormat: Text.MarkdownText
- text: {
- const summary = modelData.summary.replace(/\n/g, " ");
- const body = modelData.body.replace(/\n/g, " ");
- const colour = root.urgency === "critical" ? Colours.palette.m3secondary : Colours.palette.m3outline;
-
- if (metrics.text === metrics.elidedText)
- return `${summary} <span style='color:${colour}'>${body}</span>`;
-
- const t = metrics.elidedText.length - 3;
- if (t < summary.length)
- return `${summary.slice(0, t)}...`;
-
- return `${summary} <span style='color:${colour}'>${body.slice(0, t - summary.length)}...</span>`;
- }
- color: root.urgency === "critical" ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface
-
- Component.onCompleted: modelData.lock(this)
- Component.onDestruction: modelData.unlock(this)
-
- TextMetrics {
- id: metrics
-
- text: `${notifLine.modelData.summary} ${notifLine.modelData.body}`.replace(/\n/g, " ")
- font.pointSize: notifLine.font.pointSize
- font.family: notifLine.font.family
- elideWidth: notifLine.width
- elide: Text.ElideRight
- }
- }
-}
diff --git a/modules/lock/WeatherInfo.qml b/modules/lock/WeatherInfo.qml
deleted file mode 100644
index d6c25af..0000000
--- a/modules/lock/WeatherInfo.qml
+++ /dev/null
@@ -1,176 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.components
-import qs.services
-import qs.config
-import qs.utils
-import QtQuick
-import QtQuick.Layouts
-
-ColumnLayout {
- id: root
-
- required property int rootHeight
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.margins: Appearance.padding.large * 2
-
- spacing: Appearance.spacing.small
-
- Loader {
- Layout.topMargin: Appearance.padding.large * 2
- Layout.bottomMargin: -Appearance.padding.large
- Layout.alignment: Qt.AlignHCenter
-
- active: root.rootHeight > 610
- visible: active
-
- sourceComponent: StyledText {
- text: qsTr("Weather")
- color: Colours.palette.m3primary
- font.pointSize: Appearance.font.size.extraLarge
- font.weight: 500
- }
- }
-
- RowLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.large
-
- MaterialIcon {
- animate: true
- text: Weather.icon
- color: Colours.palette.m3secondary
- font.pointSize: Appearance.font.size.extraLarge * 2.5
- }
-
- ColumnLayout {
- spacing: Appearance.spacing.small
-
- StyledText {
- Layout.fillWidth: true
-
- animate: true
- text: Weather.description
- color: Colours.palette.m3secondary
- font.pointSize: Appearance.font.size.large
- font.weight: 500
- elide: Text.ElideRight
- }
-
- StyledText {
- Layout.fillWidth: true
-
- animate: true
- text: qsTr("Humidity: %1%").arg(Weather.humidity)
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: Appearance.font.size.normal
- elide: Text.ElideRight
- }
- }
-
- Loader {
- Layout.rightMargin: Appearance.padding.smaller
- active: root.width > 400
- visible: active
-
- sourceComponent: ColumnLayout {
- spacing: Appearance.spacing.small
-
- StyledText {
- Layout.fillWidth: true
-
- animate: true
- text: Weather.temp
- color: Colours.palette.m3primary
- horizontalAlignment: Text.AlignRight
- font.pointSize: Appearance.font.size.extraLarge
- font.weight: 500
- elide: Text.ElideLeft
- }
-
- StyledText {
- Layout.fillWidth: true
-
- animate: true
- text: qsTr("Feels like: %1").arg(Weather.feelsLike)
- color: Colours.palette.m3outline
- horizontalAlignment: Text.AlignRight
- font.pointSize: Appearance.font.size.smaller
- elide: Text.ElideLeft
- }
- }
- }
- }
-
- Loader {
- id: forecastLoader
-
- Layout.topMargin: Appearance.spacing.smaller
- Layout.bottomMargin: Appearance.padding.large * 2
- Layout.fillWidth: true
-
- active: root.rootHeight > 820
- visible: active
-
- sourceComponent: RowLayout {
- spacing: Appearance.spacing.large
-
- Repeater {
- model: {
- const forecast = Weather.hourlyForecast;
- const count = root.width < 320 ? 3 : root.width < 400 ? 4 : 5;
- if (!forecast)
- return Array.from({
- length: count
- }, () => null);
-
- return forecast.slice(0, count);
- }
-
- ColumnLayout {
- id: forecastHour
-
- required property var modelData
-
- Layout.fillWidth: true
- spacing: Appearance.spacing.small
-
- StyledText {
- Layout.fillWidth: true
- text: {
- const hour = forecastHour.modelData?.hour ?? 0;
- return hour > 12 ? `${(hour - 12).toString().padStart(2, "0")} PM` : `${hour.toString().padStart(2, "0")} AM`;
- }
- color: Colours.palette.m3outline
- horizontalAlignment: Text.AlignHCenter
- font.pointSize: Appearance.font.size.larger
- }
-
- MaterialIcon {
- Layout.alignment: Qt.AlignHCenter
- text: forecastHour.modelData?.icon ?? "cloud_alert"
- font.pointSize: Appearance.font.size.extraLarge * 1.5
- font.weight: 500
- }
-
- StyledText {
- Layout.alignment: Qt.AlignHCenter
- text: Config.services.useFahrenheit ? `${forecastHour.modelData?.tempF ?? 0}°F` : `${forecastHour.modelData?.tempC ?? 0}°C`
- color: Colours.palette.m3secondary
- font.pointSize: Appearance.font.size.larger
- }
- }
- }
- }
- }
-
- Timer {
- running: true
- triggeredOnStart: true
- repeat: true
- interval: 900000 // 15 minutes
- onTriggered: Weather.reload()
- }
-}
diff --git a/modules/utilities/RecordingDeleteModal.qml b/modules/utilities/RecordingDeleteModal.qml
deleted file mode 100644
index 127afe9..0000000
--- a/modules/utilities/RecordingDeleteModal.qml
+++ /dev/null
@@ -1,207 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.components
-import qs.components.controls
-import qs.components.effects
-import qs.services
-import qs.config
-import Caelestia
-import QtQuick
-import QtQuick.Layouts
-import QtQuick.Shapes
-
-Loader {
- id: root
-
- required property var props
-
- anchors.fill: parent
-
- opacity: root.props.recordingConfirmDelete ? 1 : 0
- active: opacity > 0
-
- sourceComponent: MouseArea {
- id: deleteConfirmation
-
- property string path
-
- Component.onCompleted: path = root.props.recordingConfirmDelete
-
- hoverEnabled: true
- onClicked: root.props.recordingConfirmDelete = ""
-
- Item {
- anchors.fill: parent
- anchors.margins: -Appearance.padding.large
- anchors.rightMargin: -Appearance.padding.large - Config.border.thickness
- anchors.bottomMargin: -Appearance.padding.large - Config.border.thickness
- opacity: 0.5
-
- StyledRect {
- anchors.fill: parent
- topLeftRadius: Config.border.rounding
- color: Colours.palette.m3scrim
- }
-
- Shape {
- id: shape
-
- anchors.fill: parent
- preferredRendererType: Shape.CurveRenderer
- asynchronous: true
-
- ShapePath {
- startX: -Config.border.rounding * 2
- startY: shape.height - Config.border.thickness
- strokeWidth: 0
- fillGradient: LinearGradient {
- orientation: LinearGradient.Horizontal
- x1: -Config.border.rounding * 2
-
- GradientStop {
- position: 0
- color: Qt.alpha(Colours.palette.m3scrim, 0)
- }
- GradientStop {
- position: 1
- color: Colours.palette.m3scrim
- }
- }
-
- PathLine {
- relativeX: Config.border.rounding
- relativeY: 0
- }
- PathArc {
- relativeY: -Config.border.rounding
- radiusX: Config.border.rounding
- radiusY: Config.border.rounding
- direction: PathArc.Counterclockwise
- }
- PathLine {
- relativeX: 0
- relativeY: Config.border.rounding + Config.border.thickness
- }
- PathLine {
- relativeX: -Config.border.rounding * 2
- relativeY: 0
- }
- }
-
- ShapePath {
- startX: shape.width - Config.border.rounding - Config.border.thickness
- strokeWidth: 0
- fillGradient: LinearGradient {
- orientation: LinearGradient.Vertical
- y1: -Config.border.rounding * 2
-
- GradientStop {
- position: 0
- color: Qt.alpha(Colours.palette.m3scrim, 0)
- }
- GradientStop {
- position: 1
- color: Colours.palette.m3scrim
- }
- }
-
- PathArc {
- relativeX: Config.border.rounding
- relativeY: -Config.border.rounding
- radiusX: Config.border.rounding
- radiusY: Config.border.rounding
- direction: PathArc.Counterclockwise
- }
- PathLine {
- relativeX: 0
- relativeY: -Config.border.rounding
- }
- PathLine {
- relativeX: Config.border.thickness
- relativeY: 0
- }
- PathLine {
- relativeX: 0
- }
- }
- }
- }
-
- StyledRect {
- anchors.centerIn: parent
- radius: Appearance.rounding.large
- color: Colours.palette.m3surfaceContainerHigh
-
- scale: 0
- Component.onCompleted: scale = Qt.binding(() => root.props.recordingConfirmDelete ? 1 : 0)
-
- width: Math.min(parent.width - Appearance.padding.large * 2, implicitWidth)
- implicitWidth: deleteConfirmationLayout.implicitWidth + Appearance.padding.large * 3
- implicitHeight: deleteConfirmationLayout.implicitHeight + Appearance.padding.large * 3
-
- MouseArea {
- anchors.fill: parent
- }
-
- Elevation {
- anchors.fill: parent
- radius: parent.radius
- z: -1
- level: 3
- }
-
- ColumnLayout {
- id: deleteConfirmationLayout
-
- anchors.fill: parent
- anchors.margins: Appearance.padding.large * 1.5
- spacing: Appearance.spacing.normal
-
- StyledText {
- text: qsTr("Delete recording?")
- font.pointSize: Appearance.font.size.large
- }
-
- StyledText {
- Layout.fillWidth: true
- text: qsTr("Recording '%1' will be permanently deleted.").arg(deleteConfirmation.path)
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: Appearance.font.size.small
- wrapMode: Text.WrapAtWordBoundaryOrAnywhere
- }
-
- RowLayout {
- Layout.topMargin: Appearance.spacing.normal
- Layout.alignment: Qt.AlignRight
- spacing: Appearance.spacing.normal
-
- TextButton {
- text: qsTr("Cancel")
- type: TextButton.Text
- onClicked: root.props.recordingConfirmDelete = ""
- }
-
- TextButton {
- text: qsTr("Delete")
- type: TextButton.Text
- onClicked: {
- CUtils.deleteFile(Qt.resolvedUrl(root.props.recordingConfirmDelete));
- root.props.recordingConfirmDelete = "";
- }
- }
- }
- }
-
- Behavior on scale {
- Anim {
- duration: Appearance.anim.durations.expressiveDefaultSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
- }
- }
- }
- }
-
- Behavior on opacity {
- Anim {}
- }
-}
diff --git a/modules/utilities/cards/RecordingList.qml b/modules/utilities/cards/RecordingList.qml
deleted file mode 100644
index b9d757a..0000000
--- a/modules/utilities/cards/RecordingList.qml
+++ /dev/null
@@ -1,241 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.components
-import qs.components.controls
-import qs.components.containers
-import qs.services
-import qs.config
-import qs.utils
-import Caelestia
-import Caelestia.Models
-import Quickshell
-import Quickshell.Widgets
-import QtQuick
-import QtQuick.Layouts
-
-ColumnLayout {
- id: root
-
- required property var props
- required property var visibilities
-
- spacing: 0
-
- WrapperMouseArea {
- Layout.fillWidth: true
-
- cursorShape: Qt.PointingHandCursor
- onClicked: root.props.recordingListExpanded = !root.props.recordingListExpanded
-
- RowLayout {
- spacing: Appearance.spacing.smaller
-
- MaterialIcon {
- Layout.alignment: Qt.AlignVCenter
- text: "list"
- font.pointSize: Appearance.font.size.large
- }
-
- StyledText {
- Layout.alignment: Qt.AlignVCenter
- Layout.fillWidth: true
- text: qsTr("Recordings")
- font.pointSize: Appearance.font.size.normal
- }
-
- IconButton {
- icon: root.props.recordingListExpanded ? "unfold_less" : "unfold_more"
- type: IconButton.Text
- label.animate: true
- onClicked: root.props.recordingListExpanded = !root.props.recordingListExpanded
- }
- }
- }
-
- StyledListView {
- id: list
-
- model: FileSystemModel {
- path: Paths.recsdir
- nameFilters: ["recording_*.mp4"]
- sortReverse: true
- }
-
- Layout.fillWidth: true
- Layout.rightMargin: -Appearance.spacing.small
- implicitHeight: (Appearance.font.size.larger + Appearance.padding.small) * (root.props.recordingListExpanded ? 10 : 3)
- clip: true
-
- StyledScrollBar.vertical: StyledScrollBar {
- flickable: list
- }
-
- delegate: RowLayout {
- id: recording
-
- required property FileSystemEntry modelData
- property string baseName
-
- anchors.left: list.contentItem.left
- anchors.right: list.contentItem.right
- anchors.rightMargin: Appearance.spacing.small
- spacing: Appearance.spacing.small / 2
-
- Component.onCompleted: baseName = modelData.baseName
-
- StyledText {
- Layout.fillWidth: true
- Layout.rightMargin: Appearance.spacing.small / 2
- text: {
- const time = recording.baseName;
- const matches = time.match(/^recording_(\d{4})(\d{2})(\d{2})_(\d{2})-(\d{2})-(\d{2})/);
- if (!matches)
- return time;
- const date = new Date(...matches.slice(1));
- date.setMonth(date.getMonth() - 1); // Woe (months start from 0)
- return qsTr("Recording at %1").arg(Qt.formatDateTime(date, Qt.locale()));
- }
- color: Colours.palette.m3onSurfaceVariant
- elide: Text.ElideRight
- }
-
- IconButton {
- icon: "play_arrow"
- type: IconButton.Text
- onClicked: {
- root.visibilities.utilities = false;
- root.visibilities.sidebar = false;
- Quickshell.execDetached(["app2unit", "--", ...Config.general.apps.playback, recording.modelData.path]);
- }
- }
-
- IconButton {
- icon: "folder"
- type: IconButton.Text
- onClicked: {
- root.visibilities.utilities = false;
- root.visibilities.sidebar = false;
- Quickshell.execDetached(["app2unit", "--", ...Config.general.apps.explorer, recording.modelData.path]);
- }
- }
-
- IconButton {
- icon: "delete_forever"
- type: IconButton.Text
- label.color: Colours.palette.m3error
- stateLayer.color: Colours.palette.m3error
- onClicked: root.props.recordingConfirmDelete = recording.modelData.path
- }
- }
-
- add: Transition {
- Anim {
- property: "opacity"
- from: 0
- to: 1
- }
- Anim {
- property: "scale"
- from: 0.5
- to: 1
- }
- }
-
- remove: Transition {
- Anim {
- property: "opacity"
- to: 0
- }
- Anim {
- property: "scale"
- to: 0.5
- }
- }
-
- displaced: Transition {
- Anim {
- properties: "opacity,scale"
- to: 1
- }
- Anim {
- property: "y"
- }
- }
-
- Loader {
- anchors.centerIn: parent
-
- opacity: list.count === 0 ? 1 : 0
- active: opacity > 0
-
- sourceComponent: ColumnLayout {
- spacing: Appearance.spacing.small
-
- MaterialIcon {
- Layout.alignment: Qt.AlignHCenter
- text: "scan_delete"
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.extraLarge
-
- opacity: root.props.recordingListExpanded ? 1 : 0
- scale: root.props.recordingListExpanded ? 1 : 0
- Layout.preferredHeight: root.props.recordingListExpanded ? implicitHeight : 0
-
- Behavior on opacity {
- Anim {}
- }
-
- Behavior on scale {
- Anim {}
- }
-
- Behavior on Layout.preferredHeight {
- Anim {}
- }
- }
-
- RowLayout {
- spacing: Appearance.spacing.smaller
-
- MaterialIcon {
- Layout.alignment: Qt.AlignHCenter
- text: "scan_delete"
- color: Colours.palette.m3outline
-
- opacity: !root.props.recordingListExpanded ? 1 : 0
- scale: !root.props.recordingListExpanded ? 1 : 0
- Layout.preferredWidth: !root.props.recordingListExpanded ? implicitWidth : 0
-
- Behavior on opacity {
- Anim {}
- }
-
- Behavior on scale {
- Anim {}
- }
-
- Behavior on Layout.preferredWidth {
- Anim {}
- }
- }
-
- StyledText {
- text: qsTr("No recordings found")
- color: Colours.palette.m3outline
- }
- }
- }
-
- Behavior on opacity {
- Anim {}
- }
- }
-
- Behavior on implicitHeight {
- Anim {
- duration: Appearance.anim.durations.expressiveDefaultSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
- }
- }
- }
-}